1
0
mirror of https://github.com/MontFerret/ferret.git synced 2025-11-06 08:39:09 +02:00
* Renamed DOCUMENT to PAGE

* Added PageLoadParams

* Added PageLoadParams

* Renamed LoadPageParams -> PageLoadParams

* Added support for context.Done() (#201)

* Bug/#189 operators precedence (#202)

* Fixed math operators precedence

* Fixed logical operators precedence

* Fixed array operator

* Added support for parentheses to enforce a different operator evaluation order

* Feature/#200 drivers (#209)

* Added new interfaces

* Renamed dynamic to cdp driver

* Renamed drivers

* Added ELEMENT_EXISTS function (#210)

* Renamed back PAGE to DOCUMENT (#211)

* Added Getter and Setter interfaces
This commit is contained in:
Tim Voronov
2018-12-21 23:14:41 -05:00
committed by GitHub
parent 6bc4b3e0e3
commit 5620be211c
92 changed files with 2953 additions and 1656 deletions

View File

@@ -0,0 +1,65 @@
package compiler_test
import (
"context"
"github.com/MontFerret/ferret/pkg/compiler"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestPrecedence(t *testing.T) {
Convey("Math operators", t, func() {
Convey("2 + 2 * 2", func() {
c := compiler.New()
p := c.MustCompile(`RETURN 2 + 2 * 2`)
out := p.MustRun(context.Background())
So(string(out), ShouldEqual, "6")
})
Convey("2 * 2 + 2", func() {
c := compiler.New()
p := c.MustCompile(`RETURN 2 * 2 + 2`)
out := p.MustRun(context.Background())
So(string(out), ShouldEqual, "6")
})
Convey("2 * (2 + 2)", func() {
c := compiler.New()
p := c.MustCompile(`RETURN 2 * (2 + 2)`)
out := p.MustRun(context.Background())
So(string(out), ShouldEqual, "8")
})
})
Convey("Logical", t, func() {
Convey("TRUE OR TRUE AND FALSE", func() {
c := compiler.New()
p := c.MustCompile(`RETURN TRUE OR TRUE AND FALSE`)
out := p.MustRun(context.Background())
So(string(out), ShouldEqual, "true")
})
Convey("FALSE AND TRUE OR TRUE", func() {
c := compiler.New()
p := c.MustCompile(`RETURN FALSE AND TRUE OR TRUE`)
out := p.MustRun(context.Background())
So(string(out), ShouldEqual, "true")
})
})
}

View File

@@ -352,10 +352,16 @@ func (v *visitor) doVisitFilterClause(ctx *fql.FilterClauseContext, scope *scope
return operators.NewEqualityOperator(v.getSourceMap(ctx), left, right, equalityOp.GetText())
}
logicalOp := exp.LogicalOperator()
logicalAndOp := exp.LogicalAndOperator()
if logicalOp != nil {
return operators.NewLogicalOperator(v.getSourceMap(ctx), left, right, logicalOp.GetText())
if logicalAndOp != nil {
return operators.NewLogicalOperator(v.getSourceMap(ctx), left, right, logicalAndOp.GetText())
}
logicalOrOp := exp.LogicalOrOperator()
if logicalOrOp != nil {
return operators.NewLogicalOperator(v.getSourceMap(ctx), left, right, logicalOrOp.GetText())
}
} else {
// should be unary operator
@@ -1078,7 +1084,21 @@ func (v *visitor) doVisitAllExpressions(contexts []fql.IExpressionContext, scope
}
func (v *visitor) doVisitMathOperator(ctx *fql.ExpressionContext, scope *scope) (core.OperatorExpression, error) {
mathOp := ctx.MathOperator().(*fql.MathOperatorContext)
var operator operators.MathOperatorType
multiCtx := ctx.MultiplicativeOperator()
if multiCtx != nil {
operator = operators.MathOperatorType(multiCtx.GetText())
} else {
additiveCtx := ctx.AdditiveOperator()
if additiveCtx == nil {
return nil, ErrInvalidToken
}
operator = operators.MathOperatorType(additiveCtx.GetText())
}
exps, err := v.doVisitAllExpressions(ctx.AllExpression(), scope)
if err != nil {
@@ -1089,10 +1109,10 @@ func (v *visitor) doVisitMathOperator(ctx *fql.ExpressionContext, scope *scope)
right := exps[1]
return operators.NewMathOperator(
v.getSourceMap(mathOp),
v.getSourceMap(ctx),
left,
right,
operators.MathOperatorType(mathOp.GetText()),
operator,
)
}
@@ -1115,7 +1135,22 @@ func (v *visitor) doVisitUnaryOperator(ctx *fql.ExpressionContext, scope *scope)
}
func (v *visitor) doVisitLogicalOperator(ctx *fql.ExpressionContext, scope *scope) (core.OperatorExpression, error) {
logicalOp := ctx.LogicalOperator().(*fql.LogicalOperatorContext)
var operator string
logicalAndOp := ctx.LogicalAndOperator()
if logicalAndOp != nil {
operator = logicalAndOp.GetText()
} else {
logicalOrOp := ctx.LogicalOrOperator()
if logicalOrOp == nil {
return nil, ErrInvalidToken
}
operator = logicalOrOp.GetText()
}
exps, err := v.doVisitAllExpressions(ctx.AllExpression(), scope)
if err != nil {
@@ -1125,7 +1160,7 @@ func (v *visitor) doVisitLogicalOperator(ctx *fql.ExpressionContext, scope *scop
left := exps[0]
right := exps[1]
return operators.NewLogicalOperator(v.getSourceMap(logicalOp), left, right, logicalOp.GetText())
return operators.NewLogicalOperator(v.getSourceMap(ctx), left, right, operator)
}
func (v *visitor) doVisitEqualityOperator(ctx *fql.ExpressionContext, scope *scope) (core.OperatorExpression, error) {
@@ -1206,13 +1241,83 @@ func (v *visitor) doVisitArrayOperator(ctx *fql.ExpressionContext, scope *scope)
)
}
func (v *visitor) doVisitExpressionGroup(ctx *fql.ExpressionGroupContext, scope *scope) (core.Expression, error) {
exp := ctx.Expression()
if exp == nil {
return nil, ErrInvalidToken
}
return v.doVisitExpression(exp.(*fql.ExpressionContext), scope)
}
func (v *visitor) doVisitExpression(ctx *fql.ExpressionContext, scope *scope) (core.Expression, error) {
seq := ctx.ExpressionGroup()
if seq != nil {
return v.doVisitExpressionGroup(seq.(*fql.ExpressionGroupContext), scope)
}
member := ctx.MemberExpression()
if member != nil {
return v.doVisitMemberExpression(member.(*fql.MemberExpressionContext), scope)
}
funCall := ctx.FunctionCallExpression()
if funCall != nil {
return v.doVisitFunctionCallExpression(funCall.(*fql.FunctionCallExpressionContext), scope)
}
notOp := ctx.UnaryOperator()
if notOp != nil {
return v.doVisitUnaryOperator(ctx, scope)
}
multiOp := ctx.MultiplicativeOperator()
if multiOp != nil {
return v.doVisitMathOperator(ctx, scope)
}
addOp := ctx.AdditiveOperator()
if addOp != nil {
return v.doVisitMathOperator(ctx, scope)
}
arrOp := ctx.ArrayOperator()
if arrOp != nil {
return v.doVisitArrayOperator(ctx, scope)
}
equalityOp := ctx.EqualityOperator()
if equalityOp != nil {
return v.doVisitEqualityOperator(ctx, scope)
}
inOp := ctx.InOperator()
if inOp != nil {
return v.doVisitInOperator(ctx, scope)
}
logicalAndOp := ctx.LogicalAndOperator()
if logicalAndOp != nil {
return v.doVisitLogicalOperator(ctx, scope)
}
logicalOrOp := ctx.LogicalOrOperator()
if logicalOrOp != nil {
return v.doVisitLogicalOperator(ctx, scope)
}
variable := ctx.Variable()
if variable != nil {
@@ -1255,54 +1360,12 @@ func (v *visitor) doVisitExpression(ctx *fql.ExpressionContext, scope *scope) (c
return v.doVisitObjectLiteral(obj.(*fql.ObjectLiteralContext), scope)
}
funCall := ctx.FunctionCallExpression()
if funCall != nil {
return v.doVisitFunctionCallExpression(funCall.(*fql.FunctionCallExpressionContext), scope)
}
member := ctx.MemberExpression()
if member != nil {
return v.doVisitMemberExpression(member.(*fql.MemberExpressionContext), scope)
}
none := ctx.NoneLiteral()
if none != nil {
return v.doVisitNoneLiteral(none.(*fql.NoneLiteralContext))
}
arrOp := ctx.ArrayOperator()
if arrOp != nil {
return v.doVisitArrayOperator(ctx, scope)
}
inOp := ctx.InOperator()
if inOp != nil {
return v.doVisitInOperator(ctx, scope)
}
equalityOp := ctx.EqualityOperator()
if equalityOp != nil {
return v.doVisitEqualityOperator(ctx, scope)
}
logicalOp := ctx.LogicalOperator()
if logicalOp != nil {
return v.doVisitLogicalOperator(ctx, scope)
}
mathOp := ctx.MathOperator()
if mathOp != nil {
return v.doVisitMathOperator(ctx, scope)
}
questionCtx := ctx.QuestionMark()
if questionCtx != nil {