作者 yangfu

feat: ast expr version 1

... ... @@ -86,7 +86,7 @@ func (a *AST) parseFunCallerOrConst() ExprAST {
// call func
if a.currTok.Tok == "(" {
f := FunCallerExprAST{}
if _, ok := defFunc[name]; !ok {
if _, ok := defFunc[strings.ToLower(name)]; !ok {
a.Err = errors.New(
fmt.Sprintf("function `%s` is undefined\n%s",
name,
... ... @@ -107,7 +107,7 @@ func (a *AST) parseFunCallerOrConst() ExprAST {
exprs = append(exprs, a.ParseExpression())
}
}
def := defFunc[name]
def := defFunc[strings.ToLower(name)]
if def.argc >= 0 && len(exprs) != def.argc {
a.Err = errors.New(
fmt.Sprintf("wrong way calling function `%s`, parameters want %d but get %d\n%s",
... ... @@ -117,8 +117,7 @@ func (a *AST) parseFunCallerOrConst() ExprAST {
ErrPos(a.source, a.currTok.Offset)))
}
a.getNextToken()
f.Name = name
f.Args = exprs
f = NewFunCallerExprAST(name, exprs...)
return f
}
// call const
... ... @@ -129,9 +128,7 @@ func (a *AST) parseFunCallerOrConst() ExprAST {
}
} else {
if strings.Contains(name, ".") {
return FieldExprAST{
Str: name,
}
return NewFieldExprAST(name)
}
a.Err = errors.New(
fmt.Sprintf("const `%s` is undefined\n%s",
... ... @@ -148,9 +145,7 @@ func (a *AST) parsePrimary() ExprAST {
case Literal:
return a.parseNumber()
case StringArgs:
e := ValueExprAST{
Str: a.currTok.Tok,
}
e := NewValueExprAST(a.currTok.Tok)
a.getNextToken()
return e
case Operator:
... ... @@ -182,11 +177,7 @@ func (a *AST) parsePrimary() ExprAST {
ErrPos(a.source, a.currTok.Offset)))
return nil
}
bin := BinaryExprAST{
Op: "-",
Lhs: NumberExprAST{},
Rhs: a.parsePrimary(),
}
bin := NewBinaryExprAST("-", NumberExprAST{}, a.parsePrimary())
return bin
} else {
return a.parseNumber()
... ... @@ -226,10 +217,6 @@ func (a *AST) parseBinOpRHS(execPrec int, lhs ExprAST) ExprAST {
return nil
}
}
lhs = BinaryExprAST{
Op: binOp,
Lhs: lhs,
Rhs: rhs,
}
lhs = NewBinaryExprAST(binOp, lhs, rhs)
}
}
... ...
... ... @@ -11,6 +11,7 @@ const (
TypeBinaryExprAST = "BinaryExprAST"
TypeFieldExprAST = "FieldExprAST"
TypeValueExprAST = "ValueExprAST"
TypeNumberExprAST = "NumberExprAST"
)
type ExprAST interface {
... ... @@ -18,6 +19,7 @@ type ExprAST interface {
}
type NumberExprAST struct {
ExprType string `json:"exprType"`
Val float64
Str string
}
... ... @@ -42,7 +44,7 @@ type BinaryExprAST struct {
}
type FunCallerExprAST struct {
ArrayFlag bool `json:"arrayFlag"`
//ArrayFlag bool `json:"arrayFlag"`
ExprType string `json:"exprType"`
Name string `json:"name"`
Args []ExprAST `json:"args"`
... ... @@ -86,7 +88,7 @@ func (n FunCallerExprAST) toStr() string {
}
type CloneFunCallerExprAST struct {
ArrayFlag bool `json:"arrayFlag"`
//ArrayFlag bool `json:"arrayFlag"`
Name string `json:"name"`
Arg []json.RawMessage `json:"args"`
}
... ...
package astexpr
import (
"gitlab.fjmaimaimai.com/allied-creation/character-library-metadata-bastion/pkg/domain"
"strconv"
"strings"
)
func NewNumberExprAST(val string) NumberExprAST {
num, _ := strconv.ParseFloat(val, 64)
return NumberExprAST{
ExprType: TypeNumberExprAST,
Val: num,
Str: val,
}
}
func NewValueExprAST(val string) ValueExprAST {
return ValueExprAST{
ExprType: TypeValueExprAST,
Val: val,
Str: val,
}
}
func NewFieldExprAST(val string) FieldExprAST {
words := strings.Split(val, ".")
table := words[0]
filed := words[0]
if len(words) > 0 {
filed = words[1]
}
return FieldExprAST{
ExprType: TypeFieldExprAST,
Str: val,
Field: &domain.TableField{
FieldName: filed,
TableName: table,
},
}
}
func NewBinaryExprAST(op string, lhs ExprAST, rhs ExprAST) BinaryExprAST {
return BinaryExprAST{
ExprType: TypeBinaryExprAST,
Op: op,
Lhs: lhs,
Rhs: rhs,
}
}
func NewFunCallerExprAST(name string, args ...ExprAST) FunCallerExprAST {
return FunCallerExprAST{
ExprType: TypeFunCallerExprAST,
Name: name,
Args: args,
}
}
... ...
... ... @@ -94,3 +94,26 @@ func TestAstExprUnmarshalJSON(t *testing.T) {
assert.Equal(t, input.data, v)
}
}
func TestAstExprParse(t *testing.T) {
funs := []struct {
Name string
Exp []string
}{
{
"多级嵌套",
[]string{`COUNTIF(销售明细.业绩,"<=1000")-COUNTIF(销售明细.业绩,"<=100")`},
},
}
for _, f := range funs {
for _, exp := range f.Exp {
r, err := Parse(exp)
if err != nil {
t.Error(err)
}
if r != 0 {
}
}
}
}
... ...
... ... @@ -138,7 +138,7 @@ func (p *Parser) nextTok() *Token {
}
tok.Offset = start
case '"':
for (p.isDigitNum(p.ch) || p.isChar(p.ch)) && p.nextCh() == nil {
for (p.isDigitNum(p.ch) || p.isChar(p.ch) || p.isCompareWordChar(p.ch)) && p.nextCh() == nil {
if p.ch == '"' {
break
}
... ...