...

Source file src/github.com/vektah/gqlparser/parser/query.go

Documentation: github.com/vektah/gqlparser/parser

     1  package parser
     2  
     3  import (
     4  	"github.com/vektah/gqlparser/gqlerror"
     5  	"github.com/vektah/gqlparser/lexer"
     6  
     7  	. "github.com/vektah/gqlparser/ast"
     8  )
     9  
    10  func ParseQuery(source *Source) (*QueryDocument, *gqlerror.Error) {
    11  	p := parser{
    12  		lexer: lexer.New(source),
    13  	}
    14  	return p.parseQueryDocument(), p.err
    15  }
    16  
    17  func (p *parser) parseQueryDocument() *QueryDocument {
    18  	var doc QueryDocument
    19  	for p.peek().Kind != lexer.EOF {
    20  		if p.err != nil {
    21  			return &doc
    22  		}
    23  		doc.Position = p.peekPos()
    24  		switch p.peek().Kind {
    25  		case lexer.Name:
    26  			switch p.peek().Value {
    27  			case "query", "mutation", "subscription":
    28  				doc.Operations = append(doc.Operations, p.parseOperationDefinition())
    29  			case "fragment":
    30  				doc.Fragments = append(doc.Fragments, p.parseFragmentDefinition())
    31  			default:
    32  				p.unexpectedError()
    33  			}
    34  		case lexer.BraceL:
    35  			doc.Operations = append(doc.Operations, p.parseOperationDefinition())
    36  		default:
    37  			p.unexpectedError()
    38  		}
    39  	}
    40  
    41  	return &doc
    42  }
    43  
    44  func (p *parser) parseOperationDefinition() *OperationDefinition {
    45  	if p.peek().Kind == lexer.BraceL {
    46  		return &OperationDefinition{
    47  			Position:     p.peekPos(),
    48  			Operation:    Query,
    49  			SelectionSet: p.parseRequiredSelectionSet(),
    50  		}
    51  	}
    52  
    53  	var od OperationDefinition
    54  	od.Position = p.peekPos()
    55  	od.Operation = p.parseOperationType()
    56  
    57  	if p.peek().Kind == lexer.Name {
    58  		od.Name = p.next().Value
    59  	}
    60  
    61  	od.VariableDefinitions = p.parseVariableDefinitions()
    62  	od.Directives = p.parseDirectives(false)
    63  	od.SelectionSet = p.parseRequiredSelectionSet()
    64  
    65  	return &od
    66  }
    67  
    68  func (p *parser) parseOperationType() Operation {
    69  	tok := p.next()
    70  	switch tok.Value {
    71  	case "query":
    72  		return Query
    73  	case "mutation":
    74  		return Mutation
    75  	case "subscription":
    76  		return Subscription
    77  	}
    78  	p.unexpectedToken(tok)
    79  	return ""
    80  }
    81  
    82  func (p *parser) parseVariableDefinitions() VariableDefinitionList {
    83  	var defs []*VariableDefinition
    84  	p.many(lexer.ParenL, lexer.ParenR, func() {
    85  		defs = append(defs, p.parseVariableDefinition())
    86  	})
    87  
    88  	return defs
    89  }
    90  
    91  func (p *parser) parseVariableDefinition() *VariableDefinition {
    92  	var def VariableDefinition
    93  	def.Position = p.peekPos()
    94  	def.Variable = p.parseVariable()
    95  
    96  	p.expect(lexer.Colon)
    97  
    98  	def.Type = p.parseTypeReference()
    99  
   100  	if p.skip(lexer.Equals) {
   101  		def.DefaultValue = p.parseValueLiteral(true)
   102  	}
   103  
   104  	return &def
   105  }
   106  
   107  func (p *parser) parseVariable() string {
   108  	p.expect(lexer.Dollar)
   109  	return p.parseName()
   110  }
   111  
   112  func (p *parser) parseOptionalSelectionSet() SelectionSet {
   113  	var selections []Selection
   114  	p.some(lexer.BraceL, lexer.BraceR, func() {
   115  		selections = append(selections, p.parseSelection())
   116  	})
   117  
   118  	return SelectionSet(selections)
   119  }
   120  
   121  func (p *parser) parseRequiredSelectionSet() SelectionSet {
   122  	if p.peek().Kind != lexer.BraceL {
   123  		p.error(p.peek(), "Expected %s, found %s", lexer.BraceL, p.peek().Kind.String())
   124  		return nil
   125  	}
   126  
   127  	var selections []Selection
   128  	p.some(lexer.BraceL, lexer.BraceR, func() {
   129  		selections = append(selections, p.parseSelection())
   130  	})
   131  
   132  	return SelectionSet(selections)
   133  }
   134  
   135  func (p *parser) parseSelection() Selection {
   136  	if p.peek().Kind == lexer.Spread {
   137  		return p.parseFragment()
   138  	}
   139  	return p.parseField()
   140  }
   141  
   142  func (p *parser) parseField() *Field {
   143  	var field Field
   144  	field.Position = p.peekPos()
   145  	field.Alias = p.parseName()
   146  
   147  	if p.skip(lexer.Colon) {
   148  		field.Name = p.parseName()
   149  	} else {
   150  		field.Name = field.Alias
   151  	}
   152  
   153  	field.Arguments = p.parseArguments(false)
   154  	field.Directives = p.parseDirectives(false)
   155  	if p.peek().Kind == lexer.BraceL {
   156  		field.SelectionSet = p.parseOptionalSelectionSet()
   157  	}
   158  
   159  	return &field
   160  }
   161  
   162  func (p *parser) parseArguments(isConst bool) ArgumentList {
   163  	var arguments ArgumentList
   164  	p.many(lexer.ParenL, lexer.ParenR, func() {
   165  		arguments = append(arguments, p.parseArgument(isConst))
   166  	})
   167  
   168  	return arguments
   169  }
   170  
   171  func (p *parser) parseArgument(isConst bool) *Argument {
   172  	arg := Argument{}
   173  	arg.Position = p.peekPos()
   174  	arg.Name = p.parseName()
   175  	p.expect(lexer.Colon)
   176  
   177  	arg.Value = p.parseValueLiteral(isConst)
   178  	return &arg
   179  }
   180  
   181  func (p *parser) parseFragment() Selection {
   182  	p.expect(lexer.Spread)
   183  
   184  	if peek := p.peek(); peek.Kind == lexer.Name && peek.Value != "on" {
   185  		return &FragmentSpread{
   186  			Position:   p.peekPos(),
   187  			Name:       p.parseFragmentName(),
   188  			Directives: p.parseDirectives(false),
   189  		}
   190  	}
   191  
   192  	var def InlineFragment
   193  	def.Position = p.peekPos()
   194  	if p.peek().Value == "on" {
   195  		p.next() // "on"
   196  
   197  		def.TypeCondition = p.parseName()
   198  	}
   199  
   200  	def.Directives = p.parseDirectives(false)
   201  	def.SelectionSet = p.parseRequiredSelectionSet()
   202  	return &def
   203  }
   204  
   205  func (p *parser) parseFragmentDefinition() *FragmentDefinition {
   206  	var def FragmentDefinition
   207  	def.Position = p.peekPos()
   208  	p.expectKeyword("fragment")
   209  
   210  	def.Name = p.parseFragmentName()
   211  	def.VariableDefinition = p.parseVariableDefinitions()
   212  
   213  	p.expectKeyword("on")
   214  
   215  	def.TypeCondition = p.parseName()
   216  	def.Directives = p.parseDirectives(false)
   217  	def.SelectionSet = p.parseRequiredSelectionSet()
   218  	return &def
   219  }
   220  
   221  func (p *parser) parseFragmentName() string {
   222  	if p.peek().Value == "on" {
   223  		p.unexpectedError()
   224  		return ""
   225  	}
   226  
   227  	return p.parseName()
   228  }
   229  
   230  func (p *parser) parseValueLiteral(isConst bool) *Value {
   231  	token := p.peek()
   232  
   233  	var kind ValueKind
   234  	switch token.Kind {
   235  	case lexer.BracketL:
   236  		return p.parseList(isConst)
   237  	case lexer.BraceL:
   238  		return p.parseObject(isConst)
   239  	case lexer.Dollar:
   240  		if isConst {
   241  			p.unexpectedError()
   242  			return nil
   243  		}
   244  		return &Value{Position: &token.Pos, Raw: p.parseVariable(), Kind: Variable}
   245  	case lexer.Int:
   246  		kind = IntValue
   247  	case lexer.Float:
   248  		kind = FloatValue
   249  	case lexer.String:
   250  		kind = StringValue
   251  	case lexer.BlockString:
   252  		kind = BlockValue
   253  	case lexer.Name:
   254  		switch token.Value {
   255  		case "true", "false":
   256  			kind = BooleanValue
   257  		case "null":
   258  			kind = NullValue
   259  		default:
   260  			kind = EnumValue
   261  		}
   262  	default:
   263  		p.unexpectedError()
   264  		return nil
   265  	}
   266  
   267  	p.next()
   268  
   269  	return &Value{Position: &token.Pos, Raw: token.Value, Kind: kind}
   270  }
   271  
   272  func (p *parser) parseList(isConst bool) *Value {
   273  	var values ChildValueList
   274  	pos := p.peekPos()
   275  	p.many(lexer.BracketL, lexer.BracketR, func() {
   276  		values = append(values, &ChildValue{Value: p.parseValueLiteral(isConst)})
   277  	})
   278  
   279  	return &Value{Children: values, Kind: ListValue, Position: pos}
   280  }
   281  
   282  func (p *parser) parseObject(isConst bool) *Value {
   283  	var fields ChildValueList
   284  	pos := p.peekPos()
   285  	p.many(lexer.BraceL, lexer.BraceR, func() {
   286  		fields = append(fields, p.parseObjectField(isConst))
   287  	})
   288  
   289  	return &Value{Children: fields, Kind: ObjectValue, Position: pos}
   290  }
   291  
   292  func (p *parser) parseObjectField(isConst bool) *ChildValue {
   293  	field := ChildValue{}
   294  	field.Position = p.peekPos()
   295  	field.Name = p.parseName()
   296  
   297  	p.expect(lexer.Colon)
   298  
   299  	field.Value = p.parseValueLiteral(isConst)
   300  	return &field
   301  }
   302  
   303  func (p *parser) parseDirectives(isConst bool) []*Directive {
   304  	var directives []*Directive
   305  
   306  	for p.peek().Kind == lexer.At {
   307  		if p.err != nil {
   308  			break
   309  		}
   310  		directives = append(directives, p.parseDirective(isConst))
   311  	}
   312  	return directives
   313  }
   314  
   315  func (p *parser) parseDirective(isConst bool) *Directive {
   316  	p.expect(lexer.At)
   317  
   318  	return &Directive{
   319  		Position:  p.peekPos(),
   320  		Name:      p.parseName(),
   321  		Arguments: p.parseArguments(isConst),
   322  	}
   323  }
   324  
   325  func (p *parser) parseTypeReference() *Type {
   326  	var typ Type
   327  
   328  	if p.skip(lexer.BracketL) {
   329  		typ.Position = p.peekPos()
   330  		typ.Elem = p.parseTypeReference()
   331  		p.expect(lexer.BracketR)
   332  	} else {
   333  		typ.Position = p.peekPos()
   334  		typ.NamedType = p.parseName()
   335  	}
   336  
   337  	if p.skip(lexer.Bang) {
   338  		typ.Position = p.peekPos()
   339  		typ.NonNull = true
   340  	}
   341  	return &typ
   342  }
   343  
   344  func (p *parser) parseName() string {
   345  	token := p.expect(lexer.Name)
   346  
   347  	return token.Value
   348  }
   349  

View as plain text