1
1
package parser
2
2
3
3
import (
4
+ "errors"
4
5
"fmt"
6
+ "io"
5
7
"math"
6
8
"strconv"
7
9
"strings"
@@ -10,6 +12,7 @@ import (
10
12
"github.com/expr-lang/expr/builtin"
11
13
"github.com/expr-lang/expr/conf"
12
14
"github.com/expr-lang/expr/file"
15
+ "github.com/expr-lang/expr/parser/lexer"
13
16
. "github.com/expr-lang/expr/parser/lexer"
14
17
"github.com/expr-lang/expr/parser/operator"
15
18
"github.com/expr-lang/expr/parser/utils"
@@ -45,13 +48,13 @@ var predicates = map[string]struct {
45
48
}
46
49
47
50
type parser struct {
48
- tokens [] Token
49
- current Token
50
- pos int
51
- err * file.Error
52
- config * conf.Config
53
- depth int // predicate call depth
54
- nodeCount uint // tracks number of AST nodes created
51
+ lexer * lexer. Lexer
52
+ current , stashed Token
53
+ hasStash bool
54
+ err * file.Error
55
+ config * conf.Config
56
+ depth int // predicate call depth
57
+ nodeCount uint // tracks number of AST nodes created
55
58
}
56
59
57
60
func (p * parser ) checkNodeLimit () error {
@@ -102,19 +105,14 @@ func Parse(input string) (*Tree, error) {
102
105
}
103
106
104
107
func ParseWithConfig (input string , config * conf.Config ) (* Tree , error ) {
105
- source := file .NewSource (input )
106
-
107
- tokens , err := Lex (source )
108
- if err != nil {
109
- return nil , err
110
- }
111
-
112
108
p := & parser {
113
- tokens : tokens ,
114
- current : tokens [0 ],
115
- config : config ,
109
+ lexer : lexer .New (),
110
+ config : config ,
116
111
}
117
112
113
+ source := file .NewSource (input )
114
+ p .lexer .Reset (source )
115
+ p .next ()
118
116
node := p .parseSequenceExpression ()
119
117
120
118
if ! p .current .Is (EOF ) {
@@ -147,12 +145,28 @@ func (p *parser) errorAt(token Token, format string, args ...any) {
147
145
}
148
146
149
147
func (p * parser ) next () {
150
- p . pos ++
151
- if p . pos >= len ( p . tokens ) {
152
- p .error ( "unexpected end of expression" )
148
+ if p . hasStash {
149
+ p . current = p . stashed
150
+ p .hasStash = false
153
151
return
154
152
}
155
- p .current = p .tokens [p .pos ]
153
+
154
+ token , err := p .lexer .Next ()
155
+ var e * file.Error
156
+ switch {
157
+ case err == nil :
158
+ p .current = token
159
+ case errors .Is (err , io .EOF ):
160
+ p .error ("unexpected end of expression" )
161
+ case errors .As (err , & e ):
162
+ p .err = e
163
+ default :
164
+ p .err = & file.Error {
165
+ Location : p .current .Location ,
166
+ Message : "unknown lexing error" ,
167
+ Prev : err ,
168
+ }
169
+ }
156
170
}
157
171
158
172
func (p * parser ) expect (kind Kind , values ... string ) {
@@ -209,15 +223,16 @@ func (p *parser) parseExpression(precedence int) Node {
209
223
210
224
// Handle "not *" operator, like "not in" or "not contains".
211
225
if negate {
212
- currentPos := p .pos
226
+ tokenBackup := p .current
213
227
p .next ()
214
228
if operator .AllowedNegateSuffix (p .current .Value ) {
215
229
if op , ok := operator .Binary [p .current .Value ]; ok && op .Precedence >= precedence {
216
230
notToken = p .current
217
231
opToken = p .current
218
232
} else {
219
- p .pos = currentPos
220
- p .current = opToken
233
+ p .hasStash = true
234
+ p .stashed = p .current
235
+ p .current = tokenBackup
221
236
break
222
237
}
223
238
} else {
0 commit comments