Very experimental GraphQL parser. It's mostly reusing the lexer from GraphQL-Ruby, but the parser is a hand-written recursive descent parser.
I want to target this at server side applications, so the parser eliminates some nice stuff for humans (namely line / column information, and it throws away comments).
Right now this code:
- Doesn't know how to execute anything. It just gives you an AST
- Isn't used anywhere (except in your heart, *but hopefully in production someday!)
You can get an AST like this:
ast = TinyGQL.parse "{ cool }"
The AST is iterable, so you can use the each method:
ast = TinyGQL.parse "{ cool }"
ast.each do |node|
p node.class
end
Nodes have predicate methods, so if you want to find particular nodes just use a predicate:
ast = TinyGQL.parse "{ cool }"
p ast.find_all(&:field?).map(&:name) # => ["cool"]
If you need a more advanced way to iterate nodes, you can use a visitor:
class Viz
include TinyGQL::Visitors::Visitor
def handle_field obj
p obj.name # => cool
super
end
end
ast = TinyGQL.parse "{ cool }"
ast.accept(Viz.new)
If you would like a functional way to collect data from the tree, use the Fold
module:
module Fold
extend TinyGQL::Visitors::Fold
def self.handle_field obj, seed
super(obj, seed + [obj.name])
end
end
ast = TinyGQL.parse "{ neat { cool } }"
p ast.fold(Fold, []) # => ["neat", "cool"]
Nodes store their position in the source GraphQL document.
If you'd like to extract the line number of the node, you'll need to keep a reference to the document and pass it to the line
method on the node:
doc = <<-eod
mutation {
likeStory(sturyID: 12345) {
story {
likeCount
}
}
}
eod
parser = TinyGQL::Parser.new doc
ast = parser.parse
ast.find_all(&:field?).each { |node|
p node.name => node.line(doc)
}
I've licensed this code as Apache 2.0, but the lexer is from GraphQL-Ruby and is under the MIT license.