@@ -19,16 +19,17 @@ package matcher
19
19
import (
20
20
"errors"
21
21
"fmt"
22
+ "log"
22
23
23
24
"github.com/goplus/gop/tpl/token"
24
25
"github.com/goplus/gop/tpl/types"
25
26
)
26
27
27
28
var (
28
- errMultiMismatch = errors .New ("multiple mismatch" )
29
-
30
29
// ErrVarAssigned error
31
30
ErrVarAssigned = errors .New ("variable is already assigned" )
31
+
32
+ errMultiMismatch = errors .New ("multiple mismatch" )
32
33
)
33
34
34
35
// -----------------------------------------------------------------------------
@@ -92,12 +93,86 @@ func (p *Context) NewErrorf(pos token.Pos, format string, args ...any) error {
92
93
return & Error {p .Fset , pos , fmt .Sprintf (format , args ... ), false }
93
94
}
94
95
96
+ // -----------------------------------------------------------------------------
97
+
98
+ // MatchToken represents a matching literal.
99
+ type MatchToken struct {
100
+ Tok token.Token
101
+ Lit string
102
+ }
103
+
104
+ func (p * MatchToken ) String () string {
105
+ return p .Lit
106
+ }
107
+
108
+ func hasConflictToken (me token.Token , next []any ) bool {
109
+ for _ , n := range next {
110
+ switch n := n .(type ) {
111
+ case * MatchToken :
112
+ if n .Tok == me {
113
+ return true
114
+ }
115
+ case token.Token :
116
+ if n == me {
117
+ return true
118
+ }
119
+ default :
120
+ panic ("unreachable" )
121
+ }
122
+ }
123
+ return false
124
+ }
125
+
126
+ func hasConflictMatchToken (me * MatchToken , next []any ) bool {
127
+ for _ , n := range next {
128
+ switch n := n .(type ) {
129
+ case * MatchToken :
130
+ if n .Tok == me .Tok && n .Lit == me .Lit {
131
+ return true
132
+ }
133
+ case token.Token :
134
+ default :
135
+ panic ("unreachable" )
136
+ }
137
+ }
138
+ return false
139
+ }
140
+
141
+ func hasConflictMe (me any , next []any ) bool {
142
+ switch me := me .(type ) {
143
+ case token.Token :
144
+ return hasConflictToken (me , next )
145
+ case * MatchToken :
146
+ return hasConflictMatchToken (me , next )
147
+ }
148
+ panic ("unreachable" )
149
+ }
150
+
151
+ func hasConflict (me []any , next []any ) bool {
152
+ for _ , m := range me {
153
+ if hasConflictMe (m , next ) {
154
+ return true
155
+ }
156
+ }
157
+ return false
158
+ }
159
+
160
+ func conflictWith (me []any , next [][]any ) int {
161
+ for i , n := range next {
162
+ if hasConflict (me , n ) {
163
+ return i
164
+ }
165
+ }
166
+ return - 1
167
+ }
168
+
95
169
// -----------------------------------------------------------------------------
96
170
// Matcher
97
171
98
172
// Matcher represents a matcher.
99
173
type Matcher interface {
100
174
Match (src []* types.Token , ctx * Context ) (n int , result any , err error )
175
+ First (in []any ) []any // item can be token.Token or *MatchToken
101
176
IsList () bool
102
177
}
103
178
@@ -109,6 +184,10 @@ func (p gTrue) Match(src []*types.Token, ctx *Context) (n int, result any, err e
109
184
return 0 , nil , nil
110
185
}
111
186
187
+ func (p gTrue ) First (in []any ) []any {
188
+ return in
189
+ }
190
+
112
191
func (p gTrue ) IsList () bool {
113
192
return false
114
193
}
@@ -135,6 +214,10 @@ func (p *gToken) Match(src []*types.Token, ctx *Context) (n int, result any, err
135
214
return 1 , t , nil
136
215
}
137
216
217
+ func (p * gToken ) First (in []any ) []any {
218
+ return append (in , p .tok )
219
+ }
220
+
138
221
func (p * gToken ) IsList () bool {
139
222
return false
140
223
}
@@ -146,22 +229,23 @@ func Token(tok token.Token) Matcher {
146
229
147
230
// -----------------------------------------------------------------------------
148
231
149
- type gLiteral struct {
150
- tok token.Token
151
- lit string
152
- }
232
+ type gLiteral MatchToken
153
233
154
234
func (p * gLiteral ) Match (src []* types.Token , ctx * Context ) (n int , result any , err error ) {
155
235
if len (src ) == 0 {
156
- return 0 , nil , ctx .NewErrorf (ctx .FileEnd , "expect `%s`, but got EOF" , p .lit )
236
+ return 0 , nil , ctx .NewErrorf (ctx .FileEnd , "expect `%s`, but got EOF" , p .Lit )
157
237
}
158
238
t := src [0 ]
159
- if t .Tok != p .tok || t .Lit != p .lit {
160
- return 0 , nil , ctx .NewErrorf (t .Pos , "expect `%s`, but got `%s`" , p .lit , t .Lit )
239
+ if t .Tok != p .Tok || t .Lit != p .Lit {
240
+ return 0 , nil , ctx .NewErrorf (t .Pos , "expect `%s`, but got `%s`" , p .Lit , t .Lit )
161
241
}
162
242
return 1 , t , nil
163
243
}
164
244
245
+ func (p * gLiteral ) First (in []any ) []any {
246
+ return append (in , (* MatchToken )(p ))
247
+ }
248
+
165
249
func (p * gLiteral ) IsList () bool {
166
250
return false
167
251
}
@@ -175,15 +259,40 @@ func Literal(tok token.Token, lit string) Matcher {
175
259
176
260
type gChoice struct {
177
261
options []Matcher
262
+ stops []bool
263
+ }
264
+
265
+ func (p * gChoice ) needStops () (stops []bool ) {
266
+ stops = p .stops
267
+ if stops == nil { // make stops
268
+ options := p .options
269
+ n := len (options )
270
+ firsts := make ([][]any , n )
271
+ for i , g := range options {
272
+ firsts [i ] = g .First (nil )
273
+ }
274
+ stops = make ([]bool , n )
275
+ for i , me := range firsts {
276
+ at := conflictWith (me , firsts [i + 1 :])
277
+ if at >= 0 {
278
+ log .Println ("conflict" , me , "with:" , firsts [at ]) // TODO(xsw): conflict
279
+ } else {
280
+ stops [i ] = true
281
+ }
282
+ }
283
+ p .stops = stops
284
+ }
285
+ return
178
286
}
179
287
180
288
func (p * gChoice ) Match (src []* types.Token , ctx * Context ) (n int , result any , err error ) {
181
289
var nMax = - 1
182
290
var errMax error
183
291
var multiErr = true
184
292
185
- for _ , g := range p .options {
186
- if n , result , err = g .Match (src , ctx ); err == nil {
293
+ stops := p .needStops ()
294
+ for i , g := range p .options {
295
+ if n , result , err = g .Match (src , ctx ); err == nil || (n > 0 && stops [i ]) {
187
296
return
188
297
}
189
298
if n >= nMax {
@@ -200,13 +309,20 @@ func (p *gChoice) Match(src []*types.Token, ctx *Context) (n int, result any, er
200
309
return nMax , nil , errMax
201
310
}
202
311
312
+ func (p * gChoice ) First (in []any ) []any {
313
+ for _ , g := range p .options {
314
+ in = g .First (in )
315
+ }
316
+ return in
317
+ }
318
+
203
319
func (p * gChoice ) IsList () bool {
204
320
return false
205
321
}
206
322
207
323
// Choice: R1 | R2 | ... | Rn
208
324
func Choice (options ... Matcher ) Matcher {
209
- return & gChoice {options }
325
+ return & gChoice {options , nil }
210
326
}
211
327
212
328
// -----------------------------------------------------------------------------
@@ -234,12 +350,19 @@ func (p *gSequence) Match(src []*types.Token, ctx *Context) (n int, result any,
234
350
return
235
351
}
236
352
353
+ func (p * gSequence ) First (in []any ) []any {
354
+ return p .items [0 ].First (in )
355
+ }
356
+
237
357
func (p * gSequence ) IsList () bool {
238
358
return true
239
359
}
240
360
241
361
// Sequence: R1 R2 ... Rn
242
362
func Sequence (items ... Matcher ) Matcher {
363
+ if len (items ) == 0 {
364
+ return gTrue {}
365
+ }
243
366
return & gSequence {items }
244
367
}
245
368
@@ -269,6 +392,10 @@ func (p *gRepeat0) Match(src []*types.Token, ctx *Context) (n int, result any, e
269
392
}
270
393
}
271
394
395
+ func (p * gRepeat0 ) First (in []any ) []any {
396
+ return p .r .First (in )
397
+ }
398
+
272
399
func (p * gRepeat0 ) IsList () bool {
273
400
return true
274
401
}
@@ -309,6 +436,10 @@ func (p *gRepeat1) Match(src []*types.Token, ctx *Context) (n int, result any, e
309
436
}
310
437
}
311
438
439
+ func (p * gRepeat1 ) First (in []any ) []any {
440
+ return p .r .First (in )
441
+ }
442
+
312
443
func (p * gRepeat1 ) IsList () bool {
313
444
return true
314
445
}
@@ -332,6 +463,10 @@ func (p *gRepeat01) Match(src []*types.Token, ctx *Context) (n int, result any,
332
463
return
333
464
}
334
465
466
+ func (p * gRepeat01 ) First (in []any ) []any {
467
+ return p .r .First (in )
468
+ }
469
+
335
470
func (p * gRepeat01 ) IsList () bool {
336
471
return false
337
472
}
@@ -408,6 +543,16 @@ func (p *Var) Match(src []*types.Token, ctx *Context) (n int, result any, err er
408
543
return
409
544
}
410
545
546
+ func (p * Var ) First (in []any ) []any {
547
+ elem := p .Elem
548
+ if elem != nil {
549
+ p .Elem = nil // to stop recursion
550
+ in = elem .First (in )
551
+ p .Elem = elem
552
+ }
553
+ return in
554
+ }
555
+
411
556
func (p * Var ) IsList () bool {
412
557
return false
413
558
}
0 commit comments