parser.go

  1package parser
  2
  3import (
  4	"strconv"
  5
  6	"github.com/vektah/gqlparser/ast"
  7	"github.com/vektah/gqlparser/gqlerror"
  8	"github.com/vektah/gqlparser/lexer"
  9)
 10
 11type parser struct {
 12	lexer lexer.Lexer
 13	err   *gqlerror.Error
 14
 15	peeked    bool
 16	peekToken lexer.Token
 17	peekError *gqlerror.Error
 18
 19	prev lexer.Token
 20}
 21
 22func (p *parser) peekPos() *ast.Position {
 23	if p.err != nil {
 24		return nil
 25	}
 26
 27	peek := p.peek()
 28	return &peek.Pos
 29}
 30
 31func (p *parser) peek() lexer.Token {
 32	if p.err != nil {
 33		return p.prev
 34	}
 35
 36	if !p.peeked {
 37		p.peekToken, p.peekError = p.lexer.ReadToken()
 38		p.peeked = true
 39	}
 40
 41	return p.peekToken
 42}
 43
 44func (p *parser) error(tok lexer.Token, format string, args ...interface{}) {
 45	if p.err != nil {
 46		return
 47	}
 48	p.err = gqlerror.ErrorLocf(tok.Pos.Src.Name, tok.Pos.Line, tok.Pos.Column, format, args...)
 49}
 50
 51func (p *parser) next() lexer.Token {
 52	if p.err != nil {
 53		return p.prev
 54	}
 55	if p.peeked {
 56		p.peeked = false
 57		p.prev, p.err = p.peekToken, p.peekError
 58	} else {
 59		p.prev, p.err = p.lexer.ReadToken()
 60	}
 61	return p.prev
 62}
 63
 64func (p *parser) expectKeyword(value string) lexer.Token {
 65	tok := p.peek()
 66	if tok.Kind == lexer.Name && tok.Value == value {
 67		return p.next()
 68	}
 69
 70	p.error(tok, "Expected %s, found %s", strconv.Quote(value), tok.String())
 71	return tok
 72}
 73
 74func (p *parser) expect(kind lexer.Type) lexer.Token {
 75	tok := p.peek()
 76	if tok.Kind == kind {
 77		return p.next()
 78	}
 79
 80	p.error(tok, "Expected %s, found %s", kind, tok.Kind.String())
 81	return tok
 82}
 83
 84func (p *parser) skip(kind lexer.Type) bool {
 85	if p.err != nil {
 86		return false
 87	}
 88
 89	tok := p.peek()
 90
 91	if tok.Kind != kind {
 92		return false
 93	}
 94	p.next()
 95	return true
 96}
 97
 98func (p *parser) unexpectedError() {
 99	p.unexpectedToken(p.peek())
100}
101
102func (p *parser) unexpectedToken(tok lexer.Token) {
103	p.error(tok, "Unexpected %s", tok.String())
104}
105
106func (p *parser) many(start lexer.Type, end lexer.Type, cb func()) {
107	hasDef := p.skip(start)
108	if !hasDef {
109		return
110	}
111
112	for p.peek().Kind != end && p.err == nil {
113		cb()
114	}
115	p.next()
116}
117
118func (p *parser) some(start lexer.Type, end lexer.Type, cb func()) {
119	hasDef := p.skip(start)
120	if !hasDef {
121		return
122	}
123
124	called := false
125	for p.peek().Kind != end && p.err == nil {
126		called = true
127		cb()
128	}
129
130	if !called {
131		p.error(p.peek(), "expected at least one definition, found %s", p.peek().Kind.String())
132		return
133	}
134
135	p.next()
136}