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 tok := p.peek()
86
87 if tok.Kind != kind {
88 return false
89 }
90 p.next()
91 return true
92}
93
94func (p *parser) unexpectedError() {
95 p.unexpectedToken(p.peek())
96}
97
98func (p *parser) unexpectedToken(tok lexer.Token) {
99 p.error(tok, "Unexpected %s", tok.String())
100}
101
102func (p *parser) many(start lexer.Type, end lexer.Type, cb func()) {
103 hasDef := p.skip(start)
104 if !hasDef {
105 return
106 }
107
108 for p.peek().Kind != end && p.err == nil {
109 cb()
110 }
111 p.next()
112}