Improve expression handling and add parentheses support
This commit is contained in:
parent
900de82d6a
commit
136e8cb26e
23
expr.go
23
expr.go
@ -8,33 +8,14 @@ import (
|
||||
)
|
||||
|
||||
func (t *Template) evalExpr(expr ast.Expr, local map[string]any) (any, error) {
|
||||
val, err := t.getValue(expr.Segment, local)
|
||||
val, err := t.getValue(expr.First, local)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a := reflect.ValueOf(val)
|
||||
|
||||
for _, exprB := range expr.Rest {
|
||||
val, err := t.getValue(exprB.Segment, local)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b := reflect.ValueOf(val)
|
||||
a = reflect.ValueOf(t.performOp(a, b, exprB.Logical))
|
||||
}
|
||||
|
||||
return a.Interface(), nil
|
||||
}
|
||||
|
||||
func (t *Template) evalExprSegment(expr ast.ExprSegment, local map[string]any) (any, error) {
|
||||
val, err := t.getValue(expr.Value, local)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
a := reflect.ValueOf(val)
|
||||
|
||||
for _, exprB := range expr.Rest {
|
||||
val, err := t.getValue(exprB.Value, local)
|
||||
val, err := t.getValue(exprB.First, local)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -17,15 +17,15 @@ func (ft forTag) Run(tc *TagContext, block, args []ast.Node) error {
|
||||
return ErrForTagInvalidArgs
|
||||
}
|
||||
|
||||
var expr ast.ExprSegment
|
||||
var expr ast.Expr
|
||||
if len(args) == 1 {
|
||||
expr2, ok := args[0].(ast.ExprSegment)
|
||||
expr2, ok := args[0].(ast.Expr)
|
||||
if !ok {
|
||||
return ErrForTagInvalidArgs
|
||||
}
|
||||
expr = expr2
|
||||
} else if len(args) == 2 {
|
||||
expr2, ok := args[1].(ast.ExprSegment)
|
||||
expr2, ok := args[1].(ast.Expr)
|
||||
if !ok {
|
||||
return ErrForTagInvalidArgs
|
||||
}
|
||||
@ -44,7 +44,7 @@ func (ft forTag) Run(tc *TagContext, block, args []ast.Node) error {
|
||||
|
||||
}
|
||||
|
||||
varName, ok := unwrap(expr.Value).(ast.Ident)
|
||||
varName, ok := unwrap(expr.First).(ast.Ident)
|
||||
if !ok {
|
||||
return ErrForTagInvalidArgs
|
||||
}
|
||||
|
2
go.mod
2
go.mod
@ -1,3 +1,5 @@
|
||||
module go.elara.ws/salix
|
||||
|
||||
go 1.21.2
|
||||
|
||||
require github.com/davecgh/go-spew v1.1.1
|
||||
|
2
go.sum
2
go.sum
@ -0,0 +1,2 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
@ -63,8 +63,8 @@ type Value struct {
|
||||
}
|
||||
|
||||
type Expr struct {
|
||||
Segment Node
|
||||
Logical Logical
|
||||
First Node
|
||||
Operator Operator
|
||||
Rest []Expr
|
||||
Position Position
|
||||
}
|
||||
@ -73,17 +73,6 @@ func (e Expr) Pos() Position {
|
||||
return e.Position
|
||||
}
|
||||
|
||||
type ExprSegment struct {
|
||||
Value Node
|
||||
Operator Operator
|
||||
Rest []ExprSegment
|
||||
Position Position
|
||||
}
|
||||
|
||||
func (es ExprSegment) Pos() Position {
|
||||
return es.Position
|
||||
}
|
||||
|
||||
type FuncCall struct {
|
||||
Name Ident
|
||||
Params []Node
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -28,6 +28,25 @@ func getPos(c *current) ast.Position {
|
||||
}
|
||||
}
|
||||
|
||||
func toExpr(c *current, first, rest any) ast.Node {
|
||||
restSlice := toAnySlice(rest)
|
||||
if len(restSlice) == 0 {
|
||||
return first.(ast.Node)
|
||||
}
|
||||
|
||||
out := ast.Expr{First: first.(ast.Node), Position: getPos(c)}
|
||||
for _, restValue := range restSlice {
|
||||
valueSlice := toAnySlice(restValue)
|
||||
out.Rest = append(out.Rest, ast.Expr{
|
||||
Operator: valueSlice[1].(ast.Operator),
|
||||
First: valueSlice[3].(ast.Node),
|
||||
Position: valueSlice[3].(ast.Node).Pos(),
|
||||
})
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Root = items:(Tag / ExprTag / EndTag / Text)* {
|
||||
@ -55,54 +74,32 @@ EndTag = "#!" name:Ident {
|
||||
}, nil
|
||||
}
|
||||
|
||||
ExprTag = "#(" item:Item ')' {
|
||||
ExprTag = "#(" item:Expr ')' {
|
||||
return ast.ExprTag{
|
||||
Value: item.(ast.Node),
|
||||
Position: getPos(c),
|
||||
}, nil
|
||||
}
|
||||
|
||||
Item = Ternary / Expr
|
||||
Expr = Ternary / LogicalExpr
|
||||
|
||||
Expr = first:ExprSegment rest:(_ Logical _ ExprSegment)* {
|
||||
restSlice := toAnySlice(rest)
|
||||
if len(restSlice) == 0 {
|
||||
return first, nil
|
||||
}
|
||||
|
||||
out := ast.Expr{Segment: first.(ast.Node), Position: getPos(c)}
|
||||
for _, restValue := range restSlice {
|
||||
valueSlice := toAnySlice(restValue)
|
||||
out.Rest = append(out.Rest, ast.Expr{
|
||||
Logical: valueSlice[1].(ast.Logical),
|
||||
Segment: valueSlice[3].(ast.Node),
|
||||
Position: valueSlice[3].(ast.Node).Pos(),
|
||||
})
|
||||
}
|
||||
|
||||
return out, nil
|
||||
LogicalExpr = _ first:ComparisonExpr rest:(_ LogicalOp _ ComparisonExpr)* _ {
|
||||
return toExpr(c, first, rest), nil
|
||||
}
|
||||
|
||||
ExprSegment = first:Value rest:(_ Operator _ Value)* {
|
||||
restSlice := toAnySlice(rest)
|
||||
if len(restSlice) == 0 {
|
||||
return first, nil
|
||||
}
|
||||
|
||||
out := ast.ExprSegment{Value: first.(ast.Node), Position: getPos(c)}
|
||||
for _, restValue := range restSlice {
|
||||
valueSlice := toAnySlice(restValue)
|
||||
out.Rest = append(out.Rest, ast.ExprSegment{
|
||||
Operator: valueSlice[1].(ast.Operator),
|
||||
Value: valueSlice[3].(ast.Node),
|
||||
Position: valueSlice[3].(ast.Node).Pos(),
|
||||
})
|
||||
}
|
||||
|
||||
return out, nil
|
||||
ComparisonExpr = _ first:ArithmeticExpr rest:(_ ComparisonOp _ ArithmeticExpr)* _ {
|
||||
return toExpr(c, first, rest), nil
|
||||
}
|
||||
|
||||
ParamList = '(' params:(Item ( ',' _ Item )* )? ')' {
|
||||
ArithmeticExpr = _ first:Value rest:(_ ArithmeticOp _ Value)* _ {
|
||||
return toExpr(c, first, rest), nil
|
||||
}
|
||||
|
||||
ParenExpr = '(' expr:Expr ')' {
|
||||
return expr, nil
|
||||
}
|
||||
|
||||
ParamList = '(' params:(Expr ( ',' _ Expr )* )? ')' {
|
||||
paramSlice := toAnySlice(params)
|
||||
if len(paramSlice) == 0 {
|
||||
return []ast.Node{}, nil
|
||||
@ -116,7 +113,7 @@ ParamList = '(' params:(Item ( ',' _ Item )* )? ')' {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
Value = not:"!"? node:(MethodCall / FieldAccess / Index / String / RawString / Float / Integer / Bool / FuncCall / VariableOr / Ident) {
|
||||
Value = not:"!"? node:(MethodCall / FieldAccess / Index / String / RawString / Float / Integer / Bool / FuncCall / VariableOr / Ident / ParenExpr) {
|
||||
return ast.Value{
|
||||
Node: node.(ast.Node),
|
||||
Not: not != nil,
|
||||
@ -218,15 +215,22 @@ Bool = ("true"i / "false"i) {
|
||||
}, err
|
||||
}
|
||||
|
||||
Operator = ("==" / "<=" / ">=" / "in"i / '<' / '>' / '+' / '-' / '/' / '*') {
|
||||
LogicalOp = ("||" / "&&") {
|
||||
return ast.Operator{
|
||||
Value: string(c.text),
|
||||
Position: getPos(c),
|
||||
}, nil
|
||||
}
|
||||
|
||||
Logical = ("&&" / "||") {
|
||||
return ast.Logical{
|
||||
ComparisonOp = ("==" / "<=" / ">=" / '<' / '>' / "in"i) {
|
||||
return ast.Operator{
|
||||
Value: string(c.text),
|
||||
Position: getPos(c),
|
||||
}, nil
|
||||
}
|
||||
|
||||
ArithmeticOp = ('+' / '-' / '/' / '*' / '%') {
|
||||
return ast.Operator{
|
||||
Value: string(c.text),
|
||||
Position: getPos(c),
|
||||
}, nil
|
||||
|
2
salix.go
2
salix.go
@ -206,8 +206,6 @@ func (t *Template) getValue(node ast.Node, local map[string]any) (any, error) {
|
||||
return node.Value, nil
|
||||
case ast.Expr:
|
||||
return t.evalExpr(node, local)
|
||||
case ast.ExprSegment:
|
||||
return t.evalExprSegment(node, local)
|
||||
case ast.FuncCall:
|
||||
return t.execFuncCall(node, local)
|
||||
case ast.Index:
|
||||
|
Loading…
Reference in New Issue
Block a user