Skip to content

Commit

Permalink
Fix CQL parser to allow multiple AND-OR terms
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-jts committed Mar 4, 2024
1 parent 39c4736 commit a0d25e3
Show file tree
Hide file tree
Showing 6 changed files with 814 additions and 680 deletions.
15 changes: 10 additions & 5 deletions internal/cql/CQLParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@ options { tokenVocab=CqlLexer; contextSuperClass=CqlContext; }
#============================================================================*/

cqlFilter : booleanExpression EOF;
booleanExpression : booleanTerm ( OR booleanTerm )?;
booleanTerm : booleanFactor ( AND booleanFactor )?;
booleanFactor : ( NOT )? booleanPrimary;
booleanPrimary : predicate
booleanExpression
: LEFTPAREN booleanExpression RIGHTPAREN # BoolExprParen
| left=booleanExpression AND right=booleanExpression # BoolExprAnd
| left=booleanExpression OR right=booleanExpression # BoolExprOr
| NOT booleanExpression # BoolExprNot
| booleanTerm # BoolExprTerm
;
//booleanFactor : ( NOT )? booleanPrimary;
booleanTerm : predicate
| booleanLiteral
| LEFTPAREN booleanExpression RIGHTPAREN;
;

/*============================================================================
# CQL supports scalar, spatial, temporal and existence predicates.
Expand Down
62 changes: 44 additions & 18 deletions internal/cql/cql.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ package cql
limitations under the License.
*/

// Build grammar with: antlr -Dlanguage=Go -package cql CqlLexer.g4 CQLParser.g4
// Build grammar with: antlr -Dlanguage=Go -package cql CqlLexer.g4 CQLParser.g4

import (
"fmt"
Expand Down Expand Up @@ -79,7 +79,7 @@ func syntaxErrorMsg(input string, col int) string {
return msg
}

//======================================
// ======================================
type CqlErrorListener struct {
*antlr.DefaultErrorListener
errorCount int
Expand Down Expand Up @@ -164,7 +164,7 @@ func getNodeText(node antlr.TerminalNode) string {
return node.GetText()
}

//========================================
// ========================================
type CqlContext struct {
*antlr.BaseParserRuleContext
// SQL fragment for the context subtree
Expand Down Expand Up @@ -211,38 +211,64 @@ func (l *cqlListener) ExitCqlFilter(ctx *CqlFilterContext) {
l.sql = sqlFor(ctx.BooleanExpression())
}

/*
func (l *cqlListener) ExitBooleanExpression(ctx *BooleanExpressionContext) {
sql := sqlFor(ctx.BooleanTerm(0))
if ctx.OR() != nil {
term := sqlFor(ctx.BooleanTerm(1))
sql := sqlFor(ctx.BooleanFactor())
//sql := sqlFor(ctx.BooleanExpression(0))
if ctx.OR(0) != nil {
term := sqlFor(ctx.BooleanExpression(1))
sql = sql + " OR " + term
} else if ctx.LEFTPAREN() != nil {
sql = "(" + sqlFor(ctx.BooleanExpression(0)) + ")"
}
ctx.SetSql(sql)
}
*/

func (l *cqlListener) ExitBooleanTerm(ctx *BooleanTermContext) {
sql := sqlFor(ctx.BooleanFactor(0))
if ctx.AND() != nil {
fact := sqlFor(ctx.BooleanFactor(1))
sql = sql + " AND " + fact
func (l *cqlListener) ExitBoolExprTerm(ctx *BoolExprTermContext) {
sql := sqlFor(ctx.BooleanTerm())
ctx.SetSql(sql)
}

func (l *cqlListener) ExitBoolExprAnd(ctx *BoolExprAndContext) {
sql := sqlFor(ctx.left)
if ctx.right != nil {
sql = sql + " AND " + sqlFor(ctx.right)
}
ctx.SetSql(sql)
}

func (l *cqlListener) ExitBooleanFactor(ctx *BooleanFactorContext) {
sql := sqlFor(ctx.BooleanPrimary())
if ctx.NOT() != nil {
sql = " NOT " + sql
func (l *cqlListener) ExitBoolExprOr(ctx *BoolExprOrContext) {
sql := sqlFor(ctx.left)
if ctx.right != nil {
sql = sql + " OR " + sqlFor(ctx.right)
}
ctx.SetSql(sql)
}

func (l *cqlListener) ExitBooleanPrimary(ctx *BooleanPrimaryContext) {
func (l *cqlListener) ExitBoolExprParen(ctx *BoolExprParenContext) {
sql := "(" + sqlFor(ctx.BooleanExpression()) + ")"
ctx.SetSql(sql)
}

func (l *cqlListener) ExitBoolExprNot(ctx *BoolExprNotContext) {
sql := "NOT " + sqlFor(ctx.BooleanExpression())
ctx.SetSql(sql)
}

/*
func (l *cqlListener) ExitBooleanTerm(ctx *BooleanTermContext) {
sql := sqlFor(ctx.BooleanPrimary())
if ctx.NOT() != nil {
sql = " NOT " + sql
}
ctx.SetSql(sql)
}
*/
func (l *cqlListener) ExitBooleanTerm(ctx *BooleanTermContext) {
var sql string
if ctx.BooleanLiteral() != nil {
sql = getText(ctx.BooleanLiteral())
} else if ctx.LEFTPAREN() != nil {
sql = "(" + sqlFor(ctx.BooleanExpression()) + ")"
} else {
sql = sqlFor(ctx.Predicate())
}
Expand Down
Loading

0 comments on commit a0d25e3

Please sign in to comment.