Skip to content

Commit 33295b6

Browse files
committed
fix: fix expression syntax parsing bug
Change-Id: Iccaf489d96a6ecd35401db525b7089e100fc2532
1 parent 2865efb commit 33295b6

File tree

7 files changed

+258
-94
lines changed

7 files changed

+258
-94
lines changed

expr.go

Lines changed: 128 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@
1515
package tagexpr
1616

1717
import (
18+
"bytes"
1819
"context"
1920
"fmt"
21+
"os"
22+
23+
"github.com/andeya/goutil"
2024
)
2125

2226
// Expr expression
@@ -31,21 +35,58 @@ func parseExpr(expr string) (*Expr, error) {
3135
expr: e,
3236
}
3337
s := expr
34-
_, err := p.parseExprNode(&s, e)
35-
if err != nil {
36-
return nil, err
37-
}
38-
sortPriority(e.RightOperand())
39-
err = p.checkSyntax()
38+
err := p.parseExprNode(&s, e)
4039
if err != nil {
4140
return nil, err
4241
}
42+
sortPriority(e)
4343
return p, nil
4444
}
45-
46-
// run calculates the value of expression.
47-
func (p *Expr) run(field string, tagExpr *TagExpr) interface{} {
48-
return p.expr.Run(context.Background(), field, tagExpr)
45+
func (p *Expr) parseExprNode(expr *string, e ExprNode) error {
46+
trimLeftSpace(expr)
47+
if *expr == "" {
48+
return nil
49+
}
50+
operand := p.readSelectorExprNode(expr)
51+
if operand == nil {
52+
operand = p.readRangeKvExprNode(expr)
53+
if operand == nil {
54+
var subExprNode *string
55+
operand, subExprNode = readGroupExprNode(expr)
56+
if operand != nil {
57+
err := p.parseExprNode(subExprNode, operand)
58+
if err != nil {
59+
return err
60+
}
61+
} else {
62+
operand = p.parseOperand(expr)
63+
}
64+
}
65+
}
66+
if operand == nil {
67+
return fmt.Errorf("syntax error: %q", *expr)
68+
}
69+
trimLeftSpace(expr)
70+
operator := p.parseOperator(expr)
71+
if operator == nil {
72+
e.SetRightOperand(operand)
73+
operand.SetParent(e)
74+
return nil
75+
}
76+
if _, ok := e.(*groupExprNode); ok {
77+
operator.SetLeftOperand(operand)
78+
operand.SetParent(operator)
79+
e.SetRightOperand(operator)
80+
operator.SetParent(e)
81+
} else {
82+
operator.SetParent(e.Parent())
83+
operator.Parent().SetRightOperand(operator)
84+
operator.SetLeftOperand(e)
85+
e.SetParent(operator)
86+
e.SetRightOperand(operand)
87+
operand.SetParent(e)
88+
}
89+
return p.parseExprNode(expr, operator)
4990
}
5091

5192
func (p *Expr) parseOperand(expr *string) (e ExprNode) {
@@ -124,56 +165,9 @@ func (*Expr) parseOperator(expr *string) (e ExprNode) {
124165
return nil
125166
}
126167

127-
func (p *Expr) parseExprNode(expr *string, e ExprNode) (ExprNode, error) {
128-
trimLeftSpace(expr)
129-
if *expr == "" {
130-
return nil, nil
131-
}
132-
operand := p.readSelectorExprNode(expr)
133-
if operand == nil {
134-
operand = p.readRangeKvExprNode(expr)
135-
if operand == nil {
136-
var subExprNode *string
137-
operand, subExprNode = readGroupExprNode(expr)
138-
if operand != nil {
139-
_, err := p.parseExprNode(subExprNode, operand)
140-
if err != nil {
141-
return nil, err
142-
}
143-
} else {
144-
operand = p.parseOperand(expr)
145-
}
146-
}
147-
}
148-
if operand == nil {
149-
return nil, fmt.Errorf("syntax error: %q", *expr)
150-
}
151-
trimLeftSpace(expr)
152-
operator := p.parseOperator(expr)
153-
if operator == nil {
154-
e.SetRightOperand(operand)
155-
operand.SetParent(e)
156-
return operand, nil
157-
}
158-
if _, ok := e.(*groupExprNode); ok {
159-
operator.SetLeftOperand(operand)
160-
operand.SetParent(operator)
161-
e.SetRightOperand(operator)
162-
operator.SetParent(e)
163-
} else {
164-
e.SetRightOperand(operand)
165-
operand.SetParent(e)
166-
operator.SetLeftOperand(e)
167-
operator.SetParent(e.Parent())
168-
operator.Parent().SetRightOperand(operator)
169-
e.SetParent(operator)
170-
}
171-
return p.parseExprNode(expr, operator)
172-
}
173-
174-
func (p *Expr) checkSyntax() error {
175-
176-
return nil
168+
// run calculates the value of expression.
169+
func (p *Expr) run(field string, tagExpr *TagExpr) interface{} {
170+
return p.expr.Run(context.Background(), field, tagExpr)
177171
}
178172

179173
/**
@@ -188,26 +182,52 @@ func (p *Expr) checkSyntax() error {
188182
**/
189183

190184
func sortPriority(e ExprNode) {
191-
for subSortPriority(e) {
185+
printExprNode(e)
186+
for subSortPriority(e.RightOperand(), false) {
187+
printExprNode(e)
192188
}
193189
}
194190

195-
func subSortPriority(e ExprNode) bool {
191+
func subSortPriority(e ExprNode, isLeft bool) bool {
196192
if e == nil {
197193
return false
198194
}
199-
leftChanged := subSortPriority(e.LeftOperand())
200-
rightChanged := subSortPriority(e.RightOperand())
195+
leftChanged := subSortPriority(e.LeftOperand(), true)
196+
rightChanged := subSortPriority(e.RightOperand(), false)
201197
if getPriority(e) > getPriority(e.LeftOperand()) {
202-
leftOperandToParent(e)
198+
printf("before:\n")
199+
printExprNode(e)
200+
leftOperandToParent(e, isLeft)
201+
printf("after:\n")
202+
printExprNode(e.Parent())
203203
return true
204204
}
205205
return leftChanged || rightChanged
206206
}
207207

208+
func leftOperandToParent(e ExprNode, isLeft bool) {
209+
le := e.LeftOperand()
210+
if le == nil {
211+
return
212+
}
213+
p := e.Parent()
214+
le.SetParent(p)
215+
if p != nil {
216+
if isLeft {
217+
p.SetLeftOperand(le)
218+
} else {
219+
p.SetRightOperand(le)
220+
}
221+
}
222+
e.SetParent(le)
223+
e.SetLeftOperand(le.RightOperand())
224+
le.RightOperand().SetParent(e)
225+
le.SetRightOperand(e)
226+
}
227+
208228
func getPriority(e ExprNode) (i int) {
209229
// defer func() {
210-
// fmt.Printf("expr:%T %d\n", e, i)
230+
// printf("expr:%T %d\n", e, i)
211231
// }()
212232
switch e.(type) {
213233
default: // () ! bool float64 string nil
@@ -227,26 +247,6 @@ func getPriority(e ExprNode) (i int) {
227247
}
228248
}
229249

230-
func leftOperandToParent(e ExprNode) {
231-
le := e.LeftOperand()
232-
if le == nil {
233-
return
234-
}
235-
e.SetLeftOperand(le.RightOperand())
236-
le.SetRightOperand(e)
237-
p := e.Parent()
238-
// if p == nil {
239-
// return
240-
// }
241-
if p.LeftOperand() == e {
242-
p.SetLeftOperand(le)
243-
} else {
244-
p.SetRightOperand(le)
245-
}
246-
le.SetParent(p)
247-
e.SetParent(le)
248-
}
249-
250250
// ExprNode expression interface
251251
type ExprNode interface {
252252
SetParent(ExprNode)
@@ -255,10 +255,11 @@ type ExprNode interface {
255255
RightOperand() ExprNode
256256
SetLeftOperand(ExprNode)
257257
SetRightOperand(ExprNode)
258+
String() string
258259
Run(context.Context, string, *TagExpr) interface{}
259260
}
260261

261-
var _ ExprNode = new(exprBackground)
262+
// var _ ExprNode = new(exprBackground)
262263

263264
type exprBackground struct {
264265
parent ExprNode
@@ -291,3 +292,43 @@ func (eb *exprBackground) SetRightOperand(right ExprNode) {
291292
}
292293

293294
func (*exprBackground) Run(context.Context, string, *TagExpr) interface{} { return nil }
295+
296+
var debugSwitch = goutil.IsGoTest()
297+
298+
func printf(format string, a ...interface{}) {
299+
if debugSwitch {
300+
fmt.Fprintf(os.Stderr, format, a...)
301+
}
302+
}
303+
304+
func printExprNode(node ExprNode) {
305+
if node == nil {
306+
return
307+
}
308+
tail := true
309+
if node.Parent() != nil {
310+
tail = node == node.Parent().RightOperand()
311+
}
312+
printf("%s\n\n", formatExprNode(node, 0, tail))
313+
}
314+
315+
func formatExprNode(node ExprNode, level int, tail bool) []byte {
316+
var b bytes.Buffer
317+
if node == nil {
318+
} else {
319+
b.Write(formatExprNode(node.LeftOperand(), level+1, false))
320+
321+
b.Write(bytes.Repeat([]byte(" "), level))
322+
if tail {
323+
b.Write([]byte("└── "))
324+
} else {
325+
b.Write([]byte("┌── "))
326+
}
327+
328+
b.Write([]byte(node.String()))
329+
b.Write([]byte("\n"))
330+
331+
b.Write(formatExprNode(node.RightOperand(), level+1, true))
332+
}
333+
return b.Bytes()
334+
}

spec_func.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,12 @@ func (p *Expr) parseFuncSign(funcName string, expr *string) (boolOpposite *bool,
6363
if strings.HasPrefix(*subExprNode, ",") {
6464
*subExprNode = (*subExprNode)[1:]
6565
operand := newGroupExprNode()
66-
_, err := p.parseExprNode(trimLeftSpace(subExprNode), operand)
66+
err := p.parseExprNode(trimLeftSpace(subExprNode), operand)
6767
if err != nil {
6868
*expr = lastStr
6969
return
7070
}
71-
sortPriority(operand.RightOperand())
71+
sortPriority(operand)
7272
args = append(args, operand)
7373
} else {
7474
*expr = lastStr
@@ -105,6 +105,10 @@ type funcExprNode struct {
105105
signOpposite *bool
106106
}
107107

108+
func (f *funcExprNode) String() string {
109+
return "func()"
110+
}
111+
108112
func (f *funcExprNode) Run(ctx context.Context, currField string, tagExpr *TagExpr) interface{} {
109113
var args []interface{}
110114
if n := len(f.args); n > 0 {
@@ -171,6 +175,10 @@ type regexpFuncExprNode struct {
171175
boolOpposite bool
172176
}
173177

178+
func (re *regexpFuncExprNode) String() string {
179+
return "regexp()"
180+
}
181+
174182
func readRegexpFuncExprNode(p *Expr, expr *string) ExprNode {
175183
last, boolOpposite, _ := getBoolAndSignOpposite(expr)
176184
if !strings.HasPrefix(last, "regexp(") {
@@ -196,7 +204,7 @@ func readRegexpFuncExprNode(p *Expr, expr *string) ExprNode {
196204
trimLeftSpace(subExprNode)
197205
if strings.HasPrefix(*subExprNode, ",") {
198206
*subExprNode = (*subExprNode)[1:]
199-
_, err = p.parseExprNode(trimLeftSpace(subExprNode), operand)
207+
err = p.parseExprNode(trimLeftSpace(subExprNode), operand)
200208
if err != nil {
201209
*expr = lastStr
202210
return nil
@@ -249,6 +257,10 @@ type sprintfFuncExprNode struct {
249257
args []ExprNode
250258
}
251259

260+
func (se *sprintfFuncExprNode) String() string {
261+
return "sprintf()"
262+
}
263+
252264
func readSprintfFuncExprNode(p *Expr, expr *string) ExprNode {
253265
if !strings.HasPrefix(*expr, "sprintf(") {
254266
return nil
@@ -275,12 +287,12 @@ func readSprintfFuncExprNode(p *Expr, expr *string) ExprNode {
275287
if strings.HasPrefix(*subExprNode, ",") {
276288
*subExprNode = (*subExprNode)[1:]
277289
operand := newGroupExprNode()
278-
_, err := p.parseExprNode(trimLeftSpace(subExprNode), operand)
290+
err := p.parseExprNode(trimLeftSpace(subExprNode), operand)
279291
if err != nil {
280292
*expr = lastStr
281293
return nil
282294
}
283-
sortPriority(operand.RightOperand())
295+
sortPriority(operand)
284296
e.args = append(e.args, operand)
285297
} else {
286298
*expr = lastStr

0 commit comments

Comments
 (0)