...
1 package parser
2
3 import (
4 "strconv"
5
6 "github.com/vektah/gqlparser/v2/ast"
7 "github.com/vektah/gqlparser/v2/gqlerror"
8 "github.com/vektah/gqlparser/v2/lexer"
9 )
10
11 type parser struct {
12 lexer lexer.Lexer
13 err error
14
15 peeked bool
16 peekToken lexer.Token
17 peekError error
18
19 prev lexer.Token
20
21 comment *ast.CommentGroup
22 commentConsuming bool
23 }
24
25 func (p *parser) consumeComment() (*ast.Comment, bool) {
26 if p.err != nil {
27 return nil, false
28 }
29 tok := p.peek()
30 if tok.Kind != lexer.Comment {
31 return nil, false
32 }
33 p.next()
34 return &ast.Comment{
35 Value: tok.Value,
36 Position: &tok.Pos,
37 }, true
38 }
39
40 func (p *parser) consumeCommentGroup() {
41 if p.err != nil {
42 return
43 }
44 if p.commentConsuming {
45 return
46 }
47 p.commentConsuming = true
48
49 var comments []*ast.Comment
50 for {
51 comment, ok := p.consumeComment()
52 if !ok {
53 break
54 }
55 comments = append(comments, comment)
56 }
57
58 p.comment = &ast.CommentGroup{List: comments}
59 p.commentConsuming = false
60 }
61
62 func (p *parser) peekPos() *ast.Position {
63 if p.err != nil {
64 return nil
65 }
66
67 peek := p.peek()
68 return &peek.Pos
69 }
70
71 func (p *parser) peek() lexer.Token {
72 if p.err != nil {
73 return p.prev
74 }
75
76 if !p.peeked {
77 p.peekToken, p.peekError = p.lexer.ReadToken()
78 p.peeked = true
79 if p.peekToken.Kind == lexer.Comment {
80 p.consumeCommentGroup()
81 }
82 }
83
84 return p.peekToken
85 }
86
87 func (p *parser) error(tok lexer.Token, format string, args ...interface{}) {
88 if p.err != nil {
89 return
90 }
91 p.err = gqlerror.ErrorLocf(tok.Pos.Src.Name, tok.Pos.Line, tok.Pos.Column, format, args...)
92 }
93
94 func (p *parser) next() lexer.Token {
95 if p.err != nil {
96 return p.prev
97 }
98 if p.peeked {
99 p.peeked = false
100 p.comment = nil
101 p.prev, p.err = p.peekToken, p.peekError
102 } else {
103 p.prev, p.err = p.lexer.ReadToken()
104 if p.prev.Kind == lexer.Comment {
105 p.consumeCommentGroup()
106 }
107 }
108 return p.prev
109 }
110
111 func (p *parser) expectKeyword(value string) (lexer.Token, *ast.CommentGroup) {
112 tok := p.peek()
113 comment := p.comment
114 if tok.Kind == lexer.Name && tok.Value == value {
115 return p.next(), comment
116 }
117
118 p.error(tok, "Expected %s, found %s", strconv.Quote(value), tok.String())
119 return tok, comment
120 }
121
122 func (p *parser) expect(kind lexer.Type) (lexer.Token, *ast.CommentGroup) {
123 tok := p.peek()
124 comment := p.comment
125 if tok.Kind == kind {
126 return p.next(), comment
127 }
128
129 p.error(tok, "Expected %s, found %s", kind, tok.Kind.String())
130 return tok, comment
131 }
132
133 func (p *parser) skip(kind lexer.Type) bool {
134 if p.err != nil {
135 return false
136 }
137
138 tok := p.peek()
139
140 if tok.Kind != kind {
141 return false
142 }
143 p.next()
144 return true
145 }
146
147 func (p *parser) unexpectedError() {
148 p.unexpectedToken(p.peek())
149 }
150
151 func (p *parser) unexpectedToken(tok lexer.Token) {
152 p.error(tok, "Unexpected %s", tok.String())
153 }
154
155 func (p *parser) many(start lexer.Type, end lexer.Type, cb func()) {
156 hasDef := p.skip(start)
157 if !hasDef {
158 return
159 }
160
161 for p.peek().Kind != end && p.err == nil {
162 cb()
163 }
164 p.next()
165 }
166
167 func (p *parser) some(start lexer.Type, end lexer.Type, cb func()) *ast.CommentGroup {
168 hasDef := p.skip(start)
169 if !hasDef {
170 return nil
171 }
172
173 called := false
174 for p.peek().Kind != end && p.err == nil {
175 called = true
176 cb()
177 }
178
179 if !called {
180 p.error(p.peek(), "expected at least one definition, found %s", p.peek().Kind.String())
181 return nil
182 }
183
184 comment := p.comment
185 p.next()
186 return comment
187 }
188
View as plain text