Skip to content

Commit 3d028fc

Browse files
committed
实现自定义函数
1 parent 095f686 commit 3d028fc

File tree

11 files changed

+700
-371
lines changed

11 files changed

+700
-371
lines changed

README.md

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,67 @@
1-
# TExpr
2-
Go语言布尔及数值运算表达式解析器
1+
# /Users/zhanglei/Work/Projects/texprTExpr
2+
33

44
[![Build Status](https://travis-ci.org/aliyun/texpr.svg?branch=master)](https://travis-ci.org/aliyun/texpr)
55
[![Coverage status](https://img.shields.io/codecov/c/github/aliyun/texpr/master.svg)](https://codecov.io/github/aliyun/texpr)
66

7+
Go语言布尔及数值运算表达式解析器
8+
79
[Java语言版本](https://github.com/tauris-io/expression)
810

11+
布尔表达式:
12+
13+
```
14+
$country in ['cn', 'us', 'jp'] && $length > 100
15+
$host == 'cs.qa.com' && 'Webkit' not in $ua
16+
```
17+
18+
数值运算表达式:
19+
20+
```
21+
( 1 ^ 5) + (2 << 3)
22+
4 | 3 + 3
23+
```
24+
25+
26+
27+
# Example
28+
29+
```
30+
package main
31+
32+
import (
33+
"fmt"
34+
"log"
35+
36+
"github.com/aliyun/texpr"
37+
)
38+
39+
type context map[string]interface{}
40+
41+
func (vg context) Get(name string) interface{} {
42+
v, ok := vg[name]
43+
if ok {
44+
return v
45+
}
46+
return nil
47+
}
48+
49+
func main() {
50+
m := context {
51+
"$value" : 15.0,
52+
}
53+
expr := texpr.MustCompile("$value - 10")
54+
v, err := expr.Eval(m)
55+
if err != nil {
56+
log.Fatalf("expression err, %s", err)
57+
}
58+
fmt.Println(v) // 5
59+
}
60+
61+
```
62+
63+
64+
965
## Quick Start
1066

1167
```bash
@@ -19,7 +75,7 @@ go run test/simple/main.go "33 > 22 && 22 > 11"
1975
go run test/simple/main.go "'world' =~ /.+orl.+/"
2076
```
2177

22-
78+
# 表达式语法
2379

2480
## 数值计算
2581

@@ -40,7 +96,7 @@ go run test/simple/main.go "'world' =~ /.+orl.+/"
4096

4197
| 操作符 | 描述 | 例子 |
4298
| ------ | ------------------------------------------------------------ | ------------ |
43-
| = | 两值相等 | A=B |
99+
| == | 两值相等 | A==B |
44100
| > | 左值大于右值 | A>B |
45101
| < | 右值大于左值 | A<B |
46102
| >= | 左值大于等于右值 | A>=B |

TExpr.g4

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,18 +85,15 @@ scientific
8585
;
8686

8787
function
88-
: funcname LPAREN expression RPAREN
88+
: funcname LPAREN parameters RPAREN
8989
;
9090

9191
funcname
92-
: COS
93-
| TAN
94-
| SIN
95-
| ACOS
96-
| ATAN
97-
| ASIN
98-
| LOG
99-
| LN
92+
: IDENTIFIER
93+
;
94+
95+
parameters
96+
: expression (',' expression)*
10097
;
10198

10299
number

antlr.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
export PATH=/usr/local/bin:$PATH
44

5-
antlr -o ./ -no-listener -visitor -Dlanguage=Go -package ast TExpr.g4
5+
antlr -o ./ast -no-listener -visitor -Dlanguage=Go -package ast TExpr.g4

ast/texpr_base_visitor.go

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ast/texpr_lexer.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ast/texpr_parser.go

Lines changed: 414 additions & 317 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ast/texpr_visitor.go

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

compiler.go

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package texpr
22

33
import (
4+
"errors"
45
"fmt"
56
"math"
67
"reflect"
@@ -28,7 +29,7 @@ func Compile(expr string) (Expression, error) {
2829
func MustCompile(expr string) Expression {
2930
exp, err := Compile(expr)
3031
if err != nil {
31-
return nil
32+
panic(`texpr: Compile("` + expr + `"): ` + err.Error())
3233
}
3334
return exp
3435
}
@@ -668,13 +669,33 @@ func (v *ExprVisitor) VisitScientific(ctx *ast.ScientificContext) interface{} {
668669
}
669670

670671
func (v *ExprVisitor) VisitFunction(ctx *ast.FunctionContext) interface{} {
671-
return v.VisitChildren(ctx)
672+
params := ctx.Parameters().Accept(v).([]interface{})
673+
fname := ctx.Funcname().Accept(v).(string)
674+
f, b := funcMap[fname]
675+
if !b {
676+
return errors.New("unknown function " + fname)
677+
}
678+
exprs := make([]Expression, len(params))
679+
for i, _ := range params {
680+
exprs[i] = params[i].(Expression)
681+
}
682+
return NewFuncExpr(fname, f, exprs)
672683
}
673684

674685
func (v *ExprVisitor) VisitFuncname(ctx *ast.FuncnameContext) interface{} {
675-
return v.VisitChildren(ctx)
686+
return ctx.IDENTIFIER().GetText()
676687
}
677688

689+
func (v *ExprVisitor) VisitParameters(ctx *ast.ParametersContext) interface{} {
690+
var params []interface{}
691+
allExprs := ctx.AllExpression()
692+
for i, _ := range allExprs {
693+
params = append(params, allExprs[i].Accept(v))
694+
}
695+
return params
696+
}
697+
698+
678699
func (v *ExprVisitor) VisitNumber(ctx *ast.NumberContext) interface{} {
679700
return v.VisitChildren(ctx)
680701
}

0 commit comments

Comments
 (0)