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}