You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kie.apache.org by ma...@apache.org on 2024/02/14 11:53:10 UTC
(incubator-kie-drools) 45/49: Move necessary files without any additional modifications
This is an automated email from the ASF dual-hosted git repository.
mariofusco pushed a commit to branch dev-new-parser
in repository https://gitbox.apache.org/repos/asf/incubator-kie-drools.git
commit 522df2e9af04808ead0927fe253fb71ad4642bac
Author: Jiří Locker <ji...@gmail.com>
AuthorDate: Mon Jan 15 21:25:22 2024 +0100
Move necessary files without any additional modifications
---
.../antlr4/org/drools/parser/DRL6Expressions.g4 | 836 +++++++++++++++++++++
.../java/org/drools/parser/DRLExpressions.java | 54 ++
.../main/java/org/drools/parser/DrlExprParser.java | 88 +++
.../parser/DroolsParserExceptionFactory.java | 380 ++++++++++
.../main/java/org/drools/parser/ParserHelper.java | 672 +++++++++++++++++
.../java/org/drools/parser/DRLExprParserTest.java | 270 +++++++
6 files changed, 2300 insertions(+)
diff --git a/drools-drl/drools-drl10-parser/src/main/antlr4/org/drools/parser/DRL6Expressions.g4 b/drools-drl/drools-drl10-parser/src/main/antlr4/org/drools/parser/DRL6Expressions.g4
new file mode 100644
index 0000000000..b531c38fef
--- /dev/null
+++ b/drools-drl/drools-drl10-parser/src/main/antlr4/org/drools/parser/DRL6Expressions.g4
@@ -0,0 +1,836 @@
+parser grammar DRL6Expressions;
+
+options {
+ language = Java;
+ tokenVocab = DRL6Lexer;
+ superClass=DRLExpressions;
+}
+
+@header {
+ package org.drools.drl.parser.lang;
+
+ import java.util.LinkedList;
+ import org.drools.drl.parser.DroolsParserException;
+ import org.drools.drl.parser.lang.ParserHelper;
+ import org.drools.drl.parser.lang.DroolsParserExceptionFactory;
+ import org.drools.drl.parser.lang.Location;
+
+ import org.drools.drl.ast.dsl.AnnotatedDescrBuilder;
+ import org.drools.drl.ast.dsl.AnnotationDescrBuilder;
+
+ import org.drools.drl.ast.descr.AtomicExprDescr;
+ import org.drools.drl.ast.descr.AnnotatedBaseDescr;
+ import org.drools.drl.ast.descr.AnnotationDescr;
+ import org.drools.drl.ast.descr.BaseDescr;
+ import org.drools.drl.ast.descr.ConstraintConnectiveDescr;
+ import org.drools.drl.ast.descr.RelationalExprDescr;
+ import org.drools.drl.ast.descr.BindingDescr;
+}
+
+@members {
+ private ParserHelper helper;
+
+ public DRL6Expressions(TokenStream input,
+ RecognizerSharedState state,
+ ParserHelper helper ) {
+ this( input,
+ state );
+ this.helper = helper;
+ }
+
+ public ParserHelper getHelper() { return helper; }
+ public boolean hasErrors() { return helper.hasErrors(); }
+ public List<DroolsParserException> getErrors() { return helper.getErrors(); }
+ public List<String> getErrorMessages() { return helper.getErrorMessages(); }
+ public void enableEditorInterface() { helper.enableEditorInterface(); }
+ public void disableEditorInterface() { helper.disableEditorInterface(); }
+ public LinkedList<DroolsSentence> getEditorInterface() { return helper.getEditorInterface(); }
+ public void reportError(RecognitionException ex) { helper.reportError( ex ); }
+ public void emitErrorMessage(String msg) {}
+
+ private boolean buildDescr;
+ private int inMap = 0;
+ private int ternOp = 0;
+ private boolean hasBindings;
+ public void setBuildDescr( boolean build ) { this.buildDescr = build; }
+ public boolean isBuildDescr() { return this.buildDescr; }
+
+ public void setLeftMostExpr( String value ) { helper.setLeftMostExpr( value ); }
+ public String getLeftMostExpr() { return helper.getLeftMostExpr(); }
+
+ public void setHasBindings( boolean value ) { this.hasBindings = value; }
+ public boolean hasBindings() { return this.hasBindings; }
+
+ private boolean isNotEOF() {
+ if (state.backtracking != 0){
+ return false;
+ }
+ if (input.get( input.index() - 1 ).getType() == DRL6Lexer.WS){
+ return true;
+ }
+ if (input.LA(-1) == DRL6Lexer.LEFT_PAREN){
+ return true;
+ }
+ return input.get( input.index() ).getType() != DRL6Lexer.EOF;
+ }
+
+ private boolean notStartWithNewline() {
+ int currentTokenIndex = input.index(); // current position in input stream
+ Token previousHiddenToken = input.get(currentTokenIndex - 1);
+ String previousHiddenTokenText = previousHiddenToken.getText();
+ return !previousHiddenTokenText.contains("\n");
+ }
+}
+
+// Alter code generation so catch-clauses get replace with
+// this action.
+@rulecatch {
+catch (RecognitionException re) {
+ throw re;
+}
+}
+
+// --------------------------------------------------------
+// GENERAL RULES
+// --------------------------------------------------------
+literal
+ : STRING { helper.emit($STRING, DroolsEditorType.STRING_CONST); }
+ | DECIMAL { helper.emit($DECIMAL, DroolsEditorType.NUMERIC_CONST); }
+ | HEX { helper.emit($HEX, DroolsEditorType.NUMERIC_CONST); }
+ | FLOAT { helper.emit($FLOAT, DroolsEditorType.NUMERIC_CONST); }
+ | BOOL { helper.emit($BOOL, DroolsEditorType.BOOLEAN_CONST); }
+ | NULL { helper.emit($NULL, DroolsEditorType.NULL_CONST); }
+ | TIME_INTERVAL { helper.emit($TIME_INTERVAL, DroolsEditorType.NULL_CONST); }
+ | STAR { helper.emit($STAR, DroolsEditorType.NUMERIC_CONST); } // this means "infinity" in Drools
+ ;
+
+operator returns [boolean negated, String opr]
+@init{ if ( isNotEOF() ) helper.emit( Location.LOCATION_LHS_INSIDE_CONDITION_OPERATOR ); helper.setHasOperator( true ); }
+@after{ if( state.backtracking == 0 && input.LA( 1 ) != DRL6Lexer.EOF) { helper.emit( Location.LOCATION_LHS_INSIDE_CONDITION_ARGUMENT ); } }
+ : x=TILDE?
+ ( op=EQUALS { $negated = false; $opr=($x != null ? $x.text : "")+$op.text; helper.emit($op, DroolsEditorType.SYMBOL); }
+ | op=NOT_EQUALS { $negated = false; $opr=($x != null ? $x.text : "")+$op.text; helper.emit($op, DroolsEditorType.SYMBOL); }
+ | rop=relationalOp { $negated = $rop.negated; $opr=($x != null ? $x.text : "")+$rop.opr; }
+ )
+ ;
+
+
+
+relationalOp returns [boolean negated, String opr, java.util.List<String> params]
+@init{ if ( isNotEOF() ) helper.emit( Location.LOCATION_LHS_INSIDE_CONDITION_OPERATOR ); helper.setHasOperator( true ); }
+@after{ if( state.backtracking == 0 && input.LA( 1 ) != DRL6Lexer.EOF) { helper.emit( Location.LOCATION_LHS_INSIDE_CONDITION_ARGUMENT ); } }
+ : ( op=LESS_EQUALS { $negated = false; $opr=$op.text; $params = null; helper.emit($op, DroolsEditorType.SYMBOL);}
+ | op=GREATER_EQUALS { $negated = false; $opr=$op.text; $params = null; helper.emit($op, DroolsEditorType.SYMBOL);}
+ | op=LESS { $negated = false; $opr=$op.text; $params = null; helper.emit($op, DroolsEditorType.SYMBOL);}
+ | op=GREATER { $negated = false; $opr=$op.text; $params = null; helper.emit($op, DroolsEditorType.SYMBOL);}
+ | xop=complexOp { $negated = false; $opr=$op.text; $params = null; helper.emit($op, DroolsEditorType.SYMBOL);}
+ | not_key nop=neg_operator_key { $negated = true; $opr=$nop.text;}
+ | cop=operator_key { $negated = false; $opr=$cop.text;}
+ )
+ ;
+
+complexOp returns [String opr]
+ : t=TILDE e=EQUALS_ASSIGN { $opr=$t.text+$e.text; }
+ ;
+
+typeList
+ : type (COMMA type)*
+ ;
+
+type
+ : tm=typeMatch
+ ;
+
+typeMatch
+ : (primitiveType) => ( primitiveType ((LEFT_SQUARE RIGHT_SQUARE)=> LEFT_SQUARE RIGHT_SQUARE)* )
+ | ( ID ((typeArguments)=>typeArguments)? (DOT ID ((typeArguments)=>typeArguments)? )* ((LEFT_SQUARE RIGHT_SQUARE)=> LEFT_SQUARE RIGHT_SQUARE)* )
+ ;
+
+typeArguments
+ : LESS typeArgument (COMMA typeArgument)* GREATER
+ ;
+
+typeArgument
+ : type
+ | QUESTION ((extends_key | super_key) type)?
+ ;
+
+// --------------------------------------------------------
+// EXPRESSIONS
+// --------------------------------------------------------
+// the following dymmy rule is to force the AT symbol to be
+// included in the follow set of the expression on the DFAs
+dummy
+ : expression ( AT | SEMICOLON | EOF | ID | RIGHT_PAREN ) ;
+
+dummy2
+ : relationalExpression EOF;
+
+// top level entry point for arbitrary expression parsing
+expression returns [BaseDescr result]
+ : left=conditionalExpression { if( buildDescr ) { $result = $left.result; } }
+ ((assignmentOperator) => op=assignmentOperator right=expression)?
+ ;
+
+conditionalExpression returns [BaseDescr result]
+ : left=conditionalOrExpression { if( buildDescr ) { $result = $left.result; } }
+ ternaryExpression?
+ ;
+
+ternaryExpression
+@init{ ternOp++; }
+ : QUESTION ts=expression COLON fs=expression
+ ;
+finally { ternOp--; }
+
+
+fullAnnotation [AnnotatedDescrBuilder inDescrBuilder] returns [AnnotationDescr result]
+@init{ String n = ""; AnnotationDescrBuilder annoBuilder = null; }
+ : AT name=ID { n = $name.text; } ( DOT x=ID { n += "." + $x.text; } )*
+ { if( buildDescr ) {
+ if ( inDescrBuilder == null ) {
+ $result = new AnnotationDescr( n );
+ } else {
+ annoBuilder = inDescrBuilder instanceof AnnotationDescrBuilder ?
+ ((AnnotationDescrBuilder) inDescrBuilder).newAnnotation( n ) : inDescrBuilder.newAnnotation( n );
+ $result = (AnnotationDescr) annoBuilder.getDescr();
+ }
+ }
+ }
+ annotationArgs[result, annoBuilder]
+ ;
+
+annotationArgs [AnnotationDescr descr, AnnotatedDescrBuilder inDescrBuilder]
+ : LEFT_PAREN
+ (
+ (ID EQUALS_ASSIGN) => annotationElementValuePairs[descr, inDescrBuilder]
+ | value=annotationValue[inDescrBuilder] { if ( buildDescr ) { $descr.setValue( $value.result ); } }
+ )?
+ RIGHT_PAREN
+ ;
+
+annotationElementValuePairs [AnnotationDescr descr, AnnotatedDescrBuilder inDescrBuilder]
+ : annotationElementValuePair[descr, inDescrBuilder] ( COMMA annotationElementValuePair[descr, inDescrBuilder] )*
+ ;
+
+annotationElementValuePair [AnnotationDescr descr, AnnotatedDescrBuilder inDescrBuilder]
+ : key=ID EQUALS_ASSIGN val=annotationValue[inDescrBuilder] { if ( buildDescr ) { $descr.setKeyValue( $key.text, $val.result ); } }
+ ;
+
+annotationValue[AnnotatedDescrBuilder inDescrBuilder] returns [Object result]
+ : exp=expression { if ( buildDescr ) $result = $exp.text; }
+ | annos=annotationArray[inDescrBuilder] { if ( buildDescr ) $result = $annos.result.toArray(); }
+ | anno=fullAnnotation[inDescrBuilder] { if ( buildDescr ) $result = $anno.result; }
+ ;
+
+annotationArray[AnnotatedDescrBuilder inDescrBuilder] returns [java.util.List result]
+@init { $result = new java.util.ArrayList();}
+ : LEFT_CURLY ( anno=annotationValue[inDescrBuilder] { $result.add( $anno.result ); }
+ ( COMMA anno=annotationValue[inDescrBuilder] { $result.add( $anno.result ); } )* )?
+ RIGHT_CURLY
+ ;
+
+
+
+conditionalOrExpression returns [BaseDescr result]
+ : left=conditionalAndExpression { if( buildDescr ) { $result = $left.result; } }
+ ( DOUBLE_PIPE
+ { if ( isNotEOF() ) helper.emit( Location.LOCATION_LHS_INSIDE_CONDITION_OPERATOR ); }
+ args=fullAnnotation[null]? right=conditionalAndExpression
+ { if( buildDescr ) {
+ ConstraintConnectiveDescr descr = ConstraintConnectiveDescr.newOr();
+ descr.addOrMerge( $result );
+ descr.addOrMerge( $right.result );
+ if ( args != null ) { descr.addAnnotation( $args.result ); }
+ $result = descr;
+ }
+ }
+ )*
+ ;
+
+conditionalAndExpression returns [BaseDescr result]
+ : left=inclusiveOrExpression { if( buildDescr ) { $result = $left.result; } }
+ ( DOUBLE_AMPER
+ { if ( isNotEOF() ) helper.emit( Location.LOCATION_LHS_INSIDE_CONDITION_OPERATOR ); }
+ args=fullAnnotation[null]? right=inclusiveOrExpression
+ { if( buildDescr ) {
+ ConstraintConnectiveDescr descr = ConstraintConnectiveDescr.newAnd();
+ descr.addOrMerge( $result );
+ descr.addOrMerge( $right.result );
+ if ( args != null ) { descr.addAnnotation( $args.result ); }
+ $result = descr;
+ }
+ }
+ )*
+ ;
+
+inclusiveOrExpression returns [BaseDescr result]
+ : left=exclusiveOrExpression { if( buildDescr ) { $result = $left.result; } }
+ ( PIPE right=exclusiveOrExpression
+ { if( buildDescr ) {
+ ConstraintConnectiveDescr descr = ConstraintConnectiveDescr.newIncOr();
+ descr.addOrMerge( $result );
+ descr.addOrMerge( $right.result );
+ $result = descr;
+ }
+ }
+ )*
+ ;
+
+exclusiveOrExpression returns [BaseDescr result]
+ : left=andExpression { if( buildDescr ) { $result = $left.result; } }
+ ( XOR right=andExpression
+ { if( buildDescr ) {
+ ConstraintConnectiveDescr descr = ConstraintConnectiveDescr.newXor();
+ descr.addOrMerge( $result );
+ descr.addOrMerge( $right.result );
+ $result = descr;
+ }
+ }
+ )*
+ ;
+
+andExpression returns [BaseDescr result]
+ : left=equalityExpression { if( buildDescr ) { $result = $left.result; } }
+ ( AMPER right=equalityExpression
+ { if( buildDescr ) {
+ ConstraintConnectiveDescr descr = ConstraintConnectiveDescr.newIncAnd();
+ descr.addOrMerge( $result );
+ descr.addOrMerge( $right.result );
+ $result = descr;
+ }
+ }
+ )*
+ ;
+
+equalityExpression returns [BaseDescr result]
+ : left=instanceOfExpression { if( buildDescr ) { $result = $left.result; } }
+ ( ( op=EQUALS | op=NOT_EQUALS )
+ { helper.setHasOperator( true );
+ if( input.LA( 1 ) != DRL6Lexer.EOF ) helper.emit( Location.LOCATION_LHS_INSIDE_CONDITION_ARGUMENT ); }
+ right=instanceOfExpression
+ { if( buildDescr ) {
+ $result = new RelationalExprDescr( $op.text, false, null, $left.result, $right.result );
+ }
+ }
+ )*
+ ;
+
+instanceOfExpression returns [BaseDescr result]
+ : left=inExpression { if( buildDescr ) { $result = $left.result; } }
+ ( op=instanceof_key
+ { helper.setHasOperator( true );
+ if( input.LA( 1 ) != DRL6Lexer.EOF ) helper.emit( Location.LOCATION_LHS_INSIDE_CONDITION_ARGUMENT ); }
+ right=type
+ { if( buildDescr ) {
+ $result = new RelationalExprDescr( $op.text, false, null, $left.result, new AtomicExprDescr($right.text) );
+ }
+ }
+ )?
+ ;
+
+inExpression returns [BaseDescr result]
+@init { ConstraintConnectiveDescr descr = null; BaseDescr leftDescr = null; BindingDescr binding = null; }
+@after { if( binding != null && descr != null ) descr.addOrMerge( binding ); }
+ : left=relationalExpression
+ { if( buildDescr ) { $result = $left.result; }
+ if( $left.result instanceof BindingDescr ) {
+ binding = (BindingDescr)$left.result;
+ leftDescr = new AtomicExprDescr( binding.getExpression() );
+ } else {
+ leftDescr = $left.result;
+ }
+ }
+ ((not_key in_key)=> not_key in=in_key LEFT_PAREN
+ { helper.emit( Location.LOCATION_LHS_INSIDE_CONDITION_ARGUMENT ); }
+ e1=expression
+ { descr = ConstraintConnectiveDescr.newAnd();
+ RelationalExprDescr rel = new RelationalExprDescr( "!=", false, null, leftDescr, $e1.result );
+ descr.addOrMerge( rel );
+ $result = descr;
+ }
+ (COMMA e2=expression
+ { RelationalExprDescr rel = new RelationalExprDescr( "!=", false, null, leftDescr, $e2.result );
+ descr.addOrMerge( rel );
+ }
+ )* RIGHT_PAREN
+ { helper.emit( Location.LOCATION_LHS_INSIDE_CONDITION_END ); }
+ | in=in_key LEFT_PAREN
+ { helper.emit( Location.LOCATION_LHS_INSIDE_CONDITION_ARGUMENT ); }
+ e1=expression
+ { descr = ConstraintConnectiveDescr.newOr();
+ RelationalExprDescr rel = new RelationalExprDescr( "==", false, null, leftDescr, $e1.result );
+ descr.addOrMerge( rel );
+ $result = descr;
+ }
+ (COMMA e2=expression
+ { RelationalExprDescr rel = new RelationalExprDescr( "==", false, null, leftDescr, $e2.result );
+ descr.addOrMerge( rel );
+ }
+ )* RIGHT_PAREN
+ { helper.emit( Location.LOCATION_LHS_INSIDE_CONDITION_END ); }
+ )?
+ ;
+
+relationalExpression returns [BaseDescr result]
+scope { BaseDescr lsd; }
+@init { $relationalExpression::lsd = null; }
+ : left=shiftExpression
+ { if( buildDescr ) {
+ if ( $left.result == null ) {
+ $result = new AtomicExprDescr( $left.text );
+ } else if ( $left.result instanceof AtomicExprDescr ) {
+ if ( $left.text.equals(((AtomicExprDescr)$left.result).getExpression()) ) {
+ $result = $left.result;
+ } else {
+ $result = new AtomicExprDescr( $left.text ) ;
+ }
+ } else if ( $left.result instanceof BindingDescr ) {
+ if ( $left.text.equals(((BindingDescr)$left.result).getExpression()) ) {
+ $result = $left.result;
+ } else {
+ BindingDescr bind = (BindingDescr) $left.result;
+ int offset = bind.isUnification() ? 2 : 1;
+ String fullExpression = $left.text.substring( $left.text.indexOf( ":" ) + offset ).trim();
+ $result = new BindingDescr( bind.getVariable(), bind.getExpression(), fullExpression, bind.isUnification() );
+ }
+ } else {
+ $result = $left.result;
+ }
+ $relationalExpression::lsd = $result;
+ }
+ }
+ ( ( operator | LEFT_PAREN )=> right=orRestriction
+ { if( buildDescr ) {
+ $result = $right.result;
+ $relationalExpression::lsd = $result;
+ }
+ }
+ )*
+ ;
+
+orRestriction returns [BaseDescr result]
+ : left=andRestriction { if( buildDescr ) { $result = $left.result; } }
+ ( (DOUBLE_PIPE fullAnnotation[null]? andRestriction)=>lop=DOUBLE_PIPE args=fullAnnotation[null]? right=andRestriction
+ { if( buildDescr ) {
+ ConstraintConnectiveDescr descr = ConstraintConnectiveDescr.newOr();
+ descr.addOrMerge( $result );
+ descr.addOrMerge( $right.result );
+ if ( args != null ) { descr.addAnnotation( $args.result ); }
+ $result = descr;
+ }
+ }
+ )* EOF?
+ ;
+
+andRestriction returns [BaseDescr result]
+ : left=singleRestriction { if( buildDescr ) { $result = $left.result; } }
+ ( (DOUBLE_AMPER fullAnnotation[null]? operator)=>lop=DOUBLE_AMPER
+ { if ( isNotEOF() ) helper.emit( Location.LOCATION_LHS_INSIDE_CONDITION_OPERATOR ); }
+ args=fullAnnotation[null]?right=singleRestriction
+ { if( buildDescr ) {
+ ConstraintConnectiveDescr descr = ConstraintConnectiveDescr.newAnd();
+ descr.addOrMerge( $result );
+ descr.addOrMerge( $right.result );
+ if ( args != null ) { descr.addAnnotation( $args.result ); }
+ $result = descr;
+ }
+ }
+ )*
+ ;
+
+singleRestriction returns [BaseDescr result]
+ : op=operator
+ { helper.emit( Location.LOCATION_LHS_INSIDE_CONDITION_ARGUMENT ); }
+ ( (squareArguments shiftExpression)=> sa=squareArguments value=shiftExpression
+ | value=shiftExpression
+ )
+ { if( buildDescr ) {
+ BaseDescr descr = ( $value.result != null &&
+ ( (!($value.result instanceof AtomicExprDescr)) ||
+ ($value.text.equals(((AtomicExprDescr)$value.result).getExpression())) )) ?
+ $value.result :
+ new AtomicExprDescr( $value.text ) ;
+ $result = new RelationalExprDescr( $op.opr, $op.negated, $sa.args, $relationalExpression::lsd, descr );
+ if( $relationalExpression::lsd instanceof BindingDescr ) {
+ $relationalExpression::lsd = new AtomicExprDescr( ((BindingDescr)$relationalExpression::lsd).getExpression() );
+ }
+ }
+ helper.emit( Location.LOCATION_LHS_INSIDE_CONDITION_END );
+ }
+ | LEFT_PAREN or=orRestriction RIGHT_PAREN { $result = $or.result; }
+ ;
+
+
+
+shiftExpression returns [BaseDescr result]
+ : left=additiveExpression { if( buildDescr ) { $result = $left.result; } }
+ ( (shiftOp)=>shiftOp additiveExpression )*
+ ;
+
+shiftOp
+ : ( LESS LESS
+ | GREATER GREATER GREATER
+ | GREATER GREATER )
+ ;
+
+additiveExpression returns [BaseDescr result]
+ : left=multiplicativeExpression { if( buildDescr ) { $result = $left.result; } }
+ ( (PLUS|MINUS)=> (PLUS | MINUS) multiplicativeExpression )*
+ ;
+
+multiplicativeExpression returns [BaseDescr result]
+ : left=unaryExpression { if( buildDescr ) { $result = $left.result; } }
+ ( ( STAR | DIV | MOD ) unaryExpression )*
+ ;
+
+unaryExpression returns [BaseDescr result]
+ : PLUS ue=unaryExpression
+ { if( buildDescr ) {
+ $result = $ue.result;
+ if( $result instanceof AtomicExprDescr ) {
+ ((AtomicExprDescr)$result).setExpression( "+" + ((AtomicExprDescr)$result).getExpression() );
+ }
+ } }
+ | MINUS ue=unaryExpression
+ { if( buildDescr ) {
+ $result = $ue.result;
+ if( $result instanceof AtomicExprDescr ) {
+ ((AtomicExprDescr)$result).setExpression( "-" + ((AtomicExprDescr)$result).getExpression() );
+ }
+ } }
+ | INCR primary
+ | DECR primary
+ | left=unaryExpressionNotPlusMinus { if( buildDescr ) { $result = $left.result; } }
+ ;
+
+unaryExpressionNotPlusMinus returns [BaseDescr result]
+@init { boolean isLeft = false; BindingDescr bind = null;}
+ : TILDE unaryExpression
+ | NEGATION ue=unaryExpression
+ {
+ if( buildDescr && ue != null ) {
+ $result = ue.negate();
+ }
+ }
+ | (castExpression)=>castExpression
+ | (backReferenceExpression)=>backReferenceExpression
+ | { isLeft = helper.getLeftMostExpr() == null;}
+ ( ({inMap == 0 && ternOp == 0 && input.LA(2) == DRL6Lexer.COLON}? (var=ID COLON
+ { hasBindings = true; helper.emit($var, DroolsEditorType.IDENTIFIER_VARIABLE); helper.emit($COLON, DroolsEditorType.SYMBOL); if( buildDescr ) { bind = new BindingDescr($var.text, null, false); helper.setStart( bind, $var ); } } ))
+ | ({inMap == 0 && ternOp == 0 && input.LA(2) == DRL6Lexer.UNIFY}? (var=ID UNIFY
+ { hasBindings = true; helper.emit($var, DroolsEditorType.IDENTIFIER_VARIABLE); helper.emit($UNIFY, DroolsEditorType.SYMBOL); if( buildDescr ) { bind = new BindingDescr($var.text, null, true); helper.setStart( bind, $var ); } } ))
+ )?
+
+ ( (xpathSeparator ID)=>left2=xpathPrimary { if( buildDescr ) { $result = $left2.result; } }
+ | left1=primary { if( buildDescr ) { $result = $left1.result; } }
+ )
+
+ ((selector)=>selector)*
+ {
+ if( buildDescr ) {
+ String expr = $unaryExpressionNotPlusMinus.text;
+ if( isLeft ) {
+ helper.setLeftMostExpr( expr );
+ }
+ if( bind != null ) {
+ if( bind.isUnification() ) {
+ expr = expr.substring( expr.indexOf( ":=" ) + 2 ).trim();
+ } else {
+ expr = expr.substring( expr.indexOf( ":" ) + 1 ).trim();
+ }
+ bind.setExpressionAndBindingField( expr );
+ helper.setEnd( bind );
+ $result = bind;
+ }
+ }
+ }
+ ((INCR|DECR)=> (INCR|DECR))?
+ ;
+
+castExpression
+ : (LEFT_PAREN primitiveType) => LEFT_PAREN primitiveType RIGHT_PAREN expr=unaryExpression
+ | (LEFT_PAREN type) => LEFT_PAREN type RIGHT_PAREN unaryExpressionNotPlusMinus
+ ;
+
+backReferenceExpression
+ : (DOT DOT DIV) => (DOT DOT DIV)+ unaryExpressionNotPlusMinus
+ ;
+
+primitiveType
+ : boolean_key
+ | char_key
+ | byte_key
+ | short_key
+ | int_key
+ | long_key
+ | float_key
+ | double_key
+ ;
+
+xpathSeparator
+ : DIV
+ | QUESTION_DIV
+ ;
+
+xpathPrimary returns [BaseDescr result]
+ : xpathChunk ({notStartWithNewline()}? xpathChunk)*
+ ;
+
+xpathChunk returns [BaseDescr result]
+ : (xpathSeparator ID)=> xpathSeparator ID (DOT ID)* (HASH ID)? (LEFT_SQUARE xpathExpressionList RIGHT_SQUARE)?
+ ;
+
+xpathExpressionList returns [java.util.List<String> exprs]
+@init { $exprs = new java.util.ArrayList<String>();}
+ : f=expression { $exprs.add( $f.text ); }
+ (COMMA s=expression { $exprs.add( $s.text ); })*
+ ;
+
+primary returns [BaseDescr result]
+ : (LEFT_PAREN)=> expr=parExpression { if( buildDescr ) { $result = $expr.result; } }
+ | (nonWildcardTypeArguments)=> nonWildcardTypeArguments (explicitGenericInvocationSuffix | this_key arguments)
+ | (literal)=> literal { if( buildDescr ) { $result = new AtomicExprDescr( $literal.text, true ); } }
+ //| this_key ({!helper.validateSpecialID(2)}?=> DOT ID)* ({helper.validateIdentifierSufix()}?=> identifierSuffix)?
+ | (super_key)=> super_key superSuffix
+ | (new_key)=> new_key creator
+ | (primitiveType)=> primitiveType (LEFT_SQUARE RIGHT_SQUARE)* DOT class_key
+ //| void_key DOT class_key
+ | (inlineMapExpression)=> inlineMapExpression
+ | (inlineListExpression)=> inlineListExpression
+ | (ID)=>i1=ID { helper.emit($i1, DroolsEditorType.IDENTIFIER); }
+ (
+ ( (DOT ID)=>d=DOT i2=ID { helper.emit($d, DroolsEditorType.SYMBOL); helper.emit($i2, DroolsEditorType.IDENTIFIER); } )
+ |
+ ( ((DOT|NULL_SAFE_DOT) LEFT_PAREN)=>d=(DOT|NULL_SAFE_DOT) LEFT_PAREN { helper.emit($d, DroolsEditorType.SYMBOL); helper.emit($LEFT_PAREN, DroolsEditorType.SYMBOL); }
+ expression (COMMA { helper.emit($COMMA, DroolsEditorType.SYMBOL); } expression)*
+ RIGHT_PAREN { helper.emit($RIGHT_PAREN, DroolsEditorType.SYMBOL); }
+ )
+ |
+ ( (HASH ID)=>h=HASH i2=ID { helper.emit($h, DroolsEditorType.SYMBOL); helper.emit($i2, DroolsEditorType.IDENTIFIER); } )
+ |
+ ( (NULL_SAFE_DOT ID)=>n=NULL_SAFE_DOT i2=ID { helper.emit($n, DroolsEditorType.SYMBOL); helper.emit($i2, DroolsEditorType.IDENTIFIER); } )
+ )* ((identifierSuffix)=>identifierSuffix)?
+ ;
+
+inlineListExpression
+ : LEFT_SQUARE expressionList? RIGHT_SQUARE
+ ;
+
+inlineMapExpression
+@init{ inMap++; }
+ : LEFT_SQUARE mapExpressionList RIGHT_SQUARE
+ ;
+finally { inMap--; }
+
+mapExpressionList
+ : mapEntry (COMMA mapEntry)*
+ ;
+
+mapEntry
+ : expression COLON expression
+ ;
+
+parExpression returns [BaseDescr result]
+ : LEFT_PAREN expr=expression RIGHT_PAREN
+ { if( buildDescr ) {
+ $result = $expr.result;
+ if( $result instanceof AtomicExprDescr ) {
+ ((AtomicExprDescr)$result).setExpression("(" +((AtomicExprDescr)$result).getExpression() + ")" );
+ }
+ }
+ }
+ ;
+
+identifierSuffix
+ : (LEFT_SQUARE RIGHT_SQUARE)=>(LEFT_SQUARE { helper.emit($LEFT_SQUARE, DroolsEditorType.SYMBOL); }
+ RIGHT_SQUARE { helper.emit($RIGHT_SQUARE, DroolsEditorType.SYMBOL); } )+
+ DOT { helper.emit($DOT, DroolsEditorType.SYMBOL); } class_key
+ | ((LEFT_SQUARE) => LEFT_SQUARE { helper.emit($LEFT_SQUARE, DroolsEditorType.SYMBOL); }
+ expression
+ RIGHT_SQUARE { helper.emit($RIGHT_SQUARE, DroolsEditorType.SYMBOL); } )+ // can also be matched by selector, but do here
+ | arguments
+// | DOT class_key
+// | DOT explicitGenericInvocation
+// | DOT this_key
+// | DOT super_key arguments
+// | DOT new_key (nonWildcardTypeArguments)? innerCreator
+ ;
+
+creator
+ : nonWildcardTypeArguments? createdName
+ (arrayCreatorRest | classCreatorRest)
+ ;
+
+createdName
+ : ID typeArguments?
+ ( DOT ID typeArguments?)*
+ | primitiveType
+ ;
+
+innerCreator
+ : {!(helper.validateIdentifierKey(DroolsSoftKeywords.INSTANCEOF))}?=> ID classCreatorRest
+ ;
+
+arrayCreatorRest
+ : LEFT_SQUARE
+ ( RIGHT_SQUARE (LEFT_SQUARE RIGHT_SQUARE)* arrayInitializer
+ | expression RIGHT_SQUARE ({!helper.validateLT(2,"]")}?=>LEFT_SQUARE expression RIGHT_SQUARE)* ((LEFT_SQUARE RIGHT_SQUARE)=> LEFT_SQUARE RIGHT_SQUARE)*
+ )
+ ;
+
+variableInitializer
+ : arrayInitializer
+ | expression
+ ;
+
+arrayInitializer
+ : LEFT_CURLY (variableInitializer (COMMA variableInitializer)* (COMMA)? )? RIGHT_CURLY
+ ;
+
+classCreatorRest
+ : arguments //classBody? //sotty: restored classBody to allow for inline, anonymous classes
+ ;
+
+explicitGenericInvocation
+ : nonWildcardTypeArguments arguments
+ ;
+
+nonWildcardTypeArguments
+ : LESS typeList GREATER
+ ;
+
+explicitGenericInvocationSuffix
+ : super_key superSuffix
+ | ID arguments
+ ;
+
+selector
+ : (DOT super_key)=>DOT { helper.emit($DOT, DroolsEditorType.SYMBOL); } super_key superSuffix
+ | (DOT new_key)=>DOT { helper.emit($DOT, DroolsEditorType.SYMBOL); } new_key (nonWildcardTypeArguments)? innerCreator
+ | (DOT ID)=>DOT { helper.emit($DOT, DroolsEditorType.SYMBOL); }
+ ID { helper.emit($ID, DroolsEditorType.IDENTIFIER); }
+ ((LEFT_PAREN) => arguments)?
+ | (NULL_SAFE_DOT ID)=>NULL_SAFE_DOT { helper.emit($NULL_SAFE_DOT, DroolsEditorType.SYMBOL); }
+ ID { helper.emit($ID, DroolsEditorType.IDENTIFIER); }
+ ((LEFT_PAREN) => arguments)?
+ //| DOT this_key
+ | (LEFT_SQUARE)=>LEFT_SQUARE { helper.emit($LEFT_SQUARE, DroolsEditorType.SYMBOL); }
+ expression
+ RIGHT_SQUARE { helper.emit($RIGHT_SQUARE, DroolsEditorType.SYMBOL); }
+ ;
+
+superSuffix
+ : arguments
+ | DOT ID ((LEFT_PAREN) => arguments)?
+ ;
+
+squareArguments returns [java.util.List<String> args]
+ : LEFT_SQUARE (el=expressionList { $args = $el.exprs; })? RIGHT_SQUARE
+ ;
+
+arguments
+ : LEFT_PAREN { helper.emit($LEFT_PAREN, DroolsEditorType.SYMBOL); }
+ expressionList?
+ RIGHT_PAREN { helper.emit($RIGHT_PAREN, DroolsEditorType.SYMBOL); }
+ ;
+
+expressionList returns [java.util.List<String> exprs]
+@init { $exprs = new java.util.ArrayList<String>();}
+ : f=expression { $exprs.add( $f.text ); }
+ (COMMA s=expression { $exprs.add( $s.text ); })*
+ ;
+
+assignmentOperator
+ : EQUALS_ASSIGN
+ | PLUS_ASSIGN
+ | MINUS_ASSIGN
+ | MULT_ASSIGN
+ | DIV_ASSIGN
+ | AND_ASSIGN
+ | OR_ASSIGN
+ | XOR_ASSIGN
+ | MOD_ASSIGN
+ | LESS LESS EQUALS_ASSIGN
+ | (GREATER GREATER GREATER)=> GREATER GREATER GREATER EQUALS_ASSIGN
+ | (GREATER GREATER)=> GREATER GREATER EQUALS_ASSIGN
+ ;
+
+// --------------------------------------------------------
+// KEYWORDS
+// --------------------------------------------------------
+extends_key
+ : {(helper.validateIdentifierKey(DroolsSoftKeywords.EXTENDS))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
+
+super_key
+ : {(helper.validateIdentifierKey(DroolsSoftKeywords.SUPER))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
+
+instanceof_key
+ : {(helper.validateIdentifierKey(DroolsSoftKeywords.INSTANCEOF))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
+
+boolean_key
+ : {(helper.validateIdentifierKey(DroolsSoftKeywords.BOOLEAN))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
+
+char_key
+ : {(helper.validateIdentifierKey(DroolsSoftKeywords.CHAR))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
+
+byte_key
+ : {(helper.validateIdentifierKey(DroolsSoftKeywords.BYTE))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
+
+short_key
+ : {(helper.validateIdentifierKey(DroolsSoftKeywords.SHORT))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
+
+int_key
+ : {(helper.validateIdentifierKey(DroolsSoftKeywords.INT))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
+
+float_key
+ : {(helper.validateIdentifierKey(DroolsSoftKeywords.FLOAT))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
+
+long_key
+ : {(helper.validateIdentifierKey(DroolsSoftKeywords.LONG))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
+
+double_key
+ : {(helper.validateIdentifierKey(DroolsSoftKeywords.DOUBLE))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
+
+void_key
+ : {(helper.validateIdentifierKey(DroolsSoftKeywords.VOID))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
+
+this_key
+ : {(helper.validateIdentifierKey(DroolsSoftKeywords.THIS))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
+
+class_key
+ : {(helper.validateIdentifierKey(DroolsSoftKeywords.CLASS))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
+
+new_key
+ : {(helper.validateIdentifierKey(DroolsSoftKeywords.NEW))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
+
+not_key
+ : {(helper.validateIdentifierKey(DroolsSoftKeywords.NOT))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
+
+in_key
+ : {(helper.validateIdentifierKey(DroolsSoftKeywords.IN))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
+
+operator_key
+ : {(helper.isPluggableEvaluator(false))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
+
+neg_operator_key
+ : {(helper.isPluggableEvaluator(true))}?=> id=ID { helper.emit($ID, DroolsEditorType.KEYWORD); }
+ ;
diff --git a/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLExpressions.java b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLExpressions.java
new file mode 100644
index 0000000000..ba811347b2
--- /dev/null
+++ b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DRLExpressions.java
@@ -0,0 +1,54 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.drools.parser;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.antlr.runtime.Parser;
+import org.antlr.runtime.RecognitionException;
+import org.antlr.runtime.RecognizerSharedState;
+import org.antlr.runtime.TokenStream;
+import org.drools.drl.ast.descr.BaseDescr;
+import org.drools.drl.parser.DroolsParserException;
+
+public abstract class DRLExpressions extends Parser {
+ public DRLExpressions(TokenStream input, RecognizerSharedState state) {
+ super(input, state);
+ }
+
+ public abstract void setBuildDescr( boolean build );
+ public abstract boolean isBuildDescr();
+
+ public abstract void setLeftMostExpr( String value );
+ public abstract String getLeftMostExpr();
+
+ public abstract void setHasBindings( boolean value );
+ public abstract boolean hasBindings();
+
+ public abstract BaseDescr conditionalOrExpression() throws RecognitionException;
+
+ public abstract ParserHelper getHelper();
+ public abstract boolean hasErrors();
+ public abstract List<DroolsParserException> getErrors();
+ public abstract List<String> getErrorMessages();
+ public abstract void enableEditorInterface();
+ public abstract void disableEditorInterface();
+ public abstract LinkedList<DroolsSentence> getEditorInterface();
+}
diff --git a/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DrlExprParser.java b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DrlExprParser.java
new file mode 100644
index 0000000000..7d624224cb
--- /dev/null
+++ b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DrlExprParser.java
@@ -0,0 +1,88 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.drools.parser;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.antlr.runtime.ANTLRStringStream;
+import org.antlr.runtime.CommonTokenStream;
+import org.antlr.runtime.RecognitionException;
+import org.antlr.runtime.RecognizerSharedState;
+import org.drools.drl.ast.descr.BaseDescr;
+import org.drools.drl.ast.descr.ConstraintConnectiveDescr;
+import org.drools.drl.parser.lang.ParserHelper;
+import org.kie.internal.builder.conf.LanguageLevelOption;
+
+/**
+ * This is a helper class that provides helper methods to parse expressions
+ * using both the DRLExpressions parser and the DRLExprTree parser.
+ */
+public class DrlExprParser {
+
+ private ParserHelper helper = null;
+
+ private final LanguageLevelOption languageLevel;
+
+ public DrlExprParser(LanguageLevelOption languageLevel) {
+ this.languageLevel = languageLevel;
+ }
+
+ /** Parse an expression from text */
+ public ConstraintConnectiveDescr parse( final String text ) {
+ ConstraintConnectiveDescr constraint = null;
+ try {
+ DRLLexer lexer = DRLFactory.getDRLLexer(new ANTLRStringStream(text), languageLevel);
+ CommonTokenStream input = new CommonTokenStream( lexer );
+ RecognizerSharedState state = new RecognizerSharedState();
+ helper = new ParserHelper( input, state, languageLevel );
+ DRLExpressions parser = DRLFactory.getDRLExpressions(input, state, helper, languageLevel);
+ parser.setBuildDescr( true );
+ parser.setLeftMostExpr( null ); // setting initial value just in case
+ BaseDescr expr = parser.conditionalOrExpression();
+ if ( expr != null && !parser.hasErrors() ) {
+ constraint = ConstraintConnectiveDescr.newAnd();
+ constraint.addOrMerge( expr );
+ }
+ } catch ( RecognitionException e ) {
+ helper.reportError( e );
+ }
+ return constraint;
+ }
+
+ public String getLeftMostExpr() {
+ return helper != null ? helper.getLeftMostExpr() : null;
+ }
+
+ /**
+ * @return true if there were parser errors.
+ */
+ public boolean hasErrors() {
+ return helper != null && helper.hasErrors();
+ }
+
+ /**
+ * @return a list of errors found while parsing.
+ */
+ @SuppressWarnings("unchecked")
+ public List<DroolsParserException> getErrors() {
+ return helper != null ? helper.getErrors() : Collections.EMPTY_LIST;
+ }
+
+}
diff --git a/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DroolsParserExceptionFactory.java b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DroolsParserExceptionFactory.java
new file mode 100644
index 0000000000..f94eab73cc
--- /dev/null
+++ b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/DroolsParserExceptionFactory.java
@@ -0,0 +1,380 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.drools.parser;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.antlr.runtime.BitSet;
+import org.antlr.runtime.EarlyExitException;
+import org.antlr.runtime.FailedPredicateException;
+import org.antlr.runtime.MismatchedNotSetException;
+import org.antlr.runtime.MismatchedSetException;
+import org.antlr.runtime.MismatchedTokenException;
+import org.antlr.runtime.MismatchedTreeNodeException;
+import org.antlr.runtime.NoViableAltException;
+import org.antlr.runtime.RecognitionException;
+import org.antlr.runtime.Token;
+import org.drools.drl.parser.DRLFactory;
+import org.drools.drl.parser.DroolsParserException;
+import org.kie.internal.builder.conf.LanguageLevelOption;
+
+/**
+ * Helper class that generates DroolsParserException with user friendly error
+ * messages.
+ *
+ * @see DroolsParserException
+ */
+public class DroolsParserExceptionFactory {
+ public final static String MISMATCHED_TOKEN_MESSAGE_COMPLETE = "Line %1$d:%2$d mismatched input '%3$s' expecting '%4$s'%5$s";
+ public final static String MISMATCHED_TOKEN_MESSAGE_PART = "Line %1$d:%2$d mismatched input '%3$s'%4$s";
+ public final static String MISMATCHED_TREE_NODE_MESSAGE_COMPLETE = "Line %1$d:%2$d mismatched tree node '%3$s' expecting '%4$s'%5$s";
+ public final static String MISMATCHED_TREE_NODE_MESSAGE_PART = "Line %1$d:%2$d mismatched tree node '%3$s'%4$s";
+ public final static String NO_VIABLE_ALT_MESSAGE = "Line %1$d:%2$d no viable alternative at input '%3$s'%4$s";
+ public final static String EARLY_EXIT_MESSAGE = "Line %1$d:%2$d required (...)+ loop did not match anything at input '%3$s'%4$s";
+ public final static String MISMATCHED_SET_MESSAGE = "Line %1$d:%2$d mismatched input '%3$s' expecting one of the following tokens: '%4$s'%5$s.";
+ public final static String MISMATCHED_NOT_SET_MESSAGE = "Line %1$d:%2$d mismatched input '%3$s' not expecting any of the following tokens: '%4$s'%5$s";
+ public final static String FAILED_PREDICATE_MESSAGE = "Line %1$d:%2$d rule '%3$s' failed predicate: {%4$s}?%5$s";
+ public final static String TRAILING_SEMI_COLON_NOT_ALLOWED_MESSAGE = "Line %1$d:%2$d trailing semi-colon not allowed%3$s";
+ public final static String PARSER_LOCATION_MESSAGE_COMPLETE = " in %1$s %2$s";
+ public final static String PARSER_LOCATION_MESSAGE_PART = " in %1$s";
+ public final static String UNEXPECTED_EXCEPTION = "Line %1$d:%2$d unexpected exception at input '%3$s'. Exception: %4$s. Stack trace:\n %5$s";
+
+ private final Collection<Map<DroolsParaphraseTypes, String>> paraphrases;
+
+ // TODO: need to deal with this array
+ private String[] tokenNames = null;
+
+ private final LanguageLevelOption languageLevel;
+
+ /**
+ * DroolsParserErrorMessages constructor.
+ *
+ * @param tokenNames
+ * tokenNames generated by ANTLR
+ * @param paraphrases
+ * paraphrases parser structure
+ */
+ public DroolsParserExceptionFactory(Collection<Map<DroolsParaphraseTypes, String>> paraphrases,
+ LanguageLevelOption languageLevel) {
+ this.paraphrases = paraphrases;
+ this.languageLevel = languageLevel;
+ }
+
+ /**
+ * This method creates a DroolsParserException for trailing semicolon
+ * exception, full of information.
+ *
+ * @param line
+ * line number
+ * @param column
+ * column position
+ * @param offset
+ * char offset
+ * @return DroolsParserException filled.
+ */
+ public DroolsParserException createTrailingSemicolonException( int line,
+ int column,
+ int offset ) {
+ String message = String
+ .format(
+ TRAILING_SEMI_COLON_NOT_ALLOWED_MESSAGE,
+ line,
+ column,
+ formatParserLocation() );
+
+ return new DroolsParserException( "ERR 104",
+ message,
+ line,
+ column,
+ offset,
+ null );
+ }
+
+ /**
+ * This method creates a DroolsParserException full of information.
+ *
+ * @param e
+ * original exception
+ * @return DroolsParserException filled.
+ */
+ public DroolsParserException createDroolsException( RecognitionException e ) {
+ List<String> codeAndMessage = createErrorMessage( e );
+ return new DroolsParserException( codeAndMessage.get( 1 ),
+ codeAndMessage
+ .get( 0 ),
+ e.line,
+ e.charPositionInLine,
+ e.index,
+ e );
+ }
+
+ /**
+ * This will take a RecognitionException, and create a sensible error
+ * message out of it
+ */
+ private List<String> createErrorMessage( RecognitionException e ) {
+ List<String> codeAndMessage = new ArrayList<>( 2 );
+ String message;
+ if ( e instanceof MismatchedTokenException ) {
+ MismatchedTokenException mte = (MismatchedTokenException) e;
+ String expecting = mte instanceof DroolsMismatchedTokenException ? ((DroolsMismatchedTokenException)mte).getTokenText() : getBetterToken( mte.expecting );
+ if ( tokenNames != null && mte.expecting >= 0 && mte.expecting < tokenNames.length ) {
+ message = String
+ .format(
+ MISMATCHED_TOKEN_MESSAGE_COMPLETE,
+ e.line,
+ e.charPositionInLine,
+ getBetterToken( e.token ),
+ expecting,
+ formatParserLocation() );
+ codeAndMessage.add( message );
+ codeAndMessage.add( "ERR 102" );
+ } else {
+ message = String
+ .format(
+ MISMATCHED_TOKEN_MESSAGE_PART,
+ e.line,
+ e.charPositionInLine,
+ getBetterToken( e.token ),
+ formatParserLocation() );
+ codeAndMessage.add( message );
+ codeAndMessage.add( "ERR 102" );
+ }
+ } else if ( e instanceof MismatchedTreeNodeException ) {
+ MismatchedTreeNodeException mtne = (MismatchedTreeNodeException) e;
+ if ( mtne.expecting >= 0 && mtne.expecting < tokenNames.length ) {
+ message = String
+ .format(
+ MISMATCHED_TREE_NODE_MESSAGE_COMPLETE,
+ e.line,
+ e.charPositionInLine,
+ getBetterToken( e.token ),
+ getBetterToken( mtne.expecting ),
+ formatParserLocation() );
+ codeAndMessage.add( message );
+ codeAndMessage.add( "ERR 106" );
+ } else {
+ message = String
+ .format(
+ MISMATCHED_TREE_NODE_MESSAGE_PART,
+ e.line,
+ e.charPositionInLine,
+ getBetterToken( e.token ),
+ formatParserLocation() );
+ codeAndMessage.add( message );
+ codeAndMessage.add( "ERR 106" );
+ }
+ } else if ( e instanceof NoViableAltException ) {
+ // NoViableAltException nvae = (NoViableAltException) e;
+ message = String.format(
+ NO_VIABLE_ALT_MESSAGE,
+ e.line,
+ e.charPositionInLine,
+ getBetterToken( e.token ),
+ formatParserLocation() );
+ codeAndMessage.add( message );
+ codeAndMessage.add( "ERR 101" );
+ } else if ( e instanceof EarlyExitException ) {
+ // EarlyExitException eee = (EarlyExitException) e;
+ message = String.format(
+ EARLY_EXIT_MESSAGE,
+ e.line,
+ e.charPositionInLine,
+ getBetterToken( e.token ),
+ formatParserLocation() );
+ codeAndMessage.add( message );
+ codeAndMessage.add( "ERR 105" );
+ } else if ( e instanceof MismatchedSetException ) {
+ MismatchedSetException mse = (MismatchedSetException) e;
+ String expected = expectedTokensAsString( mse.expecting );
+ message = String.format(
+ MISMATCHED_SET_MESSAGE,
+ e.line,
+ e.charPositionInLine,
+ getBetterToken( e.token ),
+ expected,
+ formatParserLocation() );
+ codeAndMessage.add( message );
+ codeAndMessage.add( "ERR 107" );
+ } else if ( e instanceof DroolsMismatchedSetException ) {
+ DroolsMismatchedSetException mse = (DroolsMismatchedSetException) e;
+ String expected = Arrays.asList( mse.getTokenText() ).toString();
+ message = String.format(
+ MISMATCHED_SET_MESSAGE,
+ e.line,
+ e.charPositionInLine,
+ getBetterToken( e.token ),
+ expected,
+ formatParserLocation() );
+ codeAndMessage.add( message );
+ codeAndMessage.add( "ERR 107" );
+ } else if ( e instanceof MismatchedNotSetException ) {
+ MismatchedNotSetException mse = (MismatchedNotSetException) e;
+ String expected = expectedTokensAsString( mse.expecting );
+ message = String.format(
+ MISMATCHED_NOT_SET_MESSAGE,
+ e.line,
+ e.charPositionInLine,
+ getBetterToken( e.token ),
+ expected,
+ formatParserLocation() );
+ codeAndMessage.add( message );
+ codeAndMessage.add( "ERR 108" );
+ } else if ( e instanceof FailedPredicateException ) {
+ FailedPredicateException fpe = (FailedPredicateException) e;
+ message = String.format(
+ FAILED_PREDICATE_MESSAGE,
+ e.line,
+ e.charPositionInLine,
+ fpe.ruleName,
+ fpe.predicateText,
+ formatParserLocation() );
+ codeAndMessage.add( message );
+ codeAndMessage.add( "ERR 103" );
+ }
+ if ( codeAndMessage.get( 0 ).length() == 0 ) {
+ codeAndMessage.add( "?????" );
+ }
+ return codeAndMessage;
+ }
+
+ public DroolsParserException createDroolsException( Exception e,
+ Token token ) {
+ StringWriter sw = new StringWriter();
+ e.printStackTrace( new PrintWriter(sw) );
+ return new DroolsParserException( String.format(
+ DroolsParserExceptionFactory.UNEXPECTED_EXCEPTION,
+ token.getLine(),
+ token.getCharPositionInLine(),
+ getBetterToken( token ),
+ e.toString(),
+ sw.toString() ),
+ e );
+
+ }
+
+ private String expectedTokensAsString( BitSet set ) {
+ StringBuilder buf = new StringBuilder();
+ buf.append( "{ " );
+ int i = 0;
+ for ( int token : set.toArray() ) {
+ if ( i > 0 ) buf.append( ", " );
+ buf.append( getBetterToken( token ) );
+ i++;
+ }
+ buf.append( " }" );
+ return buf.toString();
+ }
+
+ /**
+ * This will take Paraphrases stack, and create a sensible location
+ */
+ private String formatParserLocation() {
+ StringBuilder sb = new StringBuilder();
+ if ( paraphrases != null ) {
+ for ( Map<DroolsParaphraseTypes, String> map : paraphrases ) {
+ for ( Entry<DroolsParaphraseTypes, String> activeEntry : map.entrySet() ) {
+ if ( activeEntry.getValue().length() == 0 ) {
+ String kStr = getLocationName( activeEntry.getKey() );
+ if( kStr.length() > 0 ){
+ sb.append( String.format( PARSER_LOCATION_MESSAGE_PART, kStr ) );
+ }
+ } else {
+ sb.append( String.format( PARSER_LOCATION_MESSAGE_COMPLETE,
+ getLocationName( activeEntry.getKey() ),
+ activeEntry.getValue() ) );
+ }
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Returns a string based on Paraphrase Type
+ *
+ * @param type
+ * Paraphrase Type
+ * @return a string representing the
+ */
+ private String getLocationName( DroolsParaphraseTypes type ) {
+ switch ( type ) {
+ case PACKAGE :
+ return "package";
+ case IMPORT :
+ return "import";
+ case FUNCTION_IMPORT :
+ return "function import";
+ case ACCUMULATE_IMPORT :
+ return "accumulate import";
+ case GLOBAL :
+ return "global";
+ case FUNCTION :
+ return "function";
+ case QUERY :
+ return "query";
+ case TEMPLATE :
+ return "template";
+ case RULE :
+ return "rule";
+ case RULE_ATTRIBUTE :
+ return "rule attribute";
+ case PATTERN :
+ return "pattern";
+ case EVAL :
+ return "eval";
+ default :
+ return "";
+ }
+ }
+
+ /**
+ * Helper method that creates a user friendly token definition
+ *
+ * @param token
+ * token
+ * @return user friendly token definition
+ */
+ private String getBetterToken( Token token ) {
+ if ( token == null ) {
+ return "";
+ }
+ return DRLFactory.getBetterToken(token.getType(), token.getText(), languageLevel);
+ }
+
+ /**
+ * Helper method that creates a user friendly token definition
+ *
+ * @param tokenType
+ * token type
+ * @return user friendly token definition
+ */
+ private String getBetterToken( int tokenType ) {
+ return DRLFactory.getBetterToken( tokenType, null, languageLevel );
+ }
+
+
+}
diff --git a/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/ParserHelper.java b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/ParserHelper.java
new file mode 100644
index 0000000000..94e5e2f76c
--- /dev/null
+++ b/drools-drl/drools-drl10-parser/src/main/java/org/drools/parser/ParserHelper.java
@@ -0,0 +1,672 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.drools.parser;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.antlr.runtime.CommonToken;
+import org.antlr.runtime.RecognitionException;
+import org.antlr.runtime.RecognizerSharedState;
+import org.antlr.runtime.Token;
+import org.antlr.runtime.TokenStream;
+import org.drools.drl.ast.descr.AttributeDescr;
+import org.drools.drl.ast.descr.BaseDescr;
+import org.drools.drl.ast.dsl.AbstractClassTypeDeclarationBuilder;
+import org.drools.drl.ast.dsl.AccumulateDescrBuilder;
+import org.drools.drl.ast.dsl.AccumulateImportDescrBuilder;
+import org.drools.drl.ast.dsl.AttributeDescrBuilder;
+import org.drools.drl.ast.dsl.AttributeSupportBuilder;
+import org.drools.drl.ast.dsl.BehaviorDescrBuilder;
+import org.drools.drl.ast.dsl.CEDescrBuilder;
+import org.drools.drl.ast.dsl.CollectDescrBuilder;
+import org.drools.drl.ast.dsl.ConditionalBranchDescrBuilder;
+import org.drools.drl.ast.dsl.DeclareDescrBuilder;
+import org.drools.drl.ast.dsl.DescrBuilder;
+import org.drools.drl.ast.dsl.DescrFactory;
+import org.drools.drl.ast.dsl.EntryPointDeclarationDescrBuilder;
+import org.drools.drl.ast.dsl.EnumDeclarationDescrBuilder;
+import org.drools.drl.ast.dsl.EnumLiteralDescrBuilder;
+import org.drools.drl.ast.dsl.EvalDescrBuilder;
+import org.drools.drl.ast.dsl.FieldDescrBuilder;
+import org.drools.drl.ast.dsl.ForallDescrBuilder;
+import org.drools.drl.ast.dsl.FunctionDescrBuilder;
+import org.drools.drl.ast.dsl.GlobalDescrBuilder;
+import org.drools.drl.ast.dsl.GroupByDescrBuilder;
+import org.drools.drl.ast.dsl.ImportDescrBuilder;
+import org.drools.drl.ast.dsl.NamedConsequenceDescrBuilder;
+import org.drools.drl.ast.dsl.PackageDescrBuilder;
+import org.drools.drl.ast.dsl.PatternContainerDescrBuilder;
+import org.drools.drl.ast.dsl.PatternDescrBuilder;
+import org.drools.drl.ast.dsl.QueryDescrBuilder;
+import org.drools.drl.ast.dsl.RuleDescrBuilder;
+import org.drools.drl.ast.dsl.TypeDeclarationDescrBuilder;
+import org.drools.drl.ast.dsl.UnitDescrBuilder;
+import org.drools.drl.ast.dsl.WindowDeclarationDescrBuilder;
+import org.drools.drl.parser.DroolsParserException;
+import org.kie.internal.builder.conf.LanguageLevelOption;
+
+/**
+ * This is a class to hold all the helper functions/methods used
+ * by the DRL parser
+ */
+public class ParserHelper {
+ public final String[] statementKeywords = new String[]{
+ DroolsSoftKeywords.PACKAGE,
+ DroolsSoftKeywords.UNIT,
+ DroolsSoftKeywords.IMPORT,
+ DroolsSoftKeywords.GLOBAL,
+ DroolsSoftKeywords.DECLARE,
+ DroolsSoftKeywords.FUNCTION,
+ DroolsSoftKeywords.RULE,
+ DroolsSoftKeywords.QUERY
+ };
+
+ public List<DroolsParserException> errors = new ArrayList<>();
+ public LinkedList<DroolsSentence> editorInterface = null;
+ public boolean isEditorInterfaceEnabled = false;
+ private Deque<Map<DroolsParaphraseTypes, String>> paraphrases = new ArrayDeque<>();
+
+ // parameters from parser
+ private DroolsParserExceptionFactory errorMessageFactory = null;
+ private TokenStream input = null;
+ private RecognizerSharedState state = null;
+
+ private String leftMostExpr = null;
+
+ // helper attribute
+ private boolean hasOperator = false;
+
+ private final LanguageLevelOption languageLevel;
+
+ public ParserHelper(TokenStream input,
+ RecognizerSharedState state,
+ LanguageLevelOption languageLevel) {
+ this.errorMessageFactory = new DroolsParserExceptionFactory( paraphrases, languageLevel );
+ this.input = input;
+ this.state = state;
+ this.languageLevel = languageLevel;
+ }
+
+ public LinkedList<DroolsSentence> getEditorInterface() {
+ return editorInterface;
+ }
+
+ public void setLeftMostExpr( String value ) {
+ this.leftMostExpr = value;
+ }
+
+ public String getLeftMostExpr() {
+ return this.leftMostExpr;
+ }
+
+ public void enableEditorInterface() {
+ isEditorInterfaceEnabled = true;
+ }
+
+ public void disableEditorInterface() {
+ isEditorInterfaceEnabled = false;
+ }
+
+ public void setHasOperator( boolean hasOperator ) {
+ this.hasOperator = hasOperator;
+ }
+
+ public boolean getHasOperator() {
+ return hasOperator;
+ }
+
+ public void beginSentence( DroolsSentenceType sentenceType ) {
+ if ( isEditorInterfaceEnabled ) {
+ if ( null == editorInterface ) {
+ editorInterface = new LinkedList<>();
+ }
+ if (editorInterface.isEmpty()){
+ DroolsSentence sentence = new DroolsSentence();
+ sentence.setType( sentenceType );
+ editorInterface.add( sentence );
+ }
+ }
+ }
+
+ public DroolsSentence getActiveSentence() {
+ return editorInterface.getLast();
+ }
+
+ public void emit( List< ? > tokens,
+ DroolsEditorType editorType ) {
+ if ( isEditorInterfaceEnabled && tokens != null ) {
+ for ( Object activeObject : tokens ) {
+ emit( (Token) activeObject,
+ editorType );
+ }
+ }
+ }
+
+ public void emit( Token token,
+ DroolsEditorType editorType ) {
+ if ( isEditorInterfaceEnabled && token != null && editorType != null ) {
+ ((DroolsToken) token).setEditorType( editorType );
+ getActiveSentence().addContent( (DroolsToken) token );
+ }
+ }
+
+ public void emit( int activeContext ) {
+ if ( isEditorInterfaceEnabled ) {
+ getActiveSentence().addContent( activeContext );
+ }
+ }
+
+ public DroolsToken getLastTokenOnList( LinkedList< ? > list ) {
+ DroolsToken lastToken = null;
+ for ( Object object : list ) {
+ if ( object instanceof DroolsToken ) {
+ lastToken = (DroolsToken) object;
+ }
+ }
+ return lastToken;
+ }
+
+ public String retrieveLT( int LTNumber ) {
+ if ( null == input ) return null;
+ if ( null == input.LT( LTNumber ) ) return null;
+ if ( null == input.LT( LTNumber ).getText() ) return null;
+
+ return input.LT( LTNumber ).getText();
+ }
+
+ public boolean validateLT( int LTNumber,
+ String text ) {
+ String text2Validate = retrieveLT( LTNumber );
+ return validateText( text, text2Validate );
+ }
+
+ private boolean validateText( String text, String text2Validate ) {
+ return text2Validate != null && text2Validate.equals( text );
+ }
+
+ public boolean isPluggableEvaluator( int offset,
+ boolean negated ) {
+ String text2Validate = retrieveLT( offset );
+ return text2Validate != null && DroolsSoftKeywords.isOperator(text2Validate, negated);
+ }
+
+ public boolean isPluggableEvaluator( boolean negated ) {
+ return isPluggableEvaluator( 1,
+ negated );
+ }
+
+ public boolean validateIdentifierKey( String text ) {
+ return validateLT( 1,
+ text );
+ }
+
+ public boolean validateCEKeyword( int index ) {
+ String text2Validate = retrieveLT( index );
+ return validateText( text2Validate,
+ DroolsSoftKeywords.NOT ) ||
+ validateText( text2Validate,
+ DroolsSoftKeywords.EXISTS ) ||
+ validateText( text2Validate,
+ DroolsSoftKeywords.FORALL ) ||
+ validateText( text2Validate,
+ DroolsSoftKeywords.AND ) ||
+ validateText( text2Validate,
+ DroolsSoftKeywords.OR ) ||
+ validateText( text2Validate,
+ DroolsSoftKeywords.COLLECT ) ||
+ validateText( text2Validate,
+ DroolsSoftKeywords.FROM ) ||
+ validateText( text2Validate,
+ DroolsSoftKeywords.END ) ||
+ validateText( text2Validate,
+ DroolsSoftKeywords.EVAL ) ||
+ validateText( text2Validate,
+ DroolsSoftKeywords.OVER ) ||
+ validateText( text2Validate,
+ DroolsSoftKeywords.THEN );
+ }
+
+ public boolean validateStatement( int index ) {
+ boolean ret = false;
+ String text2Validate = retrieveLT( index );
+ for ( String st : statementKeywords ) {
+ if ( validateText( text2Validate,
+ st ) ) {
+ ret = true;
+ break;
+ }
+ }
+ return ret || validateAttribute( index );
+ }
+
+ public boolean validateAttribute( int index ) {
+ String text2Validate = retrieveLT( index );
+ return validateText( text2Validate,
+ DroolsSoftKeywords.SALIENCE ) ||
+ validateText( text2Validate,
+ DroolsSoftKeywords.ENABLED ) ||
+ (validateText( text2Validate,
+ DroolsSoftKeywords.NO ) &&
+ validateLT( index + 1,
+ "-" ) &&
+ validateLT( index + 2,
+ DroolsSoftKeywords.LOOP )) ||
+ (validateText( text2Validate,
+ DroolsSoftKeywords.AUTO ) &&
+ validateLT( index + 1,
+ "-" ) &&
+ validateLT( index + 2,
+ DroolsSoftKeywords.FOCUS )) ||
+ (validateText( text2Validate,
+ DroolsSoftKeywords.LOCK ) &&
+ validateLT( index + 1,
+ "-" ) &&
+ validateLT( index + 2,
+ DroolsSoftKeywords.ON ) &&
+ validateLT( index + 3,
+ "-" ) &&
+ validateLT( index + 4,
+ DroolsSoftKeywords.ACTIVE )) ||
+ (validateText( text2Validate,
+ DroolsSoftKeywords.AGENDA ) &&
+ validateLT( index + 1,
+ "-" ) &&
+ validateLT( index + 2,
+ DroolsSoftKeywords.GROUP )) ||
+ (validateText( text2Validate,
+ DroolsSoftKeywords.ACTIVATION ) &&
+ validateLT( index + 1,
+ "-" ) &&
+ validateLT( index + 2,
+ DroolsSoftKeywords.GROUP )) ||
+ (validateText( text2Validate,
+ DroolsSoftKeywords.RULEFLOW ) &&
+ validateLT( index + 1,
+ "-" ) &&
+ validateLT( index + 2,
+ DroolsSoftKeywords.GROUP )) ||
+ (validateText( text2Validate,
+ DroolsSoftKeywords.DATE ) &&
+ validateLT( index + 1,
+ "-" ) &&
+ validateLT( index + 2,
+ DroolsSoftKeywords.EFFECTIVE )) ||
+ (validateText( text2Validate,
+ DroolsSoftKeywords.DATE ) &&
+ validateLT( index + 1,
+ "-" ) &&
+ validateLT( index + 2,
+ DroolsSoftKeywords.EXPIRES )) ||
+ validateText( text2Validate,
+ DroolsSoftKeywords.DIALECT ) ||
+ validateText( text2Validate,
+ DroolsSoftKeywords.CALENDARS ) ||
+ validateText( text2Validate,
+ DroolsSoftKeywords.TIMER ) ||
+ validateText( text2Validate,
+ DroolsSoftKeywords.DURATION ) ||
+ validateText( text2Validate,
+ DroolsSoftKeywords.REFRACT ) ||
+ validateText( text2Validate,
+ DroolsSoftKeywords.DIRECT );
+ }
+
+ public void reportError( RecognitionException ex ) {
+ // if we've already reported an error and have not matched a token
+ // yet successfully, don't report any errors.
+ if ( state.errorRecovery ) {
+ return;
+ }
+ state.errorRecovery = true;
+
+ errors.add( errorMessageFactory.createDroolsException( ex ) );
+ }
+
+ public void reportError( Exception e ) {
+ try {
+ errors.add( errorMessageFactory.createDroolsException( e,
+ input.LT( 1 ) ) );
+ } catch (Exception ignored) {
+ errors.add(new DroolsParserException( "Unexpected error: " + e.getMessage(), e ));
+ }
+ }
+
+ /** return the raw DroolsParserException errors */
+ public List<DroolsParserException> getErrors() {
+ return errors;
+ }
+
+ /** Return a list of pretty strings summarising the errors */
+ public List<String> getErrorMessages() {
+ List<String> messages = new ArrayList<>( errors.size() );
+
+ for ( DroolsParserException activeException : errors ) {
+ messages.add( activeException.getMessage() );
+ }
+
+ return messages;
+ }
+
+ /** return true if any parser errors were accumulated */
+ public boolean hasErrors() {
+ return !errors.isEmpty();
+ }
+
+ /**
+ * Method that adds a paraphrase type into paraphrases stack.
+ *
+ * @param type
+ * paraphrase type
+ */
+ public void pushParaphrases( DroolsParaphraseTypes type ) {
+ Map<DroolsParaphraseTypes, String> activeMap = new HashMap<>();
+ activeMap.put( type,
+ "" );
+ paraphrases.push( activeMap );
+ }
+
+ public Map<DroolsParaphraseTypes, String> popParaphrases() {
+ return paraphrases.pop();
+ }
+
+ /**
+ * Method that sets paraphrase value for a type into paraphrases stack.
+ *
+ * @param type
+ * paraphrase type
+ * @param value
+ * paraphrase value
+ */
+ public void setParaphrasesValue( DroolsParaphraseTypes type,
+ String value ) {
+ paraphrases.peek().put( type,
+ value );
+ }
+
+ void setStart( DescrBuilder< ? , ? > db ) {
+ setStart( db,
+ input.LT( 1 ) );
+ }
+
+ void setStart( DescrBuilder< ? , ? > db,
+ Token first ) {
+ if ( db != null && first != null ) {
+ db.startCharacter( ((CommonToken) first).getStartIndex() ).startLocation( first.getLine(),
+ first.getCharPositionInLine() );
+ }
+ }
+
+ void setStart( BaseDescr descr,
+ Token first ) {
+ if ( descr != null && first != null ) {
+ descr.setLocation( first.getLine(),
+ first.getCharPositionInLine() );
+ descr.setStartCharacter( ((CommonToken) first).getStartIndex() );
+ }
+ }
+
+ void setEnd( BaseDescr descr ) {
+ Token last = input.LT( -1 );
+ if ( descr != null && last != null ) {
+ int endLocation = last.getText() != null ? last.getCharPositionInLine() + last.getText().length() - 1 : last.getCharPositionInLine();
+ descr.setEndCharacter( ((CommonToken) last).getStopIndex() + 1 );
+ descr.setEndLocation( last.getLine(),
+ endLocation );
+ }
+ }
+
+ void setEnd( DescrBuilder< ? , ? > db ) {
+ Token last = input.LT( -1 );
+ if ( db != null && last != null ) {
+ int endLocation = last.getText() != null ? last.getCharPositionInLine() + last.getText().length() - 1 : last.getCharPositionInLine();
+ db.endCharacter( ((CommonToken) last).getStopIndex() + 1 ).endLocation( last.getLine(),
+ endLocation );
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T extends DescrBuilder< ? , ? >> T start( DescrBuilder< ? , ? > ctxBuilder,
+ Class<T> clazz,
+ String param ) {
+ if ( state.backtracking == 0 ) {
+ if ( PackageDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ pushParaphrases( DroolsParaphraseTypes.PACKAGE );
+ beginSentence( DroolsSentenceType.PACKAGE );
+ setStart( ctxBuilder );
+ } else if ( ImportDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ ImportDescrBuilder imp;
+ if ( validateLT( 2,
+ DroolsSoftKeywords.FUNCTION ) ||
+ validateLT( 2,
+ DroolsSoftKeywords.STATIC ) ) {
+ imp = ctxBuilder == null ?
+ DescrFactory.newPackage().newFunctionImport() :
+ ((PackageDescrBuilder) ctxBuilder).newFunctionImport();
+ } else {
+ imp = ctxBuilder == null ?
+ DescrFactory.newPackage().newImport() :
+ ((PackageDescrBuilder) ctxBuilder).newImport();
+ }
+ pushParaphrases( DroolsParaphraseTypes.IMPORT );
+ beginSentence( DroolsSentenceType.IMPORT_STATEMENT );
+ setStart( imp );
+ return (T) imp;
+ } else if ( UnitDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ UnitDescrBuilder imp = ctxBuilder == null ?
+ DescrFactory.newPackage().newUnit() :
+ ((PackageDescrBuilder) ctxBuilder).newUnit();
+ pushParaphrases( DroolsParaphraseTypes.UNIT );
+ beginSentence( DroolsSentenceType.UNIT );
+ setStart( imp );
+ return (T) imp;
+ } else if ( AccumulateImportDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ AccumulateImportDescrBuilder imp = ctxBuilder == null ?
+ DescrFactory.newPackage().newAccumulateImport() :
+ ((PackageDescrBuilder) ctxBuilder).newAccumulateImport();
+ pushParaphrases( DroolsParaphraseTypes.ACCUMULATE_IMPORT );
+ beginSentence( DroolsSentenceType.ACCUMULATE_IMPORT_STATEMENT );
+ setStart( imp );
+ return (T) imp;
+ } else if ( GlobalDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ GlobalDescrBuilder global = ctxBuilder == null ?
+ DescrFactory.newPackage().newGlobal() :
+ ((PackageDescrBuilder) ctxBuilder).newGlobal();
+ pushParaphrases( DroolsParaphraseTypes.GLOBAL );
+ beginSentence( DroolsSentenceType.GLOBAL );
+ setStart( global );
+ return (T) global;
+ } else if ( DeclareDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ DeclareDescrBuilder declare = ctxBuilder == null ?
+ DescrFactory.newPackage().newDeclare() :
+ ((PackageDescrBuilder) ctxBuilder).newDeclare();
+ return (T) declare;
+ } else if ( TypeDeclarationDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ TypeDeclarationDescrBuilder declare = ctxBuilder == null ?
+ DescrFactory.newPackage().newDeclare().type() :
+ ((DeclareDescrBuilder) ctxBuilder).type();
+ pushParaphrases( DroolsParaphraseTypes.TYPE_DECLARE );
+ beginSentence( DroolsSentenceType.TYPE_DECLARATION );
+ setStart( declare );
+ return (T) declare;
+ } else if ( EnumDeclarationDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ EnumDeclarationDescrBuilder declare = ctxBuilder == null ?
+ DescrFactory.newPackage().newDeclare().enumerative() :
+ ((DeclareDescrBuilder) ctxBuilder).enumerative();
+ pushParaphrases( DroolsParaphraseTypes.ENUM_DECLARE );
+ beginSentence( DroolsSentenceType.ENUM_DECLARATION );
+ setStart( declare );
+ return (T) declare;
+ }else if ( EntryPointDeclarationDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ EntryPointDeclarationDescrBuilder declare = ctxBuilder == null ?
+ DescrFactory.newPackage().newDeclare().entryPoint() :
+ ((DeclareDescrBuilder) ctxBuilder).entryPoint();
+ pushParaphrases( DroolsParaphraseTypes.ENTRYPOINT_DECLARE );
+ beginSentence( DroolsSentenceType.ENTRYPOINT_DECLARATION );
+ setStart( declare );
+ return (T) declare;
+ } else if ( WindowDeclarationDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ WindowDeclarationDescrBuilder declare = ctxBuilder == null ?
+ DescrFactory.newPackage().newDeclare().window() :
+ ((DeclareDescrBuilder) ctxBuilder).window();
+ pushParaphrases( DroolsParaphraseTypes.WINDOW_DECLARE );
+ beginSentence( DroolsSentenceType.WINDOW_DECLARATION );
+ setStart( declare );
+ return (T) declare;
+ } else if ( FieldDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ FieldDescrBuilder field = ((AbstractClassTypeDeclarationBuilder) ctxBuilder).newField( param );
+ setStart( field );
+ return (T) field;
+ } else if ( EnumLiteralDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ EnumLiteralDescrBuilder literal = ((EnumDeclarationDescrBuilder) ctxBuilder).newEnumLiteral( param );
+ setStart( literal );
+ return (T) literal;
+ } else if ( FunctionDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ FunctionDescrBuilder function;
+ if ( ctxBuilder == null ) {
+ function = DescrFactory.newPackage().newFunction();
+ } else {
+ PackageDescrBuilder pkg = (PackageDescrBuilder) ctxBuilder;
+ function = pkg.newFunction().namespace( pkg.getDescr().getName() );
+ AttributeDescr attribute = pkg.getDescr().getAttribute( "dialect" );
+ if ( attribute != null ) {
+ function.dialect( attribute.getValue() );
+ }
+ }
+ pushParaphrases( DroolsParaphraseTypes.FUNCTION );
+ beginSentence( DroolsSentenceType.FUNCTION );
+ setStart( function );
+ return (T) function;
+ } else if ( RuleDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ RuleDescrBuilder rule = ctxBuilder == null ?
+ DescrFactory.newPackage().newRule() :
+ ((PackageDescrBuilder) ctxBuilder).newRule();
+ pushParaphrases( DroolsParaphraseTypes.RULE );
+ beginSentence( DroolsSentenceType.RULE );
+ setStart( rule );
+ return (T) rule;
+ } else if ( QueryDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ QueryDescrBuilder query = ctxBuilder == null ?
+ DescrFactory.newPackage().newQuery() :
+ ((PackageDescrBuilder) ctxBuilder).newQuery();
+ pushParaphrases( DroolsParaphraseTypes.QUERY );
+ beginSentence( DroolsSentenceType.QUERY );
+ setStart( query );
+ return (T) query;
+ } else if ( AttributeDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ AttributeDescrBuilder< ? > attribute = ((AttributeSupportBuilder< ? >) ctxBuilder).attribute(param);
+ setStart( attribute );
+ return (T) attribute;
+ } else if ( EvalDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ EvalDescrBuilder< ? > eval = ((CEDescrBuilder< ? , ? >) ctxBuilder).eval();
+ pushParaphrases( DroolsParaphraseTypes.EVAL );
+ beginSentence( DroolsSentenceType.EVAL );
+ setStart( eval );
+ return (T) eval;
+ } else if ( ForallDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ ForallDescrBuilder< ? > forall = ((CEDescrBuilder< ? , ? >) ctxBuilder).forall();
+ setStart( forall );
+ return (T) forall;
+ } else if ( CEDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ setStart( ctxBuilder );
+ return (T) ctxBuilder;
+ } else if ( PatternDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ PatternDescrBuilder< ? > pattern = ((PatternContainerDescrBuilder< ? , ? >) ctxBuilder).pattern();
+ pushParaphrases( DroolsParaphraseTypes.PATTERN );
+ setStart( pattern );
+ return (T) pattern;
+ } else if ( CollectDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ CollectDescrBuilder< ? > collect = ((PatternDescrBuilder< ? >) ctxBuilder).from().collect();
+ setStart( collect );
+ return (T) collect;
+ } else if ( GroupByDescrBuilder.class.isAssignableFrom(clazz) ) {
+ // GroupBy extends Accumulate and thus need to be before it
+ GroupByDescrBuilder< ? > groupBy = ((PatternDescrBuilder< ? >) ctxBuilder).from().groupBy();
+ setStart( groupBy );
+ return (T) groupBy;
+ } else if ( AccumulateDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ AccumulateDescrBuilder< ? > accumulate = ((PatternDescrBuilder< ? >) ctxBuilder).from().accumulate();
+ setStart( accumulate );
+ return (T) accumulate;
+ } else if ( BehaviorDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ BehaviorDescrBuilder< ? > behavior = ((PatternDescrBuilder< ? >) ctxBuilder).behavior();
+ setStart( behavior );
+ return (T) behavior;
+ } else if ( NamedConsequenceDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ NamedConsequenceDescrBuilder< ? > namedConsequence = ((CEDescrBuilder< ? , ? >) ctxBuilder).namedConsequence();
+ setStart( namedConsequence );
+ return (T) namedConsequence;
+ } else if ( ConditionalBranchDescrBuilder.class.isAssignableFrom( clazz ) ) {
+ ConditionalBranchDescrBuilder< ? > conditionalBranch = ((CEDescrBuilder< ? , ? >) ctxBuilder).conditionalBranch();
+ setStart( conditionalBranch );
+ return (T) conditionalBranch;
+ }
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T extends DescrBuilder< ? , ? >> T end( Class<T> clazz,
+ DescrBuilder< ? , ? > builder ) {
+ if ( state.backtracking == 0 ) {
+ if ( !(FieldDescrBuilder.class.isAssignableFrom( clazz ) ||
+ AttributeDescrBuilder.class.isAssignableFrom( clazz ) ||
+ CEDescrBuilder.class.isAssignableFrom( clazz ) ||
+ CollectDescrBuilder.class.isAssignableFrom( clazz ) ||
+ AccumulateDescrBuilder.class.isAssignableFrom( clazz ) ||
+ ForallDescrBuilder.class.isAssignableFrom( clazz ) ||
+ BehaviorDescrBuilder.class.isAssignableFrom( clazz ) ||
+ ConditionalBranchDescrBuilder.class.isAssignableFrom( clazz ) ||
+ NamedConsequenceDescrBuilder.class.isAssignableFrom( clazz )) ) {
+ popParaphrases();
+ }
+
+ if (RuleDescrBuilder.class.isAssignableFrom(clazz)) {
+ RuleDescrBuilder ruleDescrBuilder = (RuleDescrBuilder)builder;
+ ruleDescrBuilder.end().getDescr().afterRuleAdded(ruleDescrBuilder.getDescr());
+ }
+
+ setEnd( builder );
+ return (T) builder;
+ }
+ return null;
+ }
+
+ public String[] getStatementKeywords() {
+ return statementKeywords;
+ }
+}
diff --git a/drools-drl/drools-drl10-parser/src/test/java/org/drools/parser/DRLExprParserTest.java b/drools-drl/drools-drl10-parser/src/test/java/org/drools/parser/DRLExprParserTest.java
new file mode 100644
index 0000000000..a7672090cc
--- /dev/null
+++ b/drools-drl/drools-drl10-parser/src/test/java/org/drools/parser/DRLExprParserTest.java
@@ -0,0 +1,270 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.drools.parser;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.drools.compiler.builder.impl.EvaluatorRegistry;
+import org.drools.drl.ast.descr.AtomicExprDescr;
+import org.drools.drl.ast.descr.BindingDescr;
+import org.drools.drl.ast.descr.ConnectiveType;
+import org.drools.drl.ast.descr.ConstraintConnectiveDescr;
+import org.drools.drl.ast.descr.RelationalExprDescr;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.kie.internal.builder.conf.LanguageLevelOption;
+
+/**
+ * DRLExprTreeTest
+ */
+public class DRLExprParserTest {
+
+ DrlExprParser parser;
+
+ @Before
+ public void setUp() throws Exception {
+ new EvaluatorRegistry();
+ this.parser = new DrlExprParser(LanguageLevelOption.DRL6);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ this.parser = null;
+ }
+
+ @Test
+ public void testSimpleExpression() throws Exception {
+ String source = "a > b";
+ ConstraintConnectiveDescr result = parser.parse( source );
+ assertThat(parser.hasErrors()).as(parser.getErrors().toString()).isFalse();
+
+ assertThat(result.getConnective()).isEqualTo(ConnectiveType.AND);
+ assertThat(result.getDescrs().size()).isEqualTo(1);
+
+ RelationalExprDescr expr = (RelationalExprDescr) result.getDescrs().get( 0 );
+ assertThat(expr.getOperator()).isEqualTo(">");
+
+ AtomicExprDescr left = (AtomicExprDescr) expr.getLeft();
+ AtomicExprDescr right = (AtomicExprDescr) expr.getRight();
+
+ assertThat(left.getExpression()).isEqualTo("a");
+ assertThat(right.getExpression()).isEqualTo("b");
+ }
+
+ @Test
+ public void testAndConnective() throws Exception {
+ String source = "a > b && 10 != 20";
+ ConstraintConnectiveDescr result = parser.parse( source );
+ assertThat(parser.hasErrors()).as(parser.getErrors().toString()).isFalse();
+
+ assertThat(result.getConnective()).isEqualTo(ConnectiveType.AND);
+ assertThat(result.getDescrs().size()).isEqualTo(2);
+
+ RelationalExprDescr expr = (RelationalExprDescr) result.getDescrs().get( 0 );
+ assertThat(expr.getOperator()).isEqualTo(">");
+ AtomicExprDescr left = (AtomicExprDescr) expr.getLeft();
+ AtomicExprDescr right = (AtomicExprDescr) expr.getRight();
+ assertThat(left.getExpression()).isEqualTo("a");
+ assertThat(right.getExpression()).isEqualTo("b");
+
+ expr = (RelationalExprDescr) result.getDescrs().get( 1 );
+ assertThat(expr.getOperator()).isEqualTo("!=");
+ left = (AtomicExprDescr) expr.getLeft();
+ right = (AtomicExprDescr) expr.getRight();
+ assertThat(left.getExpression()).isEqualTo("10");
+ assertThat(right.getExpression()).isEqualTo("20");
+ }
+
+ @Test
+ public void testConnective2() throws Exception {
+ String source = "(a > b || 10 != 20) && someMethod(10) == 20";
+ ConstraintConnectiveDescr result = parser.parse( source );
+ assertThat(parser.hasErrors()).as(parser.getErrors().toString()).isFalse();
+
+ assertThat(result.getConnective()).isEqualTo(ConnectiveType.AND);
+ assertThat(result.getDescrs().size()).isEqualTo(2);
+
+ ConstraintConnectiveDescr or = (ConstraintConnectiveDescr) result.getDescrs().get( 0 );
+ assertThat(or.getConnective()).isEqualTo(ConnectiveType.OR);
+ assertThat(or.getDescrs().size()).isEqualTo(2);
+
+ RelationalExprDescr expr = (RelationalExprDescr) or.getDescrs().get( 0 );
+ assertThat(expr.getOperator()).isEqualTo(">");
+ AtomicExprDescr left = (AtomicExprDescr) expr.getLeft();
+ AtomicExprDescr right = (AtomicExprDescr) expr.getRight();
+ assertThat(left.getExpression()).isEqualTo("a");
+ assertThat(right.getExpression()).isEqualTo("b");
+
+ expr = (RelationalExprDescr) or.getDescrs().get( 1 );
+ assertThat(expr.getOperator()).isEqualTo("!=");
+ left = (AtomicExprDescr) expr.getLeft();
+ right = (AtomicExprDescr) expr.getRight();
+ assertThat(left.getExpression()).isEqualTo("10");
+ assertThat(right.getExpression()).isEqualTo("20");
+
+ expr = (RelationalExprDescr) result.getDescrs().get( 1 );
+ assertThat(expr.getOperator()).isEqualTo("==");
+ left = (AtomicExprDescr) expr.getLeft();
+ right = (AtomicExprDescr) expr.getRight();
+ assertThat(left.getExpression()).isEqualTo("someMethod(10)");
+ assertThat(right.getExpression()).isEqualTo("20");
+
+ }
+
+ @Test
+ public void testBinding() throws Exception {
+ String source = "$x : property";
+ ConstraintConnectiveDescr result = parser.parse( source );
+ assertThat(parser.hasErrors()).as(parser.getErrors().toString()).isFalse();
+
+ assertThat(result.getConnective()).isEqualTo(ConnectiveType.AND);
+ assertThat(result.getDescrs().size()).isEqualTo(1);
+
+ BindingDescr bind = (BindingDescr) result.getDescrs().get( 0 );
+ assertThat(bind.getVariable()).isEqualTo("$x");
+ assertThat(bind.getExpression()).isEqualTo("property");
+ }
+
+ @Test
+ public void testBindingConstraint() throws Exception {
+ String source = "$x : property > value";
+ ConstraintConnectiveDescr result = parser.parse( source );
+ assertThat(parser.hasErrors()).as(parser.getErrors().toString()).isFalse();
+
+ assertThat(result.getConnective()).isEqualTo(ConnectiveType.AND);
+ assertThat(result.getDescrs().size()).isEqualTo(1);
+
+ RelationalExprDescr rel = (RelationalExprDescr) result.getDescrs().get( 0 );
+ assertThat(rel.getOperator()).isEqualTo(">");
+
+ BindingDescr bind = (BindingDescr) rel.getLeft();
+ assertThat(bind.getVariable()).isEqualTo("$x");
+ assertThat(bind.getExpression()).isEqualTo("property");
+
+ AtomicExprDescr right = (AtomicExprDescr) rel.getRight();
+ assertThat(right.getExpression()).isEqualTo("value");
+ }
+
+ @Test
+ public void testBindingWithRestrictions() throws Exception {
+ String source = "$x : property > value && < 20";
+ ConstraintConnectiveDescr result = parser.parse( source );
+ assertThat(parser.hasErrors()).as(parser.getErrors().toString()).isFalse();
+
+ assertThat(result.getConnective()).isEqualTo(ConnectiveType.AND);
+ assertThat(result.getDescrs().size()).isEqualTo(2);
+
+ RelationalExprDescr rel = (RelationalExprDescr) result.getDescrs().get( 0 );
+ assertThat(rel.getOperator()).isEqualTo(">");
+
+ BindingDescr bind = (BindingDescr) rel.getLeft();
+ assertThat(bind.getVariable()).isEqualTo("$x");
+ assertThat(bind.getExpression()).isEqualTo("property");
+
+ AtomicExprDescr right = (AtomicExprDescr) rel.getRight();
+ assertThat(right.getExpression()).isEqualTo("value");
+
+ rel = (RelationalExprDescr) result.getDescrs().get( 1 );
+ assertThat(rel.getOperator()).isEqualTo("<");
+
+ AtomicExprDescr left = (AtomicExprDescr) rel.getLeft();
+ assertThat(left.getExpression()).isEqualTo("property");
+
+ right = (AtomicExprDescr) rel.getRight();
+ assertThat(right.getExpression()).isEqualTo("20");
+ }
+
+ @Test
+ public void testDoubleBinding() throws Exception {
+ String source = "$x : x.m( 1, a ) && $y : y[z].foo";
+ ConstraintConnectiveDescr result = parser.parse( source );
+ assertThat(parser.hasErrors()).as(parser.getErrors().toString()).isFalse();
+
+ assertThat(result.getConnective()).isEqualTo(ConnectiveType.AND);
+ assertThat(result.getDescrs().size()).isEqualTo(2);
+
+ BindingDescr bind = (BindingDescr) result.getDescrs().get( 0 );
+ assertThat(bind.getVariable()).isEqualTo("$x");
+ assertThat(bind.getExpression()).isEqualTo("x.m( 1, a )");
+
+ bind = (BindingDescr) result.getDescrs().get( 1 );
+ assertThat(bind.getVariable()).isEqualTo("$y");
+ assertThat(bind.getExpression()).isEqualTo("y[z].foo");
+ }
+
+ @Test
+ public void testDeepBinding() throws Exception {
+ String source = "($a : a > $b : b[10].prop || 10 != 20) && $x : someMethod(10) == 20";
+ ConstraintConnectiveDescr result = parser.parse( source );
+ assertThat(parser.hasErrors()).as(parser.getErrors().toString()).isFalse();
+
+ assertThat(result.getConnective()).isEqualTo(ConnectiveType.AND);
+ assertThat(result.getDescrs().size()).isEqualTo(2);
+
+ ConstraintConnectiveDescr or = (ConstraintConnectiveDescr) result.getDescrs().get( 0 );
+ assertThat(or.getConnective()).isEqualTo(ConnectiveType.OR);
+ assertThat(or.getDescrs().size()).isEqualTo(2);
+
+ RelationalExprDescr expr = (RelationalExprDescr) or.getDescrs().get( 0 );
+ assertThat(expr.getOperator()).isEqualTo(">");
+ BindingDescr leftBind = (BindingDescr) expr.getLeft();
+ BindingDescr rightBind = (BindingDescr) expr.getRight();
+ assertThat(leftBind.getVariable()).isEqualTo("$a");
+ assertThat(leftBind.getExpression()).isEqualTo("a");
+ assertThat(rightBind.getVariable()).isEqualTo("$b");
+ assertThat(rightBind.getExpression()).isEqualTo("b[10].prop");
+
+ expr = (RelationalExprDescr) or.getDescrs().get( 1 );
+ assertThat(expr.getOperator()).isEqualTo("!=");
+ AtomicExprDescr leftExpr = (AtomicExprDescr) expr.getLeft();
+ AtomicExprDescr rightExpr = (AtomicExprDescr) expr.getRight();
+ assertThat(leftExpr.getExpression()).isEqualTo("10");
+ assertThat(rightExpr.getExpression()).isEqualTo("20");
+
+ expr = (RelationalExprDescr) result.getDescrs().get( 1 );
+ assertThat(expr.getOperator()).isEqualTo("==");
+ leftBind = (BindingDescr) expr.getLeft();
+ rightExpr = (AtomicExprDescr) expr.getRight();
+ assertThat(leftBind.getVariable()).isEqualTo("$x");
+ assertThat(leftBind.getExpression()).isEqualTo("someMethod(10)");
+ assertThat(rightExpr.getExpression()).isEqualTo("20");
+
+ }
+
+ @Test(timeout = 10000L)
+ public void testNestedExpression() throws Exception {
+ // DROOLS-982
+ String source = "(((((((((((((((((((((((((((((((((((((((((((((((((( a > b ))))))))))))))))))))))))))))))))))))))))))))))))))";
+ ConstraintConnectiveDescr result = parser.parse( source );
+ assertThat(parser.hasErrors()).as(parser.getErrors().toString()).isFalse();
+
+ assertThat(result.getConnective()).isEqualTo(ConnectiveType.AND);
+ assertThat(result.getDescrs().size()).isEqualTo(1);
+
+ RelationalExprDescr expr = (RelationalExprDescr) result.getDescrs().get( 0 );
+ assertThat(expr.getOperator()).isEqualTo(">");
+
+ AtomicExprDescr left = (AtomicExprDescr) expr.getLeft();
+ AtomicExprDescr right = (AtomicExprDescr) expr.getRight();
+
+ assertThat(left.getExpression()).isEqualTo("a");
+ assertThat(right.getExpression()).isEqualTo("b");
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org