123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832 |
- package parser
- import (
- "fmt"
- "devt.de/krotik/common/errorutil"
- )
- var astNodeMapValues map[string]*ASTNode
- var astNodeMapTokens map[LexTokenID]*ASTNode
- var astNodeMapIgnoredValues map[string]*ASTNode
- func init() {
- astNodeMapValues = map[string]*ASTNode{
- "query": {NodeOperationDefinition, nil, nil, nil, 0, ndOperationDefinition, nil},
- "mutation": {NodeOperationDefinition, nil, nil, nil, 0, ndOperationDefinition, nil},
- "subscription": {NodeOperationDefinition, nil, nil, nil, 0, ndOperationDefinition, nil},
- "fragment": {NodeFragmentDefinition, nil, nil, nil, 0, ndFragmentDefinition, nil},
- "{": {NodeSelectionSet, nil, nil, nil, 0, ndSelectionSet, nil},
- "(": {NodeArguments, nil, nil, nil, 0, ndArgsOrVarDef, nil},
- "@": {NodeDirectives, nil, nil, nil, 0, ndDirectives, nil},
- "$": {NodeVariable, nil, nil, nil, 0, ndVariable, nil},
- "...": {NodeFragmentSpread, nil, nil, nil, 0, ndFragmentSpread, nil},
- "[": {NodeListValue, nil, nil, nil, 0, ndListValue, nil},
-
- "}": {"", nil, nil, nil, 0, nil, nil},
- ":": {"", nil, nil, nil, 0, nil, nil},
- ")": {"", nil, nil, nil, 0, nil, nil},
- "=": {"", nil, nil, nil, 0, nil, nil},
- "]": {"", nil, nil, nil, 0, nil, nil},
- }
- astNodeMapTokens = map[LexTokenID]*ASTNode{
- TokenName: {NodeName, nil, nil, nil, 0, ndTerm, nil},
- TokenIntValue: {NodeValue, nil, nil, nil, 0, ndTerm, nil},
- TokenStringValue: {NodeValue, nil, nil, nil, 0, ndTerm, nil},
- TokenFloatValue: {NodeValue, nil, nil, nil, 0, ndTerm, nil},
- TokenEOF: {NodeEOF, nil, nil, nil, 0, ndTerm, nil},
- }
- }
- type parser struct {
- name string
- node *ASTNode
- tokens chan LexToken
- rp RuntimeProvider
-
- isVarDef bool
- isValue bool
- }
- func Parse(name string, input string) (*ASTNode, error) {
- return ParseWithRuntime(name, input, nil)
- }
- func ParseWithRuntime(name string, input string, rp RuntimeProvider) (*ASTNode, error) {
- p := &parser{name, nil, Lex(name, input), rp, false, false}
- node, err := p.next()
- if err != nil {
- return nil, err
- }
- p.node = node
- doc := newAstNode(NodeDocument, p, node.Token)
- for err == nil && p.node.Name != NodeEOF {
- if node, err = p.run(0); err == nil {
- if node != nil && node.Name == NodeSelectionSet {
-
- if len(doc.Children) == 0 {
- ed := newAstNode(NodeExecutableDefinition, p, node.Token)
- doc.Children = append(doc.Children, ed)
- od := newAstNode(NodeOperationDefinition, p, node.Token)
- ed.Children = append(ed.Children, od)
- od.Children = append(od.Children, node)
- } else {
- return nil, p.newParserError(ErrMultipleShorthand,
- node.Token.String(), *node.Token)
- }
- } else {
- ed := newAstNode(NodeExecutableDefinition, p, node.Token)
- doc.Children = append(doc.Children, ed)
- ed.Children = append(ed.Children, node)
- }
- }
- }
- if err == nil {
- return doc, nil
- }
- return nil, err
- }
- func (p *parser) run(rightBinding int) (*ASTNode, error) {
- var err error
- var left *ASTNode
- n := p.node
-
- if p.node, err = p.next(); err == nil {
-
- if n.nullDenotation == nil {
- return nil, p.newParserError(ErrImpossibleNullDenotation, p.node.Token.Val, *p.node.Token)
- }
- left, err = n.nullDenotation(p, n)
- }
- if err != nil {
- return nil, err
- }
-
-
- errorutil.AssertTrue(rightBinding == p.node.binding, "Unexpected right binding")
- return left, nil
- }
- func (p *parser) next() (*ASTNode, error) {
- token, more := <-p.tokens
- if !more {
-
- return nil, p.newParserError(ErrUnexpectedEnd, "", token)
- } else if token.ID == TokenError {
-
- return nil, p.newParserError(ErrLexicalError, token.Val, token)
- } else if node, ok := astNodeMapValues[token.Val]; ok &&
- (!p.isValue || token.ID == TokenPunctuator) && token.ID != TokenStringValue {
-
- return node.instance(p, &token), nil
- } else if node, ok := astNodeMapTokens[token.ID]; ok {
- return node.instance(p, &token), nil
- }
- return nil, p.newParserError(ErrUnknownToken, fmt.Sprintf("id:%v (%v)", token.ID, token), token)
- }
- func ndTerm(p *parser, self *ASTNode) (*ASTNode, error) {
- return self, nil
- }
- func ndVariable(p *parser, self *ASTNode) (*ASTNode, error) {
- var err error
- if p.node.Token.ID == TokenName {
-
- self.Token = p.node.Token
- p.node, err = p.next()
- }
- return self, err
- }
- func ndListValue(p *parser, self *ASTNode) (*ASTNode, error) {
- var current *ASTNode
- var err error
- for p.node.Token.ID != TokenEOF && p.node.Token.Val != "]" {
-
- if current, err = parseValue(p); err == nil {
- self.Children = append(self.Children, current)
- } else {
- return nil, err
- }
- }
- return self, skipToken(p, "]")
- }
- func ndInputObject(p *parser, self *ASTNode) (*ASTNode, error) {
- var current *ASTNode
- var err error
- changeAstNode(self, NodeObjectValue, p)
- for p.node.Token.ID != TokenEOF && p.node.Token.Val != "}" {
- if current, err = p.run(0); err == nil {
- if current.Name != NodeName {
- err = p.newParserError(ErrNameExpected,
- current.Token.String(), *current.Token)
- } else {
- of := newAstNode(NodeObjectField, p, current.Token)
- self.Children = append(self.Children, of)
- if err = skipToken(p, ":"); err == nil {
-
- if current, err = parseValue(p); err == nil {
- of.Children = append(of.Children, current)
- }
- }
- }
- }
- if err != nil {
- return nil, err
- }
- }
- return self, skipToken(p, "}")
- }
- func ndFragmentSpread(p *parser, self *ASTNode) (*ASTNode, error) {
- var current, expectedNameNode *ASTNode
- var err error
- if p.node.Token.Val == "on" {
-
- onToken := p.node.Token
- p.node, err = p.next()
- if err == nil && p.node.Name == NodeName {
-
- changeAstNode(p.node, NodeTypeCondition, p)
- self.Children = append(self.Children, p.node)
- p.node, err = p.next()
- } else {
- self.Token = onToken
- }
- } else if p.node.Token.ID == TokenName {
-
- self.Token = p.node.Token
- p.node, err = p.next()
- } else {
- expectedNameNode = p.node
- }
- if err == nil && p.node.Token.Val == "@" {
-
- if current, err = p.run(0); err == nil {
- self.Children = append(self.Children, current)
- }
- }
- if err == nil && p.node.Token.Val == "{" {
-
- if current, err = p.run(0); err == nil {
- self.Children = append(self.Children, current)
-
- changeAstNode(self, NodeInlineFragment, p)
- }
- } else if err == nil && expectedNameNode != nil {
-
-
- err = p.newParserError(ErrNameExpected,
- expectedNameNode.Token.String(), *expectedNameNode.Token)
- }
- return self, err
- }
- func ndOperationDefinition(p *parser, self *ASTNode) (*ASTNode, error) {
- var err error
- var current = p.node
- ot := newAstNode(NodeOperationType, p, self.Token)
- self.Children = append(self.Children, ot)
- if p.node.Token.ID == TokenName {
-
- self.Children = append(self.Children, p.node)
- p.node, err = p.next()
- }
- if err == nil && p.node.Token.Val == "(" {
-
- p.isVarDef = true
- if current, err = p.run(0); err == nil {
- self.Children = append(self.Children, current)
- }
- p.isVarDef = false
- }
- if err == nil && p.node.Token.Val == "@" {
-
- if current, err = p.run(0); err == nil {
- self.Children = append(self.Children, current)
- }
- }
- if err == nil && p.node.Token.Val == "{" {
-
- if current, err = p.run(0); err == nil {
- self.Children = append(self.Children, current)
- }
- } else if err == nil {
-
- err = p.newParserError(ErrSelectionSetExpected,
- current.Token.String(), *current.Token)
- }
- return self, err
- }
- func ndFragmentDefinition(p *parser, self *ASTNode) (*ASTNode, error) {
- var err error
- var current *ASTNode
- if p.node.Token.ID == TokenName {
-
- changeAstNode(p.node, NodeFragmentName, p)
- self.Children = append(self.Children, p.node)
- p.node, err = p.next()
- } else {
- err = p.newParserError(ErrNameExpected,
- p.node.Token.String(), *p.node.Token)
- }
- if err == nil {
- if p.node.Token.Val != "on" {
-
- err = p.newParserError(ErrOnExpected,
- p.node.Token.String(), *p.node.Token)
- } else {
- p.node, err = p.next()
- if err == nil {
- if p.node.Token.ID == TokenName {
-
- changeAstNode(p.node, NodeTypeCondition, p)
- self.Children = append(self.Children, p.node)
- p.node, err = p.next()
- } else {
- err = p.newParserError(ErrNameExpected,
- p.node.Token.String(), *p.node.Token)
- }
- }
- }
- }
- if err == nil && p.node.Token.Val == "@" {
-
- if current, err = p.run(0); err == nil {
- self.Children = append(self.Children, current)
- }
- }
- if err == nil && p.node.Token.Val == "{" {
-
- if current, err = p.run(0); err == nil {
- self.Children = append(self.Children, current)
- }
- } else if err == nil {
-
- err = p.newParserError(ErrSelectionSetExpected,
- p.node.Token.String(), *p.node.Token)
- }
- return self, err
- }
- func ndSelectionSet(p *parser, self *ASTNode) (*ASTNode, error) {
- var current *ASTNode
- var err error
-
- if p.isValue {
- return ndInputObject(p, self)
- }
- for p.node.Token.ID != TokenEOF && p.node.Token.Val != "}" {
- if p.node.Token.Val == "..." {
-
- if current, err = p.run(0); err == nil {
- self.Children = append(self.Children, current)
- }
- } else {
- err = acceptFieldExpression(p, self)
- }
- if err != nil {
- return nil, err
- }
- }
- return self, skipToken(p, "}")
- }
- func acceptFieldExpression(p *parser, self *ASTNode) error {
- var err error
-
- fe := newAstNode(NodeField, p, p.node.Token)
- self.Children = append(self.Children, fe)
- current := p.node
- if p.node, err = p.next(); err == nil && p.node.Name != NodeEOF {
- if p.node.Token.Val == ":" {
-
- changeAstNode(current, NodeAlias, p)
-
- fe.Children = append(fe.Children, current)
- if p.node, err = p.next(); err == nil && p.node.Name != NodeEOF {
- current = p.node
- p.node, err = p.next()
- }
- }
- if err == nil && p.node.Name != NodeEOF {
-
- if current.Name == NodeName {
-
- fe.Children = append(fe.Children, current)
- } else {
- err = p.newParserError(ErrNameExpected,
- current.Token.String(), *current.Token)
- }
- if err == nil && p.node.Token.Val == "(" {
-
- if current, err = p.run(0); err == nil {
- fe.Children = append(fe.Children, current)
- }
- }
- if err == nil && p.node.Token.Val == "@" {
-
- if current, err = p.run(0); err == nil {
- fe.Children = append(fe.Children, current)
- }
- }
- if err == nil && p.node.Token.Val == "{" {
-
- if current, err = p.run(0); err == nil {
- fe.Children = append(fe.Children, current)
- }
- }
- }
- }
- return err
- }
- func ndArgsOrVarDef(p *parser, self *ASTNode) (*ASTNode, error) {
- var err error
- var args, arg, current *ASTNode
-
- if p.isVarDef {
- args = newAstNode(NodeVariableDefinitions, p, p.node.Token)
- } else {
- args = newAstNode(NodeArguments, p, p.node.Token)
- }
- for err == nil && p.node.Token.ID != TokenEOF && p.node.Token.Val != ")" {
- if p.isVarDef {
- arg = newAstNode(NodeVariableDefinition, p, p.node.Token)
- } else {
- arg = newAstNode(NodeArgument, p, p.node.Token)
- }
- args.Children = append(args.Children, arg)
- if current, err = p.run(0); err == nil {
- if !p.isVarDef && current.Name != NodeName {
- err = p.newParserError(ErrNameExpected,
- current.Token.String(), *current.Token)
- } else if p.isVarDef && current.Name != NodeVariable {
- err = p.newParserError(ErrVariableExpected,
- current.Token.String(), *current.Token)
- } else {
-
- arg.Children = append(arg.Children, current)
- if err = skipToken(p, ":"); err == nil {
-
- if p.isVarDef {
- if current, err = p.run(0); err == nil {
- changeAstNode(current, NodeType, p)
- arg.Children = append(arg.Children, current)
- }
- } else {
- if current, err = parseValue(p); err == nil {
- arg.Children = append(arg.Children, current)
- }
- }
- if err == nil && p.isVarDef && p.node.Token.Val == "=" {
- skipToken(p, "=")
-
- if current, err = parseValue(p); err == nil {
- changeAstNode(current, NodeDefaultValue, p)
- arg.Children = append(arg.Children, current)
- }
- }
- }
- }
- }
- }
-
- if err == nil {
- return args, skipToken(p, ")")
- }
- return nil, err
- }
- func parseValue(p *parser) (*ASTNode, error) {
- p.isValue = true
- current, err := p.run(0)
- p.isValue = false
- if err == nil {
- if current.Token.Val == "true" ||
- current.Token.Val == "false" ||
- current.Token.Val == "null" ||
- current.Token.ID == TokenIntValue ||
- current.Token.ID == TokenFloatValue ||
- current.Token.ID == TokenStringValue {
-
- changeAstNode(current, NodeValue, p)
- } else if current.Name == NodeName {
-
- changeAstNode(current, NodeEnumValue, p)
- } else {
-
- errorutil.AssertTrue(current.Name == NodeVariable ||
- current.Name == NodeListValue ||
- current.Name == NodeObjectValue, fmt.Sprint("Unexpected value node:", current))
- }
- if err == nil {
- return current, err
- }
- }
- return nil, err
- }
- func ndDirectives(p *parser, self *ASTNode) (*ASTNode, error) {
- var err error
- var current *ASTNode
- dir := newAstNode(NodeDirective, p, p.node.Token)
- if err = acceptChild(p, dir, TokenName); err == nil {
- if current, err = p.run(0); err == nil {
- dir.Children = append(dir.Children, current)
- self.Children = append(self.Children, dir)
- if p.node.Token.Val == "@" {
- if p.node, err = p.next(); err == nil {
- return ndDirectives(p, self)
- }
- }
- }
- }
- return self, err
- }
- func skipToken(p *parser, validValues ...string) error {
- var err error
- canSkip := func(val string) bool {
- for _, i := range validValues {
- if i == val {
- return true
- }
- }
- return false
- }
- if !canSkip(p.node.Token.Val) {
- if p.node.Token.ID == TokenEOF {
- return p.newParserError(ErrUnexpectedEnd, "", *p.node.Token)
- }
- return p.newParserError(ErrUnexpectedToken, p.node.Token.Val, *p.node.Token)
- }
-
-
- p.node, err = p.next()
- return err
- }
- func acceptChild(p *parser, self *ASTNode, id LexTokenID) error {
- var err error
- current := p.node
- if p.node, err = p.next(); err == nil {
- if current.Token.ID == id {
- self.Children = append(self.Children, current)
- } else {
- err = p.newParserError(ErrUnexpectedToken, current.Token.Val, *current.Token)
- }
- }
- return err
- }
|