org.drools.compiler.lang.DRL6StrictParser Maven / Gradle / Ivy
/*
* 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.compiler.lang;
import org.antlr.runtime.CommonToken;
import org.antlr.runtime.MismatchedTokenException;
import org.antlr.runtime.MissingTokenException;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.Token;
import org.antlr.runtime.TokenStream;
import org.antlr.runtime.UnwantedTokenException;
import org.drools.compiler.lang.api.AbstractClassTypeDeclarationBuilder;
import org.drools.compiler.lang.api.AccumulateDescrBuilder;
import org.drools.compiler.lang.api.AccumulateImportDescrBuilder;
import org.drools.compiler.lang.api.AnnotatedDescrBuilder;
import org.drools.compiler.lang.api.AnnotationDescrBuilder;
import org.drools.compiler.lang.api.AttributeDescrBuilder;
import org.drools.compiler.lang.api.AttributeSupportBuilder;
import org.drools.compiler.lang.api.BehaviorDescrBuilder;
import org.drools.compiler.lang.api.CEDescrBuilder;
import org.drools.compiler.lang.api.CollectDescrBuilder;
import org.drools.compiler.lang.api.ConditionalBranchDescrBuilder;
import org.drools.compiler.lang.api.DeclareDescrBuilder;
import org.drools.compiler.lang.api.DescrBuilder;
import org.drools.compiler.lang.api.EntryPointDeclarationDescrBuilder;
import org.drools.compiler.lang.api.EnumDeclarationDescrBuilder;
import org.drools.compiler.lang.api.EnumLiteralDescrBuilder;
import org.drools.compiler.lang.api.EvalDescrBuilder;
import org.drools.compiler.lang.api.FieldDescrBuilder;
import org.drools.compiler.lang.api.ForallDescrBuilder;
import org.drools.compiler.lang.api.FunctionDescrBuilder;
import org.drools.compiler.lang.api.GlobalDescrBuilder;
import org.drools.compiler.lang.api.ImportDescrBuilder;
import org.drools.compiler.lang.api.NamedConsequenceDescrBuilder;
import org.drools.compiler.lang.api.PackageDescrBuilder;
import org.drools.compiler.lang.api.ParameterSupportBuilder;
import org.drools.compiler.lang.api.PatternContainerDescrBuilder;
import org.drools.compiler.lang.api.PatternDescrBuilder;
import org.drools.compiler.lang.api.QueryDescrBuilder;
import org.drools.compiler.lang.api.RuleDescrBuilder;
import org.drools.compiler.lang.api.TypeDeclarationDescrBuilder;
import org.drools.compiler.lang.api.UnitDescrBuilder;
import org.drools.compiler.lang.api.WindowDeclarationDescrBuilder;
import org.drools.compiler.lang.api.impl.AnnotationDescrBuilderImpl;
import org.drools.compiler.lang.descr.AndDescr;
import org.drools.compiler.lang.descr.AnnotatedBaseDescr;
import org.drools.compiler.lang.descr.AnnotationDescr;
import org.drools.compiler.lang.descr.AttributeDescr;
import org.drools.compiler.lang.descr.BaseDescr;
import org.drools.compiler.lang.descr.ConditionalElementDescr;
import org.drools.compiler.lang.descr.EntryPointDeclarationDescr;
import org.drools.compiler.lang.descr.EnumDeclarationDescr;
import org.drools.compiler.lang.descr.ExistsDescr;
import org.drools.compiler.lang.descr.FunctionDescr;
import org.drools.compiler.lang.descr.GlobalDescr;
import org.drools.compiler.lang.descr.ImportDescr;
import org.drools.compiler.lang.descr.NotDescr;
import org.drools.compiler.lang.descr.OrDescr;
import org.drools.compiler.lang.descr.PackageDescr;
import org.drools.compiler.lang.descr.RuleDescr;
import org.drools.compiler.lang.descr.TypeDeclarationDescr;
import org.drools.compiler.lang.descr.UnitDescr;
import org.drools.compiler.lang.descr.WindowDeclarationDescr;
import org.drools.core.util.StringUtils;
import org.kie.internal.builder.conf.LanguageLevelOption;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
public class DRL6StrictParser extends AbstractDRLParser implements DRLParser {
private final DRL6Expressions exprParser;
public DRL6StrictParser(TokenStream input) {
super(input);
this.exprParser = new DRL6Expressions(input, state, helper);
}
protected LanguageLevelOption getLanguageLevel() {
return LanguageLevelOption.DRL6_STRICT;
}
/* ------------------------------------------------------------------------------------------------
* GRAMMAR RULES
* ------------------------------------------------------------------------------------------------ */
protected final PackageDescr compilationUnit(PackageDescrBuilder pkg) throws RecognitionException {
try {
// package declaration?
if (input.LA(1) != DRL6Lexer.EOF && helper.validateIdentifierKey(DroolsSoftKeywords.PACKAGE)) {
String pkgName = packageStatement(pkg);
pkg.name(pkgName);
if (state.failed)
return pkg.getDescr();
// unit declaration?
// this is only allowed immediately after the package declaration
if (input.LA(1) != DRL6Lexer.EOF && helper.validateIdentifierKey(DroolsSoftKeywords.UNIT)) {
unitStatement(pkg);
}
}
// statements
while (input.LA(1) != DRL6Lexer.EOF) {
annotations();
if (state.failed) {
return pkg.getDescr();
}
int next = input.index();
if (helper.validateStatement(1)) {
statement(pkg);
if (state.failed)
return pkg.getDescr();
if (next == input.index()) {
// no token consumed, so, report problem:
resyncToNextStatement();
}
} else {
resyncToNextStatement();
}
if (input.LA(1) == DRL6Lexer.SEMICOLON) {
match(input,
DRL6Lexer.SEMICOLON,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return pkg.getDescr();
}
annotationsCollector.clear();
}
} catch (RecognitionException e) {
helper.reportError(e);
} catch (Exception e) {
helper.reportError(e);
} finally {
helper.setEnd(pkg);
}
return pkg.getDescr();
}
private void annotations() {
while (input.LA(1) == DRL6Lexer.AT && !state.failed) {
annotation(annotationsCollector);
}
}
private void setAnnotationsOn(AnnotatedDescrBuilder builder) {
annotationsCollector.setAnnotationsOn(builder);
}
private void setAnnotationsOn(BaseDescr annotationsContainer) throws DroolsUnexpectedAnnotationException {
annotationsCollector.setAnnotationsOn(annotationsContainer);
}
private final AnnotationsCollector annotationsCollector = new AnnotationsCollector();
private class AnnotationsCollector implements AnnotatedDescrBuilder {
private AnnotatedBaseDescr descr = new AnnotatedBaseDescr();
@Override
public AnnotationDescrBuilder newAnnotation(String name) {
AnnotationDescrBuilder annotation = new AnnotationDescrCreator( name );
descr.addAnnotation((AnnotationDescr) annotation.getDescr());
return annotation;
}
private class AnnotationDescrCreator extends AnnotationDescrBuilderImpl {
public AnnotationDescrCreator(String name) {
super( null, name );
}
}
public void clear() {
if (!descr.getAnnotations().isEmpty()) {
descr = new AnnotatedBaseDescr();
}
}
public void setAnnotationsOn(AnnotatedDescrBuilder builder) {
if (!descr.getAnnotations().isEmpty()) {
for (AnnotationDescr annDescr : descr.getAnnotations()) {
AnnotationDescrBuilder annotation = builder.newAnnotation(annDescr.getName());
for (Map.Entry valueEntry : annDescr.getValueMap().entrySet()) {
annotation.keyValue(valueEntry.getKey(), valueEntry.getValue());
}
}
clear();
}
}
public void setAnnotationsOn(BaseDescr annotationsContainer) throws DroolsUnexpectedAnnotationException {
if (!descr.getAnnotations().isEmpty()) {
if (annotationsContainer instanceof AnnotatedBaseDescr) {
for (AnnotationDescr annotationDescr : descr.getAnnotations()) {
((AnnotatedBaseDescr) annotationsContainer).addAnnotation(annotationDescr);
}
} else {
AnnotationDescr annotationDescr = descr.getAnnotations().iterator().next();
failUnexpectedAnnotationException(annotationDescr.getName());
}
clear();
}
}
}
private void resyncToNextStatement() {
helper.reportError(new DroolsMismatchedSetException(helper.getStatementKeywords(),
input));
do {
// error recovery: look for the next statement, skipping all tokens until then
input.consume();
} while (input.LA(1) != DRL6Lexer.EOF && !helper.validateStatement(1));
}
/**
* Parses a package statement and returns the name of the package
* or null if none is defined.
*
* packageStatement := PACKAGE qualifiedIdentifier SEMICOLON?
*
* @return the name of the package or null if none is defined
*/
public String packageStatement(PackageDescrBuilder pkg) throws RecognitionException {
String pkgName = null;
try {
helper.start(pkg,
PackageDescrBuilder.class,
null);
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.PACKAGE,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return pkgName;
pkgName = qualifiedIdentifier();
if (state.failed)
return pkgName;
if (state.backtracking == 0) {
helper.setParaphrasesValue(DroolsParaphraseTypes.PACKAGE,
pkgName);
}
if (input.LA(1) == DRL6Lexer.SEMICOLON) {
match(input,
DRL6Lexer.SEMICOLON,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return pkgName;
}
} catch (RecognitionException re) {
reportError(re);
} finally {
helper.end(PackageDescrBuilder.class,
pkg);
}
return pkgName;
}
/**
* unitStatement := UNIT qualifiedIdentifier SEMICOLON?
*/
public UnitDescr unitStatement( PackageDescrBuilder pkg ) throws RecognitionException {
UnitDescrBuilder imp = helper.start( pkg,
UnitDescrBuilder.class,
null );
try {
// import
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.UNIT,
null,
DroolsEditorType.KEYWORD);
if (state.failed) return null;
// qualifiedIdentifier
String target = qualifiedIdentifier();
if (state.failed)
return null;
if (state.backtracking == 0) {
imp.target( target );
}
if (input.LA(1) == DRL6Lexer.SEMICOLON) {
match(input,
DRL6Lexer.SEMICOLON,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed) return null;
}
return (imp != null) ? imp.getDescr() : null;
} finally {
helper.end(ImportDescrBuilder.class,
imp);
}
}
/**
* statement := importStatement
* | globalStatement
* | declare
* | rule
* | ruleAttribute
* | function
* | query
* ;
*
* @throws org.antlr.runtime.RecognitionException
*/
public BaseDescr statement(PackageDescrBuilder pkg) throws RecognitionException {
BaseDescr descr = null;
try {
if (helper.validateIdentifierKey(DroolsSoftKeywords.IMPORT)) {
descr = importStatement(pkg);
if (state.failed)
return descr;
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.GLOBAL)) {
descr = globalStatement(pkg);
if (state.failed)
return descr;
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.DECLARE)) {
descr = declare(pkg);
if (state.failed)
return descr;
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.RULE)) {
descr = rule(pkg);
if (state.failed)
return descr;
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.QUERY)) {
descr = query(pkg);
if (state.failed)
return descr;
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.FUNCTION)) {
descr = function(pkg);
if (state.failed)
return descr;
} else if (helper.validateAttribute(1)) {
descr = attribute(pkg);
if (state.failed)
return descr;
}
} catch (RecognitionException e) {
helper.reportError(e);
} catch (Exception e) {
helper.reportError(e);
}
return descr;
}
/* ------------------------------------------------------------------------------------------------
* IMPORT STATEMENT
* ------------------------------------------------------------------------------------------------ */
/**
* importStatement := IMPORT ((FUNCTION|STATIC)? qualifiedIdentifier ((DOT STAR)?
* |(ACC|ACCUMULATE) qualifiedIdentifier ID)
*
* @return
* @throws org.antlr.runtime.RecognitionException
*/
public ImportDescr importStatement(PackageDescrBuilder pkg) throws RecognitionException {
try {
String kwd;
if (helper.validateLT(2, kwd = DroolsSoftKeywords.ACC) ||
helper.validateLT(2, kwd = DroolsSoftKeywords.ACCUMULATE)) {
AccumulateImportDescrBuilder imp = helper.start(pkg,
AccumulateImportDescrBuilder.class,
null);
try {
// import
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.IMPORT,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
// import accumulate
match(input,
DRL6Lexer.ID,
kwd,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
// qualifiedIdentifier
String target = qualifiedIdentifier();
if (state.failed)
return null;
// function name
Token id = match(input,
DRL6Lexer.ID,
null,
null,
DroolsEditorType.IDENTIFIER);
if (state.failed)
return null;
if (state.backtracking == 0) {
imp.target(target).functionName(id.getText());
}
return (imp != null) ? imp.getDescr() : null;
} finally {
helper.end(AccumulateImportDescrBuilder.class,
imp);
}
} else {
ImportDescrBuilder imp = helper.start(pkg,
ImportDescrBuilder.class,
null);
try {
// import
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.IMPORT,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
if (helper.validateIdentifierKey(kwd = DroolsSoftKeywords.FUNCTION) ||
helper.validateIdentifierKey(kwd = DroolsSoftKeywords.STATIC)) {
// function
match(input,
DRL6Lexer.ID,
kwd,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
}
// qualifiedIdentifier
String target = qualifiedIdentifier();
if (state.failed)
return null;
if (input.LA(1) == DRL6Lexer.DOT && input.LA(2) == DRL6Lexer.STAR) {
// .*
match(input,
DRL6Lexer.DOT,
null,
null,
DroolsEditorType.IDENTIFIER);
if (state.failed)
return null;
match(input,
DRL6Lexer.STAR,
null,
null,
DroolsEditorType.IDENTIFIER);
if (state.failed)
return null;
target += ".*";
}
if (state.backtracking == 0)
imp.target(target);
return (imp != null) ? imp.getDescr() : null;
} finally {
helper.end(ImportDescrBuilder.class,
imp);
}
}
} catch (RecognitionException re) {
reportError(re);
}
return null;
}
/* ------------------------------------------------------------------------------------------------
* GLOBAL STATEMENT
* ------------------------------------------------------------------------------------------------ */
/**
* globalStatement := GLOBAL type ID
*
* @return
* @throws org.antlr.runtime.RecognitionException
*/
public GlobalDescr globalStatement(PackageDescrBuilder pkg) throws RecognitionException {
GlobalDescrBuilder global = null;
try {
global = helper.start(pkg,
GlobalDescrBuilder.class,
null);
// 'global'
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.GLOBAL,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
// type
String type = type();
if (state.backtracking == 0)
global.type(type);
if (state.failed)
return null;
// identifier
Token id = match(input,
DRL6Lexer.ID,
null,
null,
DroolsEditorType.IDENTIFIER_TYPE);
if (state.failed)
return null;
if (state.backtracking == 0) {
global.identifier(id.getText());
helper.setParaphrasesValue(DroolsParaphraseTypes.GLOBAL,
id.getText());
}
} catch (RecognitionException re) {
reportError(re);
} finally {
helper.end(GlobalDescrBuilder.class,
global);
}
return (global != null) ? global.getDescr() : null;
}
/* ------------------------------------------------------------------------------------------------
* DECLARE STATEMENT
* ------------------------------------------------------------------------------------------------ */
/**
* declare := DECLARE
* | (ENTRY-POINT) => entryPointDeclaration
* | (WINDOW) => windowDeclaration
* | (TRAIT) => typeDeclaration (trait)
* | (ENUM) => enumDeclaration
* | typeDeclaration (class)
* END
*
* @return
* @throws org.antlr.runtime.RecognitionException
*/
public BaseDescr declare(PackageDescrBuilder pkg) throws RecognitionException {
BaseDescr declaration = null;
try {
DeclareDescrBuilder declare = helper.start(pkg,
DeclareDescrBuilder.class,
null);
// 'declare'
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.DECLARE,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
if (helper.validateIdentifierKey(DroolsSoftKeywords.ENTRY)) {
// entry point declaration
declaration = entryPointDeclaration(declare);
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.WINDOW)) {
// window declaration
declaration = windowDeclaration(declare);
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.TRAIT)) {
// trait type declaration
// 'trait'
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.TRAIT,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
declaration = typeDeclaration(declare, true);
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.ENUM)) {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.ENUM,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
declaration = enumDeclaration(declare);
} else {
// class type declaration
declaration = typeDeclaration(declare, false);
}
} catch (RecognitionException re) {
reportError(re);
}
return declaration;
}
/**
* entryPointDeclaration := annotation* ENTRY-POINT stringId END
*
* @return
* @throws org.antlr.runtime.RecognitionException
*/
public EntryPointDeclarationDescr entryPointDeclaration(DeclareDescrBuilder ddb) throws RecognitionException {
EntryPointDeclarationDescrBuilder declare = null;
try {
declare = helper.start(ddb,
EntryPointDeclarationDescrBuilder.class,
null);
setAnnotationsOn(declare);
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.ENTRY,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
match(input,
DRL6Lexer.MINUS,
null,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.POINT,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
String ep = stringId();
if (state.failed)
return null;
if (state.backtracking == 0) {
declare.entryPointId(ep);
}
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.END,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
} catch (RecognitionException re) {
reportError(re);
} finally {
helper.end(EntryPointDeclarationDescrBuilder.class,
declare);
}
return (declare != null) ? declare.getDescr() : null;
}
/**
* windowDeclaration := annotation* WINDOW ID lhsPatternBind END
*
* @return
* @throws org.antlr.runtime.RecognitionException
*/
public WindowDeclarationDescr windowDeclaration(DeclareDescrBuilder ddb) throws RecognitionException {
WindowDeclarationDescrBuilder declare = null;
try {
declare = helper.start(ddb,
WindowDeclarationDescrBuilder.class,
null);
setAnnotationsOn(declare);
String window = "";
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.WINDOW,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
Token id = match(input,
DRL6Lexer.ID,
null,
null,
DroolsEditorType.IDENTIFIER);
if (state.failed)
return null;
window = id.getText();
if (state.backtracking == 0) {
declare.name(window);
}
lhsPatternBind(declare, false);
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.END,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
} catch (RecognitionException re) {
reportError(re);
} finally {
helper.end(WindowDeclarationDescrBuilder.class,
declare);
}
return (declare != null) ? declare.getDescr() : null;
}
/*
* typeDeclaration := annotation* [ENUM] qualifiedIdentifier
* enumerative+
* field*
* END
*
* @return
* @throws RecognitionException
*/
public EnumDeclarationDescr enumDeclaration(DeclareDescrBuilder ddb) throws RecognitionException {
EnumDeclarationDescrBuilder declare = null;
try {
declare = helper.start(ddb,
EnumDeclarationDescrBuilder.class,
null);
setAnnotationsOn(declare);
// type may be qualified when adding metadata
String type = qualifiedIdentifier();
if (state.failed)
return null;
if (state.backtracking == 0)
declare.name(type);
while (input.LA(1) == DRL6Lexer.ID) {
int next = input.LA(2);
if (next == DRL6Lexer.LEFT_PAREN || next == DRL6Lexer.COMMA || next == DRL6Lexer.SEMICOLON) {
enumerative(declare);
if (state.failed)
return null;
}
if (input.LA(1) == DRL6Lexer.COMMA) {
match(input,
DRL6Lexer.COMMA,
null,
null,
DroolsEditorType.SYMBOL);
} else {
match(input,
DRL6Lexer.SEMICOLON,
null,
null,
DroolsEditorType.SYMBOL);
break;
}
}
//boolean qualified = type.indexOf( '.' ) >= 0;
while ( //! qualified &&
input.LA(1) == DRL6Lexer.ID && !helper.validateIdentifierKey(DroolsSoftKeywords.END)) {
// field*
field(declare);
if (state.failed)
return null;
}
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.END,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
} catch (RecognitionException re) {
reportError(re);
} finally {
helper.end(TypeDeclarationDescrBuilder.class,
declare);
}
return (declare != null) ? declare.getDescr() : null;
}
/**
* typeDeclaration := annotation* [TYPE] qualifiedIdentifier (EXTENDS qualifiedIdentifier)?
* field*
* END
*
* @return
* @throws org.antlr.runtime.RecognitionException
*/
public TypeDeclarationDescr typeDeclaration(DeclareDescrBuilder ddb, boolean isTrait) throws RecognitionException {
TypeDeclarationDescrBuilder declare = null;
try {
declare = helper.start(ddb,
TypeDeclarationDescrBuilder.class,
null);
setAnnotationsOn(declare);
declare.setTrait(isTrait);
if (helper.validateIdentifierKey(DroolsSoftKeywords.TYPE)) {
// 'type'
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.TYPE,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
}
// type may be qualified when adding metadata
String type = qualifiedIdentifier();
if (state.failed)
return null;
if (state.backtracking == 0)
declare.name(type);
if (helper.validateIdentifierKey(DroolsSoftKeywords.EXTENDS)) {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.EXTENDS,
null,
DroolsEditorType.KEYWORD);
if (!state.failed) {
// Going for type includes generics, which is a no-no (JIRA-3040)
String superType = qualifiedIdentifier();
declare.superType(superType);
while (input.LA(1) == DRL6Lexer.COMMA) {
match(input,
DRL6Lexer.COMMA,
null,
null,
DroolsEditorType.SYMBOL);
superType = qualifiedIdentifier();
declare.superType(superType);
}
}
}
//boolean qualified = type.indexOf( '.' ) >= 0;
while ( (input.LA(1) == DRL6Lexer.ID || input.LA(1) == DRL6Lexer.AT) &&
!helper.validateIdentifierKey(DroolsSoftKeywords.END)) {
// field*
field(declare);
if (state.failed)
return null;
}
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.END,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
} catch (RecognitionException re) {
reportError(re);
} finally {
helper.end(TypeDeclarationDescrBuilder.class,
declare);
}
return (declare != null) ? declare.getDescr() : null;
}
/**
* enumerative := ID ( LEFT_PAREN expression (COMMA expression)* RIGHT_PAREN )?
*/
private void enumerative(EnumDeclarationDescrBuilder declare) {
EnumLiteralDescrBuilder literal = null;
String lit = null;
try {
Token enumLit = match(input,
DRL6Lexer.ID,
null,
null,
DroolsEditorType.IDENTIFIER);
lit = enumLit.getText();
if (state.failed)
return;
} catch (RecognitionException re) {
reportError(re);
}
try {
literal = helper.start(declare,
EnumLiteralDescrBuilder.class,
lit);
if (input.LA(1) == DRL6Lexer.LEFT_PAREN) {
match(input,
DRL6Lexer.LEFT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
boolean more;
do {
int first = input.index();
exprParser.conditionalExpression();
if (state.failed)
return;
if (state.backtracking == 0 && input.index() > first) {
// expression consumed something
String arg = input.toString(first,
input.LT(-1).getTokenIndex());
literal.constructorArg(arg);
}
more = input.LA(1) == DRL6Lexer.COMMA;
if (more) {
match(input,
DRL6Lexer.COMMA,
null,
null,
DroolsEditorType.SYMBOL);
}
} while (more);
match(input,
DRL6Lexer.RIGHT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
}
} catch (RecognitionException re) {
reportError(re);
} finally {
helper.end(FieldDescrBuilder.class,
literal);
}
}
/**
* field := annotation* label fieldType (EQUALS_ASSIGN conditionalExpression)? SEMICOLON?
*/
private void field(AbstractClassTypeDeclarationBuilder declare) {
annotations();
FieldDescrBuilder field = null;
String fname = null;
try {
fname = label(DroolsEditorType.IDENTIFIER);
if (state.failed)
return;
} catch (RecognitionException re) {
reportError(re);
}
try {
field = helper.start(declare,
FieldDescrBuilder.class,
fname);
setAnnotationsOn(field);
// type
String type = type();
if (state.failed)
return;
if (state.backtracking == 0)
field.type(type);
if (input.LA(1) == DRL6Lexer.EQUALS_ASSIGN) {
// EQUALS_ASSIGN
match(input,
DRL6Lexer.EQUALS_ASSIGN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
int first = input.index();
exprParser.conditionalExpression();
if (state.failed)
return;
if (state.backtracking == 0 && input.index() > first) {
// expression consumed something
String value = input.toString(first,
input.LT(-1).getTokenIndex());
field.initialValue(value);
}
}
if (input.LA(1) == DRL6Lexer.SEMICOLON) {
match(input,
DRL6Lexer.SEMICOLON,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
}
} catch (RecognitionException re) {
reportError(re);
} finally {
helper.end(FieldDescrBuilder.class,
field);
}
}
/* ------------------------------------------------------------------------------------------------
* FUNCTION STATEMENT
* ------------------------------------------------------------------------------------------------ */
/**
* function := FUNCTION type? ID parameters(typed) chunk_{_}
*
* @return
* @throws org.antlr.runtime.RecognitionException
*/
public FunctionDescr function(PackageDescrBuilder pkg) throws RecognitionException {
FunctionDescrBuilder function = null;
try {
function = helper.start(pkg,
FunctionDescrBuilder.class,
null);
// 'function'
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.FUNCTION,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
if (input.LA(1) != DRL6Lexer.ID || input.LA(2) != DRL6Lexer.LEFT_PAREN) {
// type
String type = type();
if (state.failed)
return null;
if (state.backtracking == 0)
function.returnType(type);
}
// name
Token id = match(input,
DRL6Lexer.ID,
null,
null,
DroolsEditorType.IDENTIFIER);
if (state.failed)
return null;
if (state.backtracking == 0) {
function.name(id.getText());
helper.setParaphrasesValue(DroolsParaphraseTypes.FUNCTION,
"\"" + id.getText() + "\"");
}
// arguments
parameters(function,
true);
if (state.failed)
return null;
// body
String body = chunk(DRL6Lexer.LEFT_CURLY,
DRL6Lexer.RIGHT_CURLY,
-1);
if (state.failed)
return null;
if (state.backtracking == 0)
function.body(body);
} catch (RecognitionException re) {
reportError(re);
} finally {
helper.end(FunctionDescrBuilder.class,
function);
}
return (function != null) ? function.getDescr() : null;
}
/**
* parameters := LEFT_PAREN ( parameter ( COMMA parameter )* )? RIGHT_PAREN
* @param statement
* @param requiresType
* @throws org.antlr.runtime.RecognitionException
*/
private void parameters(ParameterSupportBuilder> statement,
boolean requiresType) throws RecognitionException {
match(input,
DRL6Lexer.LEFT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
if (input.LA(1) != DRL6Lexer.RIGHT_PAREN) {
parameter(statement,
requiresType);
if (state.failed)
return;
while (input.LA(1) == DRL6Lexer.COMMA) {
match(input,
DRL6Lexer.COMMA,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
parameter(statement,
requiresType);
if (state.failed)
return;
}
}
match(input,
DRL6Lexer.RIGHT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
}
/**
* parameter := ({requiresType}?=>type)? ID (LEFT_SQUARE RIGHT_SQUARE)*
* @param statement
* @param requiresType
* @throws org.antlr.runtime.RecognitionException
*/
private void parameter(ParameterSupportBuilder> statement,
boolean requiresType) throws RecognitionException {
String type = "Object";
if (requiresType) {
type = type();
if (state.failed)
return;
}
int start = input.index();
match(input,
DRL6Lexer.ID,
null,
null,
DroolsEditorType.IDENTIFIER);
if (state.failed)
return;
while (input.LA(1) == DRL6Lexer.LEFT_SQUARE) {
match(input,
DRL6Lexer.LEFT_SQUARE,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
match(input,
DRL6Lexer.RIGHT_SQUARE,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
}
int end = input.LT(-1).getTokenIndex();
if (state.backtracking == 0)
statement.parameter(type,
input.toString(start,
end));
}
/* ------------------------------------------------------------------------------------------------
* QUERY STATEMENT
* ------------------------------------------------------------------------------------------------ */
/**
* query := annotation* QUERY stringId parameters? lhsExpression END
*
* @return
* @throws org.antlr.runtime.RecognitionException
*/
public RuleDescr query(PackageDescrBuilder pkg) throws RecognitionException {
QueryDescrBuilder query = null;
try {
query = helper.start(pkg,
QueryDescrBuilder.class,
null);
setAnnotationsOn(query);
// 'query'
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.QUERY,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
if (helper.validateIdentifierKey(DroolsSoftKeywords.WHEN) ||
helper.validateIdentifierKey(DroolsSoftKeywords.THEN) ||
helper.validateIdentifierKey(DroolsSoftKeywords.END)) {
failMissingTokenException();
return null; // in case it is backtracking
}
String name = stringId();
if (state.backtracking == 0)
query.name(name);
if (state.failed)
return null;
if (state.backtracking == 0) {
helper.emit(Location.LOCATION_RULE_HEADER);
}
if (speculateParameters(true)) {
// parameters
parameters(query,
true);
if (state.failed)
return null;
if (state.backtracking == 0) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION);
}
} else if (speculateParameters(false)) {
// parameters
parameters(query,
false);
if (state.failed)
return null;
if (state.backtracking == 0) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION);
}
}
if (state.backtracking == 0 && input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION);
}
if (input.LA(1) != DRL6Lexer.EOF) {
lhsExpression(query != null ? query.lhs() : null);
}
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.END,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
helper.emit(Location.LOCATION_RHS);
} catch (RecognitionException re) {
reportError(re);
} finally {
helper.end(QueryDescrBuilder.class,
query);
}
return (query != null) ? query.getDescr() : null;
}
private boolean speculateParameters(boolean requiresType) {
state.backtracking++;
int start = input.mark();
try {
parameters(null,
requiresType); // can never throw exception
} catch (RecognitionException re) {
System.err.println("impossible: " + re);
re.printStackTrace();
}
boolean success = !state.failed;
input.rewind(start);
state.backtracking--;
state.failed = false;
return success;
}
/* ------------------------------------------------------------------------------------------------
* RULE STATEMENT
* ------------------------------------------------------------------------------------------------ */
/**
* rule := annotation* RULE stringId (EXTENDS stringId)? attributes? lhs? rhs END
*
* @return
* @throws org.antlr.runtime.RecognitionException
*/
public RuleDescr rule(PackageDescrBuilder pkg) throws RecognitionException {
RuleDescrBuilder rule = null;
try {
rule = helper.start(pkg,
RuleDescrBuilder.class,
null);
setAnnotationsOn(rule);
// 'rule'
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.RULE,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
if (helper.validateIdentifierKey(DroolsSoftKeywords.WHEN) ||
helper.validateIdentifierKey(DroolsSoftKeywords.THEN) ||
helper.validateIdentifierKey(DroolsSoftKeywords.END)) {
failMissingTokenException();
return null; // in case it is backtracking
}
String name = stringId();
if (state.failed)
return null;
if (state.backtracking == 0) {
rule.name(name);
helper.setParaphrasesValue(DroolsParaphraseTypes.RULE,
"\"" + name + "\"");
helper.emit(Location.LOCATION_RULE_HEADER);
}
if (helper.validateIdentifierKey(DroolsSoftKeywords.EXTENDS)) {
// 'extends'
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.EXTENDS,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
String parent = stringId();
if (state.backtracking == 0)
rule.extendsRule(parent);
if (state.failed)
return null;
}
if (state.backtracking == 0 && input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_RULE_HEADER);
}
attributes(rule);
if (helper.validateIdentifierKey(DroolsSoftKeywords.WHEN)) {
lhs(rule);
} else {
// creates an empty LHS
rule.lhs();
}
rhs(rule);
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.END,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
} catch (RecognitionException re) {
reportError(re);
} finally {
helper.end(RuleDescrBuilder.class,
rule);
}
return (rule != null) ? rule.getDescr() : null;
}
/**
* stringId := ( ID | STRING )
* @return
* @throws org.antlr.runtime.RecognitionException
*/
String stringId() throws RecognitionException {
if (input.LA(1) == DRL6Lexer.ID) {
Token id = match(input,
DRL6Lexer.ID,
null,
null,
DroolsEditorType.IDENTIFIER);
if (state.failed)
return null;
return id.getText();
} else if (input.LA(1) == DRL6Lexer.STRING) {
Token id = match(input,
DRL6Lexer.STRING,
null,
null,
DroolsEditorType.IDENTIFIER);
if (state.failed)
return null;
return StringUtils.unescapeJava(safeStripStringDelimiters(id.getText()));
} else {
throw new MismatchedTokenException(DRL6Lexer.ID,
input);
}
}
/**
* attributes := (ATTRIBUTES COLON?)? [ attribute ( COMMA? attribute )* ]
* @param rule
* @throws org.antlr.runtime.RecognitionException
*/
void attributes( RuleDescrBuilder rule ) throws RecognitionException {
if (helper.validateIdentifierKey(DroolsSoftKeywords.ATTRIBUTES)) {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.ATTRIBUTES,
null,
DroolsEditorType.IDENTIFIER);
if (state.failed)
return;
if (input.LA(1) == DRL6Lexer.COLON) {
match(input,
DRL6Lexer.COLON,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
}
}
if (helper.validateAttribute(1)) {
attribute(rule);
if (state.failed)
return;
while (input.LA(1) == DRL6Lexer.COMMA || helper.validateAttribute(1)) {
if (input.LA(1) == DRL6Lexer.COMMA) {
match(input,
DRL6Lexer.COMMA,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
}
attribute(rule);
if (state.failed)
return;
}
}
}
/**
* attribute :=
* salience
* | enabled
* | ( NO-LOOP
* | AUTO-FOCUS
* | LOCK-ON-ACTIVE
* | REFRACT
* | DIRECT
* ) BOOLEAN?
* | ( AGENDA-GROUP
* | ACTIVATION-GROUP
* | RULEFLOW-GROUP
* | DATE-EFFECTIVE
* | DATE-EXPIRES
* | DIALECT
* ) STRING
* | CALENDARS STRING (COMMA STRING)*
* | TIMER ( DECIMAL | chunk_(_) )
* | DURATION ( DECIMAL | chunk_(_) )
*
* The above syntax is not quite how this is parsed, because the soft keyword
* is determined by look-ahead and passed on to one of the x-Attribute methods
* (booleanAttribute, stringAttribute, stringListAttribute, intOrChunkAttribute)
* which will actually gobble the tokens.
*
* @return
*/
public AttributeDescr attribute(AttributeSupportBuilder> as) {
AttributeDescr attribute = null;
try {
if (state.backtracking == 0 && input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_RULE_HEADER_KEYWORD);
}
if (helper.validateIdentifierKey(DroolsSoftKeywords.SALIENCE)) {
attribute = salience(as);
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.ENABLED)) {
attribute = enabled(as);
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.NO) &&
helper.validateLT(2,
"-") &&
helper.validateLT(3,
DroolsSoftKeywords.LOOP)) {
attribute = booleanAttribute(as,
new String[]{DroolsSoftKeywords.NO, "-", DroolsSoftKeywords.LOOP});
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.AUTO) &&
helper.validateLT(2,
"-") &&
helper.validateLT(3,
DroolsSoftKeywords.FOCUS)) {
attribute = booleanAttribute(as,
new String[]{DroolsSoftKeywords.AUTO, "-", DroolsSoftKeywords.FOCUS});
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.LOCK) &&
helper.validateLT(2,
"-") &&
helper.validateLT(3,
DroolsSoftKeywords.ON) &&
helper.validateLT(4,
"-") &&
helper.validateLT(5,
DroolsSoftKeywords.ACTIVE)) {
attribute = booleanAttribute(as,
new String[]{DroolsSoftKeywords.LOCK, "-", DroolsSoftKeywords.ON, "-", DroolsSoftKeywords.ACTIVE});
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.REFRACT)) {
attribute = booleanAttribute(as,
new String[]{DroolsSoftKeywords.REFRACT});
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.DIRECT)) {
attribute = booleanAttribute(as,
new String[]{DroolsSoftKeywords.DIRECT});
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.AGENDA) &&
helper.validateLT(2,
"-") &&
helper.validateLT(3,
DroolsSoftKeywords.GROUP)) {
attribute = stringAttribute(as,
new String[]{DroolsSoftKeywords.AGENDA, "-", DroolsSoftKeywords.GROUP});
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.ACTIVATION) &&
helper.validateLT(2,
"-") &&
helper.validateLT(3,
DroolsSoftKeywords.GROUP)) {
attribute = stringAttribute(as,
new String[]{DroolsSoftKeywords.ACTIVATION, "-", DroolsSoftKeywords.GROUP});
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.RULEFLOW) &&
helper.validateLT(2,
"-") &&
helper.validateLT(3,
DroolsSoftKeywords.GROUP)) {
attribute = stringAttribute(as,
new String[]{DroolsSoftKeywords.RULEFLOW, "-", DroolsSoftKeywords.GROUP});
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.DATE) &&
helper.validateLT(2,
"-") &&
helper.validateLT(3,
DroolsSoftKeywords.EFFECTIVE)) {
attribute = stringAttribute(as,
new String[]{DroolsSoftKeywords.DATE, "-", DroolsSoftKeywords.EFFECTIVE});
if (attribute != null) {
attribute.setType(AttributeDescr.Type.DATE);
} else {
throw new RecognitionException();
}
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.DATE) &&
helper.validateLT(2,
"-") &&
helper.validateLT(3,
DroolsSoftKeywords.EXPIRES)) {
attribute = stringAttribute(as,
new String[]{DroolsSoftKeywords.DATE, "-", DroolsSoftKeywords.EXPIRES});
if (attribute != null) {
attribute.setType(AttributeDescr.Type.DATE);
} else {
throw new RecognitionException();
}
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.DIALECT)) {
attribute = stringAttribute(as,
new String[]{DroolsSoftKeywords.DIALECT});
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.CALENDARS)) {
attribute = stringListAttribute(as,
new String[]{DroolsSoftKeywords.CALENDARS});
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.TIMER)) {
attribute = intOrChunkAttribute(as,
new String[]{DroolsSoftKeywords.TIMER});
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.DURATION)) {
attribute = intOrChunkAttribute(as,
new String[]{DroolsSoftKeywords.DURATION});
}
if (state.backtracking == 0) {
helper.emit(Location.LOCATION_RULE_HEADER);
}
} catch (RecognitionException re) {
reportError(re);
}
return attribute;
}
/**
* salience := SALIENCE conditionalExpression
* @throws org.antlr.runtime.RecognitionException
*/
private AttributeDescr salience(AttributeSupportBuilder> as) throws RecognitionException {
AttributeDescrBuilder> attribute = null;
try {
// 'salience'
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.SALIENCE,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
if (state.backtracking == 0) {
attribute = helper.start((DescrBuilder, ?>) as,
AttributeDescrBuilder.class,
DroolsSoftKeywords.SALIENCE);
}
boolean hasParen = input.LA(1) == DRL6Lexer.LEFT_PAREN;
int first = input.index();
if (hasParen) {
match(input,
DRL6Lexer.LEFT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
}
String value = conditionalExpression();
if (state.failed)
return null;
if (hasParen) {
match(input,
DRL6Lexer.RIGHT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
}
if (state.backtracking == 0) {
if (attribute != null) {
if (hasParen) {
value = input.toString(first,
input.LT(-1).getTokenIndex());
}
attribute.value(value);
attribute.type(AttributeDescr.Type.EXPRESSION);
}
}
} finally {
if (attribute != null) {
helper.end(AttributeDescrBuilder.class,
attribute);
}
}
return attribute != null ? attribute.getDescr() : null;
}
/**
* enabled := ENABLED conditionalExpression
* @throws org.antlr.runtime.RecognitionException
*/
private AttributeDescr enabled(AttributeSupportBuilder> as) throws RecognitionException {
AttributeDescrBuilder> attribute = null;
try {
// 'enabled'
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.ENABLED,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
if (state.backtracking == 0) {
attribute = helper.start((DescrBuilder, ?>) as,
AttributeDescrBuilder.class,
DroolsSoftKeywords.ENABLED);
}
boolean hasParen = input.LA(1) == DRL6Lexer.LEFT_PAREN;
int first = input.index();
if (hasParen) {
match(input,
DRL6Lexer.LEFT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
}
String value = conditionalExpression();
if (state.failed)
return null;
if (hasParen) {
match(input,
DRL6Lexer.RIGHT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
}
if (state.backtracking == 0) {
if (attribute != null) {
if (hasParen) {
value = input.toString(first,
input.LT(-1).getTokenIndex());
}
attribute.value(value);
attribute.type(AttributeDescr.Type.EXPRESSION);
}
}
} finally {
if (attribute != null) {
helper.end(AttributeDescrBuilder.class,
attribute);
}
}
return attribute != null ? attribute.getDescr() : null;
}
/**
* booleanAttribute := attributeKey (BOOLEAN)?
* @param key
* @throws org.antlr.runtime.RecognitionException
*/
private AttributeDescr booleanAttribute(AttributeSupportBuilder> as,
String[] key) throws RecognitionException {
AttributeDescrBuilder> attribute = null;
try {
StringBuilder builder = new StringBuilder();
for (String k : key) {
if ("-".equals(k)) {
match(input,
DRL6Lexer.MINUS,
k,
null,
DroolsEditorType.KEYWORD); // part of the keyword
if (state.failed)
return null;
} else {
match(input,
DRL6Lexer.ID,
k,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
}
builder.append(k);
}
if (state.backtracking == 0) {
attribute = helper.start((DescrBuilder, ?>) as,
AttributeDescrBuilder.class,
builder.toString());
}
String value = "true";
if (input.LA(1) == DRL6Lexer.BOOL) {
Token bool = match(input,
DRL6Lexer.BOOL,
null,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
value = bool.getText();
}
if (state.backtracking == 0) {
if (attribute != null) {
attribute.value(value);
attribute.type(AttributeDescr.Type.BOOLEAN);
}
}
} finally {
if (attribute != null) {
helper.end(AttributeDescrBuilder.class,
attribute);
}
}
return attribute != null ? attribute.getDescr() : null;
}
/**
* stringAttribute := attributeKey STRING
* @param key
* @throws org.antlr.runtime.RecognitionException
*/
private AttributeDescr stringAttribute(AttributeSupportBuilder> as,
String[] key) throws RecognitionException {
AttributeDescrBuilder> attribute = null;
try {
StringBuilder builder = new StringBuilder();
for (String k : key) {
if ("-".equals(k)) {
match(input,
DRL6Lexer.MINUS,
k,
null,
DroolsEditorType.KEYWORD); // part of the keyword
if (state.failed)
return null;
} else {
match(input,
DRL6Lexer.ID,
k,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
}
builder.append(k);
}
if (state.backtracking == 0) {
attribute = helper.start((DescrBuilder, ?>) as,
AttributeDescrBuilder.class,
builder.toString());
}
Token value = match(input,
DRL6Lexer.STRING,
null,
null,
DroolsEditorType.STRING_CONST);
if (state.failed)
return null;
if (state.backtracking == 0) {
if (attribute != null) {
attribute.value(StringUtils.unescapeJava(safeStripStringDelimiters(value.getText())));
attribute.type(AttributeDescr.Type.STRING);
}
}
} finally {
if (attribute != null) {
helper.end(AttributeDescrBuilder.class,
attribute);
}
}
return attribute != null ? attribute.getDescr() : null;
}
/**
* stringListAttribute := attributeKey STRING (COMMA STRING)*
* @param key
* @throws org.antlr.runtime.RecognitionException
*/
private AttributeDescr stringListAttribute(AttributeSupportBuilder> as,
String[] key) throws RecognitionException {
AttributeDescrBuilder> attribute = null;
try {
StringBuilder builder = new StringBuilder();
for (String k : key) {
if ("-".equals(k)) {
match(input,
DRL6Lexer.MINUS,
k,
null,
DroolsEditorType.KEYWORD); // part of the keyword
if (state.failed)
return null;
} else {
match(input,
DRL6Lexer.ID,
k,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
}
builder.append(k);
}
if (state.backtracking == 0) {
attribute = helper.start((DescrBuilder, ?>) as,
AttributeDescrBuilder.class,
builder.toString());
}
builder = new StringBuilder();
builder.append("[ ");
Token value = match(input,
DRL6Lexer.STRING,
null,
null,
DroolsEditorType.STRING_CONST);
if (state.failed)
return null;
builder.append(value.getText());
while (input.LA(1) == DRL6Lexer.COMMA) {
match(input,
DRL6Lexer.COMMA,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
builder.append(", ");
value = match(input,
DRL6Lexer.STRING,
null,
null,
DroolsEditorType.STRING_CONST);
if (state.failed)
return null;
builder.append(value.getText());
}
builder.append(" ]");
if (state.backtracking == 0) {
if (attribute != null) {
attribute.value(builder.toString());
attribute.type(AttributeDescr.Type.LIST);
}
}
} finally {
if (attribute != null) {
helper.end(AttributeDescrBuilder.class,
attribute);
}
}
return attribute != null ? attribute.getDescr() : null;
}
/**
* intOrChunkAttribute := attributeKey ( DECIMAL | chunk_(_) )
* @param key
* @throws org.antlr.runtime.RecognitionException
*/
private AttributeDescr intOrChunkAttribute(AttributeSupportBuilder> as,
String[] key) throws RecognitionException {
AttributeDescrBuilder> attribute = null;
try {
StringBuilder builder = new StringBuilder();
for (String k : key) {
if ("-".equals(k)) {
match(input,
DRL6Lexer.MINUS,
k,
null,
DroolsEditorType.KEYWORD); // part of the keyword
if (state.failed)
return null;
} else {
match(input,
DRL6Lexer.ID,
k,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
}
builder.append(k);
}
if (state.backtracking == 0) {
attribute = helper.start((DescrBuilder, ?>) as,
AttributeDescrBuilder.class,
builder.toString());
}
if (input.LA(1) == DRL6Lexer.LEFT_PAREN) {
String value = chunk(DRL6Lexer.LEFT_PAREN,
DRL6Lexer.RIGHT_PAREN,
-1);
if (state.failed)
return null;
if (state.backtracking == 0) {
if (attribute != null) {
attribute.value(safeStripDelimiters(value,
"(",
")"));
attribute.type(AttributeDescr.Type.EXPRESSION);
}
}
} else {
String value = "";
if (input.LA(1) == DRL6Lexer.PLUS) {
Token sign = match(input,
DRL6Lexer.PLUS,
null,
null,
DroolsEditorType.NUMERIC_CONST);
if (state.failed)
return null;
value += sign.getText();
} else if (input.LA(1) == DRL6Lexer.MINUS) {
Token sign = match(input,
DRL6Lexer.MINUS,
null,
null,
DroolsEditorType.NUMERIC_CONST);
if (state.failed)
return null;
value += sign.getText();
}
Token nbr = match(input,
DRL6Lexer.DECIMAL,
null,
null,
DroolsEditorType.NUMERIC_CONST);
if (state.failed)
return null;
value += nbr.getText();
if (state.backtracking == 0) {
if (attribute != null) {
attribute.value(value);
attribute.type(AttributeDescr.Type.NUMBER);
}
}
}
} finally {
if (attribute != null) {
helper.end(AttributeDescrBuilder.class,
attribute);
}
}
return attribute != null ? attribute.getDescr() : null;
}
/**
* lhs := WHEN COLON? lhsExpression
* @param rule
* @throws org.antlr.runtime.RecognitionException
*/
void lhs( RuleDescrBuilder rule ) throws RecognitionException {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.WHEN,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return;
if (input.LA(1) == DRL6Lexer.COLON) {
match(input,
DRL6Lexer.COLON,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
}
lhsExpression(rule != null ? rule.lhs() : null);
}
/**
* lhsExpression := lhsOr*
*
* @param lhs
* @throws org.antlr.runtime.RecognitionException
*/
private void lhsExpression(CEDescrBuilder, AndDescr> lhs) throws RecognitionException {
helper.start(lhs,
CEDescrBuilder.class,
null);
if (state.backtracking == 0) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION);
}
try {
while (input.LA(1) != DRL6Lexer.EOF &&
!helper.validateIdentifierKey(DroolsSoftKeywords.THEN) &&
!helper.validateIdentifierKey(DroolsSoftKeywords.END)) {
if (state.backtracking == 0) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION);
}
lhsOr(lhs,
true);
if (lhs.getDescr() != null && lhs.getDescr() instanceof ConditionalElementDescr) {
ConditionalElementDescr root = (ConditionalElementDescr) lhs.getDescr();
BaseDescr[] descrs = root.getDescrs().toArray(new BaseDescr[root.getDescrs().size()]);
root.getDescrs().clear();
for (int i = 0; i < descrs.length; i++) {
root.addOrMerge(descrs[i]);
}
}
if (state.failed)
return;
}
} finally {
helper.end(CEDescrBuilder.class,
lhs);
}
}
/**
* lhsOr := LEFT_PAREN OR lhsAnd+ RIGHT_PAREN
* | lhsAnd (OR lhsAnd)*
*
* @param ce
* @param allowOr
* @throws org.antlr.runtime.RecognitionException
*/
private BaseDescr lhsOr(final CEDescrBuilder, ?> ce,
boolean allowOr) throws RecognitionException {
BaseDescr result = null;
if (allowOr && input.LA(1) == DRL6Lexer.LEFT_PAREN && helper.validateLT(2,
DroolsSoftKeywords.OR)) {
// prefixed OR
CEDescrBuilder, OrDescr> or = null;
if (state.backtracking == 0) {
or = ce.or();
result = or.getDescr();
helper.start(or,
CEDescrBuilder.class,
null);
}
try {
match(input,
DRL6Lexer.LEFT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.OR,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
if (state.backtracking == 0) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION_AND_OR);
}
while (input.LA(1) != DRL6Lexer.RIGHT_PAREN) {
lhsAnd(or,
allowOr);
if (state.failed)
return null;
}
match(input,
DRL6Lexer.RIGHT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
} finally {
if (state.backtracking == 0) {
helper.end(CEDescrBuilder.class,
or);
}
}
} else {
// infix OR
// create an OR anyway, as if it is not an OR we remove it later
CEDescrBuilder, OrDescr> or = null;
if (state.backtracking == 0) {
or = ce.or();
result = or.getDescr();
helper.start(or,
CEDescrBuilder.class,
null);
}
try {
lhsAnd(or,
allowOr);
if (state.failed)
return null;
if (allowOr &&
(helper.validateIdentifierKey(DroolsSoftKeywords.OR)
||
input.LA(1) == DRL6Lexer.DOUBLE_PIPE)) {
while (helper.validateIdentifierKey(DroolsSoftKeywords.OR) ||
input.LA(1) == DRL6Lexer.DOUBLE_PIPE) {
if (input.LA(1) == DRL6Lexer.DOUBLE_PIPE) {
match(input,
DRL6Lexer.DOUBLE_PIPE,
null,
null,
DroolsEditorType.SYMBOL);
} else {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.OR,
null,
DroolsEditorType.KEYWORD);
}
if (state.failed)
return null;
if (state.backtracking == 0) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION_AND_OR);
}
lhsAnd(or,
allowOr);
if (state.failed)
return null;
}
} else if (allowOr) {
if (state.backtracking == 0) {
// if no OR present, then remove it and add children to parent
((ConditionalElementDescr) ce.getDescr()).getDescrs().remove(or.getDescr());
for (BaseDescr base : or.getDescr().getDescrs()) {
((ConditionalElementDescr) ce.getDescr()).addDescr(base);
}
result = ce.getDescr();
}
}
} finally {
if (state.backtracking == 0) {
helper.end(CEDescrBuilder.class,
or);
}
}
}
return result;
}
/**
* lhsAnd := LEFT_PAREN AND lhsUnary+ RIGHT_PAREN
* | lhsUnary (AND lhsUnary)*
*
* @param ce
* @throws org.antlr.runtime.RecognitionException
*/
private BaseDescr lhsAnd(final CEDescrBuilder, ?> ce,
boolean allowOr) throws RecognitionException {
BaseDescr result = null;
if (input.LA(1) == DRL6Lexer.LEFT_PAREN && helper.validateLT(2,
DroolsSoftKeywords.AND)) {
// prefixed AND
CEDescrBuilder, AndDescr> and = null;
if (state.backtracking == 0) {
and = ce.and();
result = ce.getDescr();
helper.start(and,
CEDescrBuilder.class,
null);
}
try {
match(input,
DRL6Lexer.LEFT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.AND,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
if (state.backtracking == 0) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION_AND_OR);
}
while (input.LA(1) != DRL6Lexer.RIGHT_PAREN) {
lhsUnary(and,
allowOr);
if (state.failed)
return null;
}
match(input,
DRL6Lexer.RIGHT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
} finally {
if (state.backtracking == 0) {
helper.end(CEDescrBuilder.class,
and);
}
}
} else {
// infix AND
// create an AND anyway, since if it is not an AND we remove it later
CEDescrBuilder, AndDescr> and = null;
if (state.backtracking == 0) {
and = ce.and();
result = and.getDescr();
helper.start(and,
CEDescrBuilder.class,
null);
}
try {
lhsUnary(and,
allowOr);
if (state.failed)
return null;
if (helper.validateIdentifierKey(DroolsSoftKeywords.AND) ||
input.LA(1) == DRL6Lexer.DOUBLE_AMPER) {
while (helper.validateIdentifierKey(DroolsSoftKeywords.AND) ||
input.LA(1) == DRL6Lexer.DOUBLE_AMPER) {
if (input.LA(1) == DRL6Lexer.DOUBLE_AMPER) {
match(input,
DRL6Lexer.DOUBLE_AMPER,
null,
null,
DroolsEditorType.SYMBOL);
} else {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.AND,
null,
DroolsEditorType.KEYWORD);
}
if (state.failed)
return null;
if (state.backtracking == 0) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION_AND_OR);
}
lhsUnary(and,
allowOr);
if (state.failed)
return null;
}
} else {
if (state.backtracking == 0 && and.getDescr().getDescrs().size() < 2) {
// if no AND present, then remove it and add children to parent
((ConditionalElementDescr) ce.getDescr()).getDescrs().remove(and.getDescr());
for (BaseDescr base : and.getDescr().getDescrs()) {
((ConditionalElementDescr) ce.getDescr()).addDescr(base);
}
result = ce.getDescr();
}
}
} finally {
if (state.backtracking == 0) {
helper.end(CEDescrBuilder.class,
and);
}
}
}
return result;
}
/**
* lhsUnary :=
* annotation*
* ( lhsExists namedConsequence?
* | lhsNot namedConsequence?
* | lhsEval consequenceInvocation*
* | lhsForall
* | lhsAccumulate
* | LEFT_PAREN lhsOr RIGHT_PAREN namedConsequence?
* | lhsPatternBind consequenceInvocation*
* )
* SEMICOLON?
*
* @param ce
* @return
*/
private BaseDescr lhsUnary(final CEDescrBuilder, ?> ce,
boolean allowOr) throws RecognitionException {
annotations();
BaseDescr result = null;
if (helper.validateIdentifierKey(DroolsSoftKeywords.EXISTS)) {
result = lhsExists(ce,
allowOr);
if (helper.validateIdentifierKey(DroolsSoftKeywords.DO)) {
namedConsequence(ce, null);
}
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.NOT)) {
result = lhsNot(ce,
allowOr);
if (helper.validateIdentifierKey(DroolsSoftKeywords.DO)) {
namedConsequence(ce, null);
}
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.EVAL)) {
result = lhsEval(ce);
for (BaseDescr i = consequenceInvocation(ce); i != null; i = consequenceInvocation(ce))
;
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.FORALL)) {
result = lhsForall(ce);
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.ACCUMULATE) || helper.validateIdentifierKey(DroolsSoftKeywords.ACC)) {
result = lhsAccumulate(ce);
} else if (input.LA(1) == DRL6Lexer.LEFT_PAREN) {
// the order here is very important: this if branch must come before the lhsPatternBind below
result = lhsParen(ce,
allowOr);
if (helper.validateIdentifierKey(DroolsSoftKeywords.DO)) {
namedConsequence(ce, null);
}
} else if (input.LA(1) == DRL6Lexer.ID || input.LA(1) == DRL6Lexer.QUESTION) {
result = lhsPatternBind(ce,
allowOr);
for (BaseDescr i = consequenceInvocation(ce); i != null; i = consequenceInvocation(ce))
;
} else {
failMismatchedTokenException();
}
if (input.LA(1) == DRL6Lexer.SEMICOLON) {
match(input,
DRL6Lexer.SEMICOLON,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
}
setAnnotationsOn(result);
return result;
}
/**
* consequenceInvocation := conditionalBranch | namedConsequence
*
* @param ce
* @return
*/
private BaseDescr consequenceInvocation(CEDescrBuilder, ?> ce) throws RecognitionException {
BaseDescr result = null;
if (helper.validateIdentifierKey(DroolsSoftKeywords.IF)) {
result = conditionalBranch(ce, null);
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.DO)) {
result = namedConsequence(ce, null);
}
return result;
}
/**
* conditionalBranch := IF LEFT_PAREN conditionalExpression RIGHT_PAREN
* ( namedConsequence | breakingNamedConsequence )
* ( ELSE ( namedConsequence | breakingNamedConsequence | conditionalBranch ) )?
*/
private BaseDescr conditionalBranch(CEDescrBuilder, ?> ce, ConditionalBranchDescrBuilder> conditionalBranch) throws RecognitionException {
if (conditionalBranch == null) {
conditionalBranch = helper.start((DescrBuilder, ?>) ce,
ConditionalBranchDescrBuilder.class,
null);
}
try {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.IF,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
EvalDescrBuilder> eval = conditionalBranch.condition();
if (!parseEvalExpression(eval))
return null;
if (helper.validateIdentifierKey(DroolsSoftKeywords.DO)) {
if (namedConsequence(null, conditionalBranch.consequence()) == null)
return null;
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.BREAK)) {
if (breakingNamedConsequence(null, conditionalBranch.consequence()) == null)
return null;
} else {
return null;
}
if (helper.validateIdentifierKey(DroolsSoftKeywords.ELSE)) {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.ELSE,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
ConditionalBranchDescrBuilder> elseBranch = conditionalBranch.otherwise();
if (helper.validateIdentifierKey(DroolsSoftKeywords.DO)) {
if (namedConsequence(null, elseBranch.consequence()) == null)
return null;
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.BREAK)) {
if (breakingNamedConsequence(null, elseBranch.consequence()) == null)
return null;
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.IF)) {
if (conditionalBranch(null, elseBranch) == null)
return null;
} else {
return null;
}
}
} finally {
helper.end(ConditionalBranchDescrBuilder.class,
conditionalBranch);
}
return conditionalBranch.getDescr();
}
/**
* namedConsequence := DO LEFT_SQUARE ID RIGHT_SQUARE BREAK?
*/
private BaseDescr namedConsequence(CEDescrBuilder, ?> ce, NamedConsequenceDescrBuilder> namedConsequence) throws RecognitionException {
if (namedConsequence == null) {
namedConsequence = helper.start((DescrBuilder, ?>) ce,
NamedConsequenceDescrBuilder.class,
null);
}
try {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.DO,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
match(input,
DRL6Lexer.LEFT_SQUARE,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
Token label = match(input,
DRL6Lexer.ID,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
namedConsequence.name(label.getText());
match(input,
DRL6Lexer.RIGHT_SQUARE,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
} finally {
helper.end(NamedConsequenceDescrBuilder.class,
namedConsequence);
}
return namedConsequence.getDescr();
}
/**
* breakingNamedConsequence := BREAK LEFT_SQUARE ID RIGHT_SQUARE
*/
private BaseDescr breakingNamedConsequence(CEDescrBuilder, ?> ce, NamedConsequenceDescrBuilder> namedConsequence) throws RecognitionException {
if (namedConsequence == null) {
namedConsequence = helper.start((DescrBuilder, ?>) ce,
NamedConsequenceDescrBuilder.class,
null);
}
try {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.BREAK,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
match(input,
DRL6Lexer.LEFT_SQUARE,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
Token label = match(input,
DRL6Lexer.ID,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
namedConsequence.name(label.getText());
namedConsequence.breaking(true);
match(input,
DRL6Lexer.RIGHT_SQUARE,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
} finally {
helper.end(NamedConsequenceDescrBuilder.class,
namedConsequence);
}
return namedConsequence.getDescr();
}
/**
* lhsExists := EXISTS
* ( (LEFT_PAREN (or_key|and_key))=> lhsOr // prevents '((' for prefixed and/or
* | LEFT_PAREN lhsOr RIGHT_PAREN
* | lhsPatternBind
* )
*
* @param ce
* @return
* @throws org.antlr.runtime.RecognitionException
*/
protected BaseDescr lhsExists(CEDescrBuilder, ?> ce,
boolean allowOr) throws RecognitionException {
CEDescrBuilder, ExistsDescr> exists = null;
if (state.backtracking == 0) {
exists = ce.exists();
helper.start(exists,
CEDescrBuilder.class,
null);
}
try {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.EXISTS,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
if (state.backtracking == 0) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION_EXISTS);
}
if (input.LA(1) == DRL6Lexer.LEFT_PAREN) {
boolean prefixed = helper.validateLT(2,
DroolsSoftKeywords.AND) || helper.validateLT(2,
DroolsSoftKeywords.OR);
if (!prefixed) {
match(input,
DRL6Lexer.LEFT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
}
lhsOr(exists,
allowOr);
if (state.failed)
return null;
if (!prefixed) {
match(input,
DRL6Lexer.RIGHT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
}
} else {
lhsPatternBind(exists,
true);
if (state.failed)
return null;
}
} finally {
if (state.backtracking == 0) {
helper.end(CEDescrBuilder.class,
exists);
}
}
return exists != null ? exists.getDescr() : null;
}
/**
* lhsNot := NOT
* ( (LEFT_PAREN (or_key|and_key))=> lhsOr // prevents '((' for prefixed and/or
* | LEFT_PAREN lhsOr RIGHT_PAREN
* | lhsPatternBind
* )
*
* @param ce
* @return
* @throws org.antlr.runtime.RecognitionException
*/
protected BaseDescr lhsNot(CEDescrBuilder, ?> ce,
boolean allowOr) throws RecognitionException {
CEDescrBuilder, NotDescr> not = null;
if (state.backtracking == 0) {
not = ce.not();
helper.start(not,
CEDescrBuilder.class,
null);
}
try {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.NOT,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
if (state.backtracking == 0) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION_NOT);
}
if (input.LA(1) == DRL6Lexer.LEFT_PAREN) {
boolean prefixed = helper.validateLT(2,
DroolsSoftKeywords.AND) || helper.validateLT(2,
DroolsSoftKeywords.OR);
if (!prefixed) {
match(input,
DRL6Lexer.LEFT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
}
if (state.backtracking == 0 && input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION);
}
lhsOr(not,
allowOr);
if (state.failed)
return null;
if (!prefixed) {
match(input,
DRL6Lexer.RIGHT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
}
} else if (input.LA(1) != DRL6Lexer.EOF) {
lhsPatternBind(not,
true);
if (state.failed)
return null;
}
} finally {
if (state.backtracking == 0) {
helper.end(CEDescrBuilder.class,
not);
}
}
return not != null ? not.getDescr() : null;
}
/**
* lhsForall := FORALL LEFT_PAREN lhsPatternBind+ RIGHT_PAREN
*
* @param ce
* @return
* @throws org.antlr.runtime.RecognitionException
*/
protected BaseDescr lhsForall(CEDescrBuilder, ?> ce) throws RecognitionException {
ForallDescrBuilder> forall = helper.start(ce,
ForallDescrBuilder.class,
null);
try {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.FORALL,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
match(input,
DRL6Lexer.LEFT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
do {
lhsPatternBind(forall,
false);
if (state.failed)
return null;
if (input.LA(1) == DRL6Lexer.COMMA) {
match(input,
DRL6Lexer.COMMA,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
}
} while (input.LA(1) != DRL6Lexer.EOF && input.LA(1) != DRL6Lexer.RIGHT_PAREN);
match(input,
DRL6Lexer.RIGHT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
} finally {
helper.end(ForallDescrBuilder.class,
forall);
}
return forall != null ? forall.getDescr() : null;
}
/**
* lhsEval := EVAL LEFT_PAREN conditionalExpression RIGHT_PAREN
*
* @param ce
* @return
* @throws org.antlr.runtime.RecognitionException
*/
private BaseDescr lhsEval(CEDescrBuilder, ?> ce) throws RecognitionException {
EvalDescrBuilder> eval = null;
try {
eval = helper.start(ce,
EvalDescrBuilder.class,
null);
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.EVAL,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
if (!parseEvalExpression(eval))
return null;
} catch (RecognitionException e) {
throw e;
} finally {
helper.end(EvalDescrBuilder.class,
eval);
}
return eval != null ? eval.getDescr() : null;
}
private boolean parseEvalExpression(EvalDescrBuilder> eval) throws RecognitionException {
match(input,
DRL6Lexer.LEFT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return false;
if (state.backtracking == 0) {
helper.emit(Location.LOCATION_LHS_INSIDE_EVAL);
}
int idx = input.index();
final String expr;
try {
expr = conditionalExpression();
} catch (RecognitionException e) {
final Token tempToken = helper.getLastTokenOnList(helper.getEditorInterface().getLast().getContent());
if (tempToken != null) {
for (int i = tempToken.getTokenIndex() + 1; i < input.size(); i++) {
final Token token = input.get(i);
if (token.getType() == DRL6Lexer.EOF) {
break;
}
helper.emit(token, DroolsEditorType.CODE_CHUNK);
}
}
throw e;
}
if (state.backtracking == 0) {
eval.constraint(expr);
}
match(input,
DRL6Lexer.RIGHT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return false;
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION);
return true;
}
/**
* lhsParen := LEFT_PAREN lhsOr RIGHT_PAREN
*
* @param ce
* @return
* @throws org.antlr.runtime.RecognitionException
*/
private BaseDescr lhsParen(CEDescrBuilder, ?> ce,
boolean allowOr) throws RecognitionException {
match(input,
DRL6Lexer.LEFT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
if (state.backtracking == 0 && input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION);
}
BaseDescr descr = lhsOr(ce,
allowOr);
if (state.failed)
return null;
match(input,
DRL6Lexer.RIGHT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
return descr;
}
/**
* lhsPatternBind := label?
* ( LEFT_PAREN lhsPattern (OR lhsPattern)* RIGHT_PAREN
* | lhsPattern )
*
* @param ce
* @return
* @throws org.antlr.runtime.RecognitionException
*/
@SuppressWarnings("unchecked")
private BaseDescr lhsPatternBind(PatternContainerDescrBuilder, ?> ce,
final boolean allowOr) throws RecognitionException {
PatternDescrBuilder> pattern = null;
CEDescrBuilder, OrDescr> or = null;
BaseDescr result = null;
Token first = input.LT(1);
pattern = helper.start((DescrBuilder, ?>) ce,
PatternDescrBuilder.class,
null);
if (pattern != null) {
result = pattern.getDescr();
}
String label = null;
boolean isUnification = false;
if (input.LA(1) == DRL6Lexer.ID && input.LA(2) == DRL6Lexer.COLON && !helper.validateCEKeyword(1)) {
label = label(DroolsEditorType.IDENTIFIER_PATTERN);
if (state.failed)
return null;
} else if (input.LA(1) == DRL6Lexer.ID && input.LA(2) == DRL6Lexer.UNIFY && !helper.validateCEKeyword(1)) {
label = unif(DroolsEditorType.IDENTIFIER_PATTERN);
if (state.failed)
return null;
isUnification = true;
}
if (input.LA(1) == DRL6Lexer.LEFT_PAREN) {
try {
match(input,
DRL6Lexer.LEFT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
if (helper.validateCEKeyword(1)) {
failMismatchedTokenException();
return null; // in case it is backtracking
}
lhsPattern(pattern,
label,
isUnification);
if (state.failed)
return null;
if (allowOr && helper.validateIdentifierKey(DroolsSoftKeywords.OR) && ce instanceof CEDescrBuilder) {
if (state.backtracking == 0) {
// this is necessary because of the crappy bind with multi-pattern OR syntax
or = ((CEDescrBuilder, OrDescr>) ce).or();
result = or.getDescr();
helper.end(PatternDescrBuilder.class,
pattern);
helper.start(or,
CEDescrBuilder.class,
null);
// adjust real or starting token:
helper.setStart(or,
first);
// remove original pattern from the parent CE child list:
((ConditionalElementDescr) ce.getDescr()).getDescrs().remove(pattern.getDescr());
// add pattern to the OR instead
or.getDescr().addDescr(pattern.getDescr());
}
while (helper.validateIdentifierKey(DroolsSoftKeywords.OR)) {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.OR,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return null;
pattern = helper.start(or,
PatternDescrBuilder.class,
null);
// new pattern, same binding
lhsPattern(pattern,
label,
isUnification);
if (state.failed)
return null;
helper.end(PatternDescrBuilder.class,
pattern);
}
}
match(input,
DRL6Lexer.RIGHT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
} finally {
if (or != null) {
helper.end(CEDescrBuilder.class,
or);
} else {
helper.end(PatternDescrBuilder.class,
pattern);
}
}
} else {
try {
lhsPattern(pattern,
label,
isUnification);
if (state.failed)
return null;
} finally {
helper.end(PatternDescrBuilder.class,
pattern);
}
}
return result;
}
/**
* lhsAccumulate := (ACCUMULATE|ACC) LEFT_PAREN lhsAnd (COMMA|SEMICOLON)
* accumulateFunctionBinding (COMMA accumulateFunctionBinding)*
* (SEMICOLON constraints)?
* RIGHT_PAREN SEMICOLON?
*
* @param ce
* @return
* @throws org.antlr.runtime.RecognitionException
*/
private BaseDescr lhsAccumulate(PatternContainerDescrBuilder, ?> ce) throws RecognitionException {
PatternDescrBuilder> pattern = null;
BaseDescr result = null;
pattern = helper.start((DescrBuilder, ?>) ce,
PatternDescrBuilder.class,
null);
if (pattern != null) {
result = pattern.getDescr();
}
try {
if (state.backtracking == 0) {
pattern.type("Object[]");
pattern.isQuery(false);
// might have to add the implicit bindings as well
}
AccumulateDescrBuilder> accumulate = helper.start(pattern,
AccumulateDescrBuilder.class,
null);
try {
if (helper.validateIdentifierKey(DroolsSoftKeywords.ACCUMULATE)) {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.ACCUMULATE,
null,
DroolsEditorType.KEYWORD);
} else {
// might be using the short mnemonic
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.ACC,
null,
DroolsEditorType.KEYWORD);
}
if (state.failed)
return null;
if (state.backtracking == 0 && input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_FROM_ACCUMULATE);
}
match(input,
DRL6Lexer.LEFT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
CEDescrBuilder, AndDescr> source = accumulate.source();
try {
helper.start(source,
CEDescrBuilder.class,
null);
lhsAnd(source,
false);
if (state.failed)
return null;
if (source.getDescr() != null && source.getDescr() instanceof ConditionalElementDescr) {
ConditionalElementDescr root = (ConditionalElementDescr) source.getDescr();
BaseDescr[] descrs = root.getDescrs().toArray(new BaseDescr[root.getDescrs().size()]);
root.getDescrs().clear();
for (int i = 0; i < descrs.length; i++) {
root.addOrMerge(descrs[i]);
}
}
} finally {
helper.end(CEDescrBuilder.class,
source);
}
if (input.LA(1) == DRL6Lexer.COMMA) {
match(input,
DRL6Lexer.COMMA,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
} else if (input.LA(-1) != DRL6Lexer.SEMICOLON) {
// lhsUnary will consume an optional SEMICOLON, so we need to check if it was consumed already
// or if we must fail consuming it now
match(input,
DRL6Lexer.SEMICOLON,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
}
// accumulate functions
accumulateFunctionBinding(accumulate);
if (state.failed)
return null;
while (input.LA(1) == DRL6Lexer.COMMA) {
match(input,
DRL6Lexer.COMMA,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
accumulateFunctionBinding(accumulate);
if (state.failed)
return null;
}
if (input.LA(1) == DRL6Lexer.SEMICOLON) {
match(input,
DRL6Lexer.SEMICOLON,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
constraints(pattern);
}
match(input,
DRL6Lexer.RIGHT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
} finally {
helper.end(AccumulateDescrBuilder.class,
accumulate);
if (state.backtracking == 0 && input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION);
}
}
} finally {
helper.end(PatternDescrBuilder.class,
pattern);
}
if (input.LA(1) == DRL6Lexer.SEMICOLON) {
match(input,
DRL6Lexer.SEMICOLON,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
}
return result;
}
private void failMismatchedTokenException() throws DroolsMismatchedTokenException {
if (state.backtracking > 0) {
state.failed = true;
} else {
DroolsMismatchedTokenException mte = new DroolsMismatchedTokenException(input.LA(1),
input.LT(1).getText(),
input);
input.consume();
throw mte;
}
}
void failMissingTokenException() throws MissingTokenException {
if (state.backtracking > 0) {
state.failed = true;
} else {
throw new MissingTokenException(DRL6Lexer.STRING,
input,
null);
}
}
void failUnexpectedAnnotationException(String annotationName) throws DroolsUnexpectedAnnotationException {
if (state.backtracking > 0) {
state.failed = true;
} else {
throw new DroolsUnexpectedAnnotationException(input, annotationName);
}
}
/**
* lhsPattern := xpathPrimary |
* ( QUESTION? qualifiedIdentifier
* LEFT_PAREN positionalConstraints? constraints? RIGHT_PAREN
* (OVER patternFilter)? (FROM patternSource)? )
*
* @param pattern
* @param label
* @param isUnification
* @throws org.antlr.runtime.RecognitionException
*/
void lhsPattern(PatternDescrBuilder> pattern,
String label,
boolean isUnification) throws RecognitionException {
if (label != null && input.LA(1) == DRL6Lexer.DIV) {
int first = input.index();
exprParser.xpathPrimary();
if (state.failed) return;
int last = input.LT(-1).getTokenIndex();
String expr = toExpression("", first, last);
pattern.id( label, isUnification ).constraint( expr );
return;
}
boolean query = false;
if (input.LA(1) == DRL6Lexer.QUESTION) {
match(input,
DRL6Lexer.QUESTION,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
query = true;
}
String type = this.qualifiedIdentifier();
if (state.failed)
return;
if (state.backtracking == 0) {
pattern.type(type);
pattern.isQuery(query);
if (label != null) {
pattern.id(label,
isUnification);
}
}
match(input,
DRL6Lexer.LEFT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
if (input.LA(1) != DRL6Lexer.RIGHT_PAREN && speculatePositionalConstraints()) {
positionalConstraints(pattern);
}
if (input.LA(1) != DRL6Lexer.RIGHT_PAREN) {
constraints(pattern);
}
match(input,
DRL6Lexer.RIGHT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
if (helper.validateIdentifierKey(DroolsSoftKeywords.OVER)) {
// || input.LA( 1 ) == DRL6Lexer.PIPE ) {
patternFilter(pattern);
}
if (helper.validateIdentifierKey(DroolsSoftKeywords.FROM)) {
patternSource(pattern);
}
if (state.backtracking == 0) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION);
}
}
/**
* label := ID COLON
* @return
* @throws org.antlr.runtime.RecognitionException
*/
String label( DroolsEditorType edType ) throws RecognitionException {
Token label = match(input,
DRL6Lexer.ID,
null,
null,
edType);
if (state.failed)
return null;
match(input,
DRL6Lexer.COLON,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
return label.getText();
}
/**
* unif := ID UNIFY
* @return
* @throws org.antlr.runtime.RecognitionException
*/
private String unif(DroolsEditorType edType) throws RecognitionException {
Token label = match(input,
DRL6Lexer.ID,
null,
null,
edType);
if (state.failed)
return null;
match(input,
DRL6Lexer.UNIFY,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
return label.getText();
}
private boolean speculatePositionalConstraints() {
state.backtracking++;
int start = input.mark();
try {
positionalConstraints(null); // can never throw exception
} catch (RecognitionException re) {
System.err.println("impossible: " + re);
re.printStackTrace();
}
boolean success = !state.failed;
input.rewind(start);
state.backtracking--;
state.failed = false;
return success;
}
/**
* positionalConstraints := constraint (COMMA constraint)* SEMICOLON
* @param pattern
* @throws org.antlr.runtime.RecognitionException
*/
private void positionalConstraints(PatternDescrBuilder> pattern) throws RecognitionException {
constraint(pattern,
true,
"");
if (state.failed)
return;
while (input.LA(1) == DRL6Lexer.COMMA) {
match(input,
DRL6Lexer.COMMA,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
constraint(pattern,
true,
"");
if (state.failed)
return;
}
match(input,
DRL6Lexer.SEMICOLON,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
}
/**
* constraints := constraint (COMMA constraint)*
* @param pattern
* @throws org.antlr.runtime.RecognitionException
*/
private void constraints(PatternDescrBuilder> pattern) throws RecognitionException {
constraints(pattern, "");
}
private void constraints(PatternDescrBuilder> pattern, String prefix) throws RecognitionException {
constraint(pattern,
false,
prefix);
if (state.failed)
return;
while (input.LA(1) == DRL6Lexer.COMMA) {
match(input,
DRL6Lexer.COMMA,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
constraint(pattern,
false,
prefix);
if (state.failed)
return;
}
}
/**
* constraint := nestedConstraint | conditionalOrExpression
* @param pattern
* @throws org.antlr.runtime.RecognitionException
*/
private void constraint(PatternDescrBuilder> pattern,
boolean positional,
String prefix) throws RecognitionException {
if (speculateNestedConstraint()) {
nestedConstraint(pattern, prefix);
return;
}
if (state.backtracking == 0) {
helper.emit(Location.LOCATION_LHS_INSIDE_CONDITION_START);
}
int first = input.index();
exprParser.getHelper().setHasOperator(false); // resetting
try {
exprParser.conditionalOrExpression();
} finally {
if (state.backtracking == 0) {
if (input.LA(1) == DRL6Lexer.ID && input.LA(2) == DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_INSIDE_CONDITION_ARGUMENT);
} else if (input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_INSIDE_CONDITION_END);
} else if (!lastTokenWasWhiteSpace()) {
int location = getCurrentLocation();
if (location == Location.LOCATION_LHS_INSIDE_CONDITION_END) {
helper.emit(Location.LOCATION_LHS_INSIDE_CONDITION_ARGUMENT);
} else if (input.get(input.index()).getType() != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_INSIDE_CONDITION_START);
}
} else if (getCurrentLocation() == Location.LOCATION_LHS_INSIDE_CONDITION_START &&
!exprParser.getHelper().getHasOperator() &&
lastTokenWasWhiteSpace() &&
input.LA(1) == DRL6Lexer.EOF &&
input.LA(-1) == DRL6Lexer.ID) {
helper.emit(Location.LOCATION_LHS_INSIDE_CONDITION_OPERATOR);
}
}
}
if (state.failed)
return;
if (state.backtracking == 0 && input.index() > first) {
// expression consumed something
int last = input.LT(-1).getTokenIndex();
String expr = toExpression(prefix, first, last);
pattern.constraint(expr,
positional);
BaseDescr constrDescr = pattern.getDescr().getDescrs().get(pattern.getDescr().getDescrs().size() - 1);
constrDescr.setLocation(input.get(first).getLine(),
input.get(first).getCharPositionInLine());
constrDescr.setEndLocation(input.get(last).getLine(),
input.get(last).getCharPositionInLine());
constrDescr.setStartCharacter(((CommonToken) input.get(first)).getStartIndex());
constrDescr.setEndCharacter(((CommonToken) input.get(last)).getStopIndex());
}
}
private String toExpression(String prefix, int first, int last) {
String expr = input.toString(first, last);
if (prefix.length() == 0) {
return expr;
}
StringBuilder sb = new StringBuilder();
toOrExpression(sb, prefix, expr);
return sb.toString();
}
private void toOrExpression(StringBuilder sb, String prefix, String expr) {
int start = 0;
int end = expr.indexOf("||");
do {
if (start > 0) {
sb.append(" || ");
}
toAndExpression(sb, prefix, end > 0 ? expr.substring(start, end) : expr.substring(start));
start = end + 2;
end = expr.indexOf("||", start);
} while (start > 1);
}
private void toAndExpression(StringBuilder sb, String prefix, String expr) {
int start = 0;
int end = expr.indexOf("&&");
do {
if (start > 0) {
sb.append(" && ");
}
sb.append(toExpression(prefix, end > 0 ? expr.substring(start, end) : expr.substring(start)));
start = end + 2;
end = expr.indexOf("&&", start);
} while (start > 1);
}
private String toExpression(String prefix, String expr) {
expr = expr.trim();
int colonPos = expr.indexOf(":");
return colonPos < 0 ? prefix + expr : expr.substring(0, colonPos + 1) + " " + prefix + expr.substring(colonPos + 1).trim();
}
private boolean speculateNestedConstraint() throws RecognitionException {
return getNestedConstraintPrefixLenght() > 0;
}
/**
* nestedConstraint := ( ID ( DOT | HASH ) )* ID DOT LEFT_PAREN constraints RIGHT_PAREN
* @param pattern
* @throws org.antlr.runtime.RecognitionException
*/
private void nestedConstraint(PatternDescrBuilder> pattern, String prefix) throws RecognitionException {
int prefixLenght = getNestedConstraintPrefixLenght();
int prefixStart = input.index();
prefix += input.toString(prefixStart, prefixStart + prefixLenght - 2);
for (int i = 0; i < prefixLenght; i++) {
input.consume();
}
constraints(pattern, prefix);
match(input,
DRL6Lexer.RIGHT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
}
private int getNestedConstraintPrefixLenght() {
int cursor = 0;
int lastToken = input.LA(++cursor);
while (true) {
int nextToken = input.LA(++cursor);
switch (lastToken) {
case DRL6Lexer.ID:
if (nextToken != DRL6Lexer.DOT && nextToken != DRL6Lexer.NULL_SAFE_DOT && nextToken != DRL6Lexer.HASH) {
return -1;
}
break;
case DRL6Lexer.DOT:
case DRL6Lexer.NULL_SAFE_DOT:
if (nextToken == DRL6Lexer.LEFT_PAREN) {
return cursor;
}
case DRL6Lexer.HASH:
if (nextToken != DRL6Lexer.ID) {
return -1;
}
break;
default:
return -1;
}
lastToken = nextToken;
}
}
private boolean lastTokenWasWhiteSpace() {
int index = input.index();
while (index >= 0) {
int type = input.get(index).getType();
switch (type) {
case DRL6Lexer.EOF:
index--;
break;
case DRL6Lexer.WS:
return true;
default:
return false;
}
}
return false;
}
private int getCurrentLocation() {
LinkedList ei = helper.getEditorInterface();
LinkedList> content = ei.getLast().getContent();
// the following call is efficient as it points to the tail of the list
ListIterator> listIterator = content.listIterator(content.size());
while (listIterator.hasPrevious()) {
Object previous = listIterator.previous();
if (previous instanceof Integer) {
return ((Integer) previous).intValue();
}
}
return Location.LOCATION_UNKNOWN;
}
/**
* patternFilter := OVER filterDef
* DISALLOWED: | ( PIPE filterDef )+
*
* @param pattern
* @throws org.antlr.runtime.RecognitionException
*/
private void patternFilter(PatternDescrBuilder> pattern) throws RecognitionException {
// if ( input.LA( 1 ) == DRL6Lexer.PIPE ) {
// while ( input.LA( 1 ) == DRL6Lexer.PIPE ) {
// match( input,
// DRL6Lexer.PIPE,
// null,
// null,
// DroolsEditorType.SYMBOL );
// if ( state.failed ) return;
//
// filterDef( pattern );
// if ( state.failed ) return;
// }
// } else {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.OVER,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return;
filterDef(pattern);
if (state.failed)
return;
// }
}
/**
* filterDef := label ID LEFT_PAREN parameters RIGHT_PAREN
* @param pattern
* @throws org.antlr.runtime.RecognitionException
*/
private void filterDef(PatternDescrBuilder> pattern) throws RecognitionException {
BehaviorDescrBuilder> behavior = helper.start(pattern,
BehaviorDescrBuilder.class,
null);
try {
String bName = label(DroolsEditorType.IDENTIFIER_PATTERN);
if (state.failed)
return;
Token subtype = match(input,
DRL6Lexer.ID,
null,
null,
DroolsEditorType.IDENTIFIER_PATTERN);
if (state.failed)
return;
if (state.backtracking == 0) {
behavior.type(bName,
subtype.getText());
}
List parameters = parameters();
if (state.failed)
return;
if (state.backtracking == 0) {
behavior.parameters(parameters);
}
} finally {
helper.end(BehaviorDescrBuilder.class,
behavior);
}
}
/**
* patternSource := FROM
* ( fromAccumulate
* | fromCollect
* | fromEntryPoint
* | fromWindow
* | fromExpression )
* @param pattern
* @throws org.antlr.runtime.RecognitionException
*/
private void patternSource(PatternDescrBuilder> pattern) throws RecognitionException {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.FROM,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return;
if (state.backtracking == 0) {
helper.emit(Location.LOCATION_LHS_FROM);
}
if (helper.validateIdentifierKey(DroolsSoftKeywords.ACCUMULATE) || helper.validateIdentifierKey(DroolsSoftKeywords.ACC)) {
fromAccumulate(pattern);
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.COLLECT)) {
fromCollect(pattern);
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.ENTRY) &&
helper.validateLT(2,
"-") &&
helper.validateLT(3,
DroolsSoftKeywords.POINT)) {
fromEntryPoint(pattern);
if (state.failed)
return;
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.WINDOW)) {
fromWindow(pattern);
} else {
fromExpression(pattern);
if (!lastTokenWasWhiteSpace() && input.LA(1) == DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_FROM);
throw new RecognitionException();
}
if (state.failed)
return;
}
if (input.LA(1) == DRL6Lexer.SEMICOLON) {
match(input,
DRL6Lexer.SEMICOLON,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
}
}
/**
* fromExpression := conditionalOrExpression
*
* @param pattern
* @throws org.antlr.runtime.RecognitionException
*/
private void fromExpression(PatternDescrBuilder> pattern) throws RecognitionException {
String expr = conditionalOrExpression();
if (state.failed)
return;
if (state.backtracking == 0) {
pattern.from().expression(expr);
if (input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION);
}
}
}
/**
* fromEntryPoint := ENTRY-POINT stringId
*
* @param pattern
* @throws org.antlr.runtime.RecognitionException
*/
private void fromEntryPoint(PatternDescrBuilder> pattern) throws RecognitionException {
String ep = "";
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.ENTRY,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return;
match(input,
DRL6Lexer.MINUS,
null,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return;
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.POINT,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return;
ep = stringId();
if (state.backtracking == 0) {
pattern.from().entryPoint(ep);
if (input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION);
}
}
}
/**
* fromWindow := WINDOW ID
*
* @param pattern
* @throws org.antlr.runtime.RecognitionException
*/
private void fromWindow(PatternDescrBuilder> pattern) throws RecognitionException {
String window = "";
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.WINDOW,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return;
Token id = match(input,
DRL6Lexer.ID,
null,
null,
DroolsEditorType.IDENTIFIER);
if (state.failed)
return;
window = id.getText();
if (state.backtracking == 0) {
pattern.from().window(window);
if (input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION);
}
}
}
/**
* fromCollect := COLLECT LEFT_PAREN lhsPatternBind RIGHT_PAREN
*
* @param pattern
* @throws org.antlr.runtime.RecognitionException
*/
private void fromCollect(PatternDescrBuilder> pattern) throws RecognitionException {
CollectDescrBuilder> collect = helper.start(pattern,
CollectDescrBuilder.class,
null);
try {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.COLLECT,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return;
if (state.backtracking == 0 && input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_FROM_COLLECT);
}
match(input,
DRL6Lexer.LEFT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
lhsPatternBind(collect,
false);
if (state.failed)
return;
match(input,
DRL6Lexer.RIGHT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
} finally {
helper.end(CollectDescrBuilder.class,
collect);
if (state.backtracking == 0 && input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION);
}
}
}
/**
* fromAccumulate := ACCUMULATE LEFT_PAREN lhsAnd (COMMA|SEMICOLON)
* ( INIT chunk_(_) COMMA ACTION chunk_(_) COMMA
* ( REVERSE chunk_(_) COMMA)? RESULT chunk_(_)
* | accumulateFunction
* ) RIGHT_PAREN
*
* @param pattern
* @throws org.antlr.runtime.RecognitionException
*/
private void fromAccumulate(PatternDescrBuilder> pattern) throws RecognitionException {
AccumulateDescrBuilder> accumulate = helper.start(pattern,
AccumulateDescrBuilder.class,
null);
try {
if (helper.validateIdentifierKey(DroolsSoftKeywords.ACCUMULATE)) {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.ACCUMULATE,
null,
DroolsEditorType.KEYWORD);
} else {
// might be using the short mnemonic
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.ACC,
null,
DroolsEditorType.KEYWORD);
}
if (state.failed)
return;
if (state.backtracking == 0 && input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_FROM_ACCUMULATE);
}
match(input,
DRL6Lexer.LEFT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
CEDescrBuilder, AndDescr> source = accumulate.source();
try {
helper.start(source,
CEDescrBuilder.class,
null);
lhsAnd(source,
false);
if (state.failed)
return;
if (source.getDescr() != null && source.getDescr() instanceof ConditionalElementDescr) {
ConditionalElementDescr root = (ConditionalElementDescr) source.getDescr();
BaseDescr[] descrs = root.getDescrs().toArray(new BaseDescr[root.getDescrs().size()]);
root.getDescrs().clear();
for (int i = 0; i < descrs.length; i++) {
root.addOrMerge(descrs[i]);
}
}
} finally {
helper.end(CEDescrBuilder.class,
source);
}
if (input.LA(1) == DRL6Lexer.COMMA) {
match(input,
DRL6Lexer.COMMA,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
} else if (input.LA(-1) != DRL6Lexer.SEMICOLON) {
match(input,
DRL6Lexer.SEMICOLON,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
}
if (helper.validateIdentifierKey(DroolsSoftKeywords.INIT)) {
// custom code, inline accumulate
// initBlock
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.INIT,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return;
if (state.backtracking == 0 && input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_FROM_ACCUMULATE_INIT);
}
String init = chunk(DRL6Lexer.LEFT_PAREN,
DRL6Lexer.RIGHT_PAREN,
Location.LOCATION_LHS_FROM_ACCUMULATE_INIT_INSIDE);
if (state.failed)
return;
if (state.backtracking == 0)
accumulate.init(init);
if (input.LA(1) == DRL6Lexer.COMMA) {
match(input,
DRL6Lexer.COMMA,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
}
// actionBlock
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.ACTION,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return;
if (state.backtracking == 0 && input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_FROM_ACCUMULATE_ACTION);
}
String action = chunk(DRL6Lexer.LEFT_PAREN,
DRL6Lexer.RIGHT_PAREN,
Location.LOCATION_LHS_FROM_ACCUMULATE_ACTION_INSIDE);
if (state.failed)
return;
if (state.backtracking == 0)
accumulate.action(action);
if (input.LA(1) == DRL6Lexer.COMMA) {
match(input,
DRL6Lexer.COMMA,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
}
// reverseBlock
if (helper.validateIdentifierKey(DroolsSoftKeywords.REVERSE)) {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.REVERSE,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return;
if (state.backtracking == 0 && input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_FROM_ACCUMULATE_REVERSE);
}
String reverse = chunk(DRL6Lexer.LEFT_PAREN,
DRL6Lexer.RIGHT_PAREN,
Location.LOCATION_LHS_FROM_ACCUMULATE_REVERSE_INSIDE);
if (state.failed)
return;
if (state.backtracking == 0)
accumulate.reverse(reverse);
if (input.LA(1) == DRL6Lexer.COMMA) {
match(input,
DRL6Lexer.COMMA,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
}
}
// resultBlock
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.RESULT,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return;
if (state.backtracking == 0 && input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_FROM_ACCUMULATE_RESULT);
}
String result = chunk(DRL6Lexer.LEFT_PAREN,
DRL6Lexer.RIGHT_PAREN,
Location.LOCATION_LHS_FROM_ACCUMULATE_RESULT_INSIDE);
if (state.failed)
return;
if (state.backtracking == 0)
accumulate.result(result);
} else {
// accumulate functions
accumulateFunction(accumulate,
false,
null);
if (state.failed)
return;
}
match(input,
DRL6Lexer.RIGHT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
} finally {
helper.end(AccumulateDescrBuilder.class,
accumulate);
if (state.backtracking == 0 && input.LA(1) != DRL6Lexer.EOF) {
helper.emit(Location.LOCATION_LHS_BEGIN_OF_CONDITION);
}
}
}
/**
* accumulateFunctionBinding := label accumulateFunction
* @param accumulate
* @throws org.antlr.runtime.RecognitionException
*/
private void accumulateFunctionBinding(AccumulateDescrBuilder> accumulate) throws RecognitionException {
String label = null;
boolean unif = false;
if (input.LA(2) == DRL6Lexer.COLON) {
label = label(DroolsEditorType.IDENTIFIER_VARIABLE);
} else if (input.LA(2) == DRL6Lexer.UNIFY) {
label = unif(DroolsEditorType.IDENTIFIER_VARIABLE);
unif = true;
}
accumulateFunction( accumulate,
unif,
label );
}
/**
* accumulateFunction := label? ID parameters
* @param accumulate
* @throws org.antlr.runtime.RecognitionException
*/
private void accumulateFunction(AccumulateDescrBuilder> accumulate,
boolean unif,
String label) throws RecognitionException {
Token function = match(input,
DRL6Lexer.ID,
null,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return;
List parameters = parameters();
if (state.failed)
return;
if (state.backtracking == 0) {
accumulate.function(function.getText(),
label,
unif,
parameters != null ? parameters.toArray(new String[]{}) : new String[]{});
}
}
/**
* parameters := LEFT_PAREN (conditionalExpression (COMMA conditionalExpression)* )? RIGHT_PAREN
*
* @return
* @throws org.antlr.runtime.RecognitionException
*/
private List parameters() throws RecognitionException {
match(input,
DRL6Lexer.LEFT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
List parameters = new ArrayList();
if (input.LA(1) != DRL6Lexer.EOF && input.LA(1) != DRL6Lexer.RIGHT_PAREN) {
String param = conditionalExpression();
if (state.failed)
return null;
parameters.add(param);
while (input.LA(1) == DRL6Lexer.COMMA) {
match(input,
DRL6Lexer.COMMA,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
param = conditionalExpression();
if (state.failed)
return null;
parameters.add(param);
}
}
match(input,
DRL6Lexer.RIGHT_PAREN,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return null;
return parameters;
}
/**
* rhs := defaultConsequence namedConsequence* (~END)*
* @param rule
*/
void rhs( RuleDescrBuilder rule ) {
defaultConsequence(rule);
while (input.LA(1) != DRL6Lexer.EOF && helper.validateIdentifierKey(DroolsSoftKeywords.THEN)) {
namedConsequence(rule);
}
}
/**
* defaultConsequence := THEN chunk
* @param rule
*/
public void defaultConsequence(RuleDescrBuilder rule) {
try {
int first = input.index();
Token t = match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.THEN,
null,
DroolsEditorType.KEYWORD);
if (state.failed)
return;
if (state.backtracking == 0) {
rule.getDescr().setConsequenceLocation(t.getLine(),
t.getCharPositionInLine());
helper.emit(Location.LOCATION_RHS);
}
String chunk = getConsequenceCode(first);
// remove the "then" keyword and any subsequent spaces and line breaks
// keep indentation of 1st non-blank line
chunk = chunk.replaceFirst("^then\\s*\\r?\\n?",
"");
rule.rhs(chunk);
} catch (RecognitionException re) {
reportError(re);
}
}
/**
* namedConsequence := THEN LEFT_SQUARE ID RIGHT_SQUARE chunk
* @param rule
*/
public void namedConsequence(RuleDescrBuilder rule) {
try {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.THEN,
null,
DroolsEditorType.KEYWORD);
match(input,
DRL6Lexer.LEFT_SQUARE,
null,
null,
DroolsEditorType.SYMBOL);
Token label = match(input,
DRL6Lexer.ID,
null,
null,
DroolsEditorType.SYMBOL);
int first = input.index();
match(input,
DRL6Lexer.RIGHT_SQUARE,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
String name = label.getText();
String chunk = getConsequenceCode(first);
// remove the closing squqre bracket "]" and any subsequent spaces and line breaks
// keep indentation of 1st non-blank line
chunk = chunk.replaceFirst("^\\]\\s*\\r?\\n?",
"");
rule.namedRhs(name, chunk);
} catch (RecognitionException re) {
reportError(re);
}
}
protected String getConsequenceCode( int first ) {
while (input.LA(1) != DRL6Lexer.EOF) {
if (helper.validateIdentifierKey(DroolsSoftKeywords.END)) {
int next = input.LA(2) == DRL6Lexer.SEMICOLON ? 3 : 2;
if (input.LA(next) == DRL6Lexer.EOF || input.LA(next) == DRL6Lexer.AT || helper.validateStatement(next)) {
break;
}
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.THEN)) {
if (isNextTokenThenCompatible( input.LA( 2 ) ) ) {
break;
}
}
helper.emit( input.LT( 1 ), DroolsEditorType.CODE_CHUNK );
input.consume();
}
int last = input.LT(1).getTokenIndex();
if (last <= first) {
return "";
}
String chunk = input.toString(first,
last);
if (chunk.endsWith(DroolsSoftKeywords.END)) {
chunk = chunk.substring(0,
chunk.length() - DroolsSoftKeywords.END.length());
} else if (chunk.endsWith(DroolsSoftKeywords.THEN)) {
chunk = chunk.substring(0,
chunk.length() - DroolsSoftKeywords.THEN.length());
}
return chunk;
}
private boolean isNextTokenThenCompatible(int next) {
return next != DRL6Lexer.LEFT_PAREN &&
next != DRL6Lexer.RIGHT_PAREN &&
next != DRL6Lexer.RIGHT_SQUARE &&
next != DRL6Lexer.COMMA &&
next != DRL6Lexer.SEMICOLON;
}
/* ------------------------------------------------------------------------------------------------
* ANNOTATION
* ------------------------------------------------------------------------------------------------ */
/**
* annotation := fullAnnotation | AT ID chunk_(_)?
*/
void annotation( AnnotatedDescrBuilder> adb ) {
AnnotationDescrBuilder> annotation = null;
try {
if (speculateFullAnnotation()) {
boolean buildState = exprParser.isBuildDescr();
exprParser.setBuildDescr(true);
exprParser.fullAnnotation(adb);
exprParser.setBuildDescr(buildState);
} else {
// '@'
Token at = match(input,
DRL6Lexer.AT,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return;
// identifier
String fqn = qualifiedIdentifier();
if (state.failed)
return;
if (state.backtracking == 0) {
annotation = adb.newAnnotation(fqn);
helper.setStart(annotation,
at);
}
try {
if (input.LA(1) == DRL6Lexer.LEFT_PAREN) {
String value = chunk(DRL6Lexer.LEFT_PAREN,
DRL6Lexer.RIGHT_PAREN,
-1).trim();
if (state.failed)
return;
if (state.backtracking == 0) {
if (annotation != null) {
annotation.value(value);
} else {
throw new RecognitionException();
}
}
}
} finally {
if (state.backtracking == 0) {
helper.setEnd(annotation);
}
}
}
} catch (RecognitionException re) {
reportError(re);
}
}
/**
* Invokes the expression parser, trying to parse the annotation
* as a full java-style annotation
*
* @return true if the sequence of tokens will match the
* elementValuePairs() syntax. false otherwise.
*/
private boolean speculateFullAnnotation() {
state.backtracking++;
int start = input.mark();
try {
exprParser.fullAnnotation(null);
} catch (RecognitionException re) {
System.err.println("impossible: " + re);
re.printStackTrace();
}
boolean success = !state.failed;
input.rewind(start);
state.backtracking--;
state.failed = false;
return success;
}
/* ------------------------------------------------------------------------------------------------
* UTILITY RULES
* ------------------------------------------------------------------------------------------------ */
/**
* Matches a type name
*
* type := ID typeArguments? ( DOT ID typeArguments? )* (LEFT_SQUARE RIGHT_SQUARE)*
*
* @return
* @throws org.antlr.runtime.RecognitionException
*/
public String type() throws RecognitionException {
String type = "";
try {
int first = input.index(), last = first;
match(input,
DRL6Lexer.ID,
null,
new int[]{DRL6Lexer.DOT, DRL6Lexer.LESS},
DroolsEditorType.IDENTIFIER);
if (state.failed)
return type;
if (input.LA(1) == DRL6Lexer.LESS) {
typeArguments();
if (state.failed)
return type;
}
while (input.LA(1) == DRL6Lexer.DOT && input.LA(2) == DRL6Lexer.ID) {
match(input,
DRL6Lexer.DOT,
null,
new int[]{DRL6Lexer.ID},
DroolsEditorType.IDENTIFIER);
if (state.failed)
return type;
match(input,
DRL6Lexer.ID,
null,
new int[]{DRL6Lexer.DOT},
DroolsEditorType.IDENTIFIER);
if (state.failed)
return type;
if (input.LA(1) == DRL6Lexer.LESS) {
typeArguments();
if (state.failed)
return type;
}
}
while (input.LA(1) == DRL6Lexer.LEFT_SQUARE && input.LA(2) == DRL6Lexer.RIGHT_SQUARE) {
match(input,
DRL6Lexer.LEFT_SQUARE,
null,
new int[]{DRL6Lexer.RIGHT_SQUARE},
DroolsEditorType.IDENTIFIER);
if (state.failed)
return type;
match(input,
DRL6Lexer.RIGHT_SQUARE,
null,
null,
DroolsEditorType.IDENTIFIER);
if (state.failed)
return type;
}
last = input.LT(-1).getTokenIndex();
type = input.toString(first,
last);
type = type.replace(" ",
"");
} catch (RecognitionException re) {
reportError(re);
}
return type;
}
/**
* Matches type arguments
*
* typeArguments := LESS typeArgument (COMMA typeArgument)* GREATER
*
* @return
* @throws org.antlr.runtime.RecognitionException
*/
public String typeArguments() throws RecognitionException {
String typeArguments = "";
try {
int first = input.index();
Token token = match(input,
DRL6Lexer.LESS,
null,
new int[]{DRL6Lexer.QUESTION, DRL6Lexer.ID},
DroolsEditorType.SYMBOL);
if (state.failed)
return typeArguments;
typeArgument();
if (state.failed)
return typeArguments;
while (input.LA(1) == DRL6Lexer.COMMA) {
token = match(input,
DRL6Lexer.COMMA,
null,
new int[]{DRL6Lexer.QUESTION, DRL6Lexer.ID},
DroolsEditorType.IDENTIFIER);
if (state.failed)
return typeArguments;
typeArgument();
if (state.failed)
return typeArguments;
}
token = match(input,
DRL6Lexer.GREATER,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return typeArguments;
typeArguments = input.toString(first,
token.getTokenIndex());
} catch (RecognitionException re) {
reportError(re);
}
return typeArguments;
}
/**
* Matches a type argument
*
* typeArguments := QUESTION (( EXTENDS | SUPER ) type )?
* | type
* ;
*
* @return
* @throws org.antlr.runtime.RecognitionException
*/
public String typeArgument() throws RecognitionException {
String typeArgument = "";
try {
int first = input.index(), last = first;
int next = input.LA(1);
switch (next) {
case DRL6Lexer.QUESTION:
match(input,
DRL6Lexer.QUESTION,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return typeArgument;
if (helper.validateIdentifierKey(DroolsSoftKeywords.EXTENDS)) {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.EXTENDS,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return typeArgument;
type();
if (state.failed)
return typeArgument;
} else if (helper.validateIdentifierKey(DroolsSoftKeywords.SUPER)) {
match(input,
DRL6Lexer.ID,
DroolsSoftKeywords.SUPER,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return typeArgument;
type();
if (state.failed)
return typeArgument;
}
break;
case DRL6Lexer.ID:
type();
if (state.failed)
return typeArgument;
break;
default:
// TODO: raise error
}
last = input.LT(-1).getTokenIndex();
typeArgument = input.toString(first,
last);
} catch (RecognitionException re) {
reportError(re);
}
return typeArgument;
}
/**
* Matches a qualified identifier
*
* qualifiedIdentifier := ID ( DOT ID )*
*
* @return
* @throws org.antlr.runtime.RecognitionException
*/
public String qualifiedIdentifier() throws RecognitionException {
String qi = "";
try {
Token first = match(input,
DRL6Lexer.ID,
null,
new int[]{DRL6Lexer.DOT},
DroolsEditorType.IDENTIFIER);
if (state.failed)
return qi;
Token last = first;
while (input.LA(1) == DRL6Lexer.DOT && input.LA(2) == DRL6Lexer.ID) {
last = match(input,
DRL6Lexer.DOT,
null,
new int[]{DRL6Lexer.ID},
DroolsEditorType.IDENTIFIER);
if (state.failed)
return qi;
last = match(input,
DRL6Lexer.ID,
null,
new int[]{DRL6Lexer.DOT},
DroolsEditorType.IDENTIFIER);
if (state.failed)
return qi;
}
qi = input.toString(first,
last);
qi = qi.replace(" ",
"");
} catch (RecognitionException re) {
reportError(re);
}
return qi;
}
/**
* Matches a conditional expression
*
* @return
* @throws org.antlr.runtime.RecognitionException
*/
public String conditionalExpression() throws RecognitionException {
int first = input.index();
exprParser.conditionalExpression();
if (state.failed)
return null;
if (state.backtracking == 0 && input.index() > first) {
// expression consumed something
String expr = input.toString(first,
input.LT(-1).getTokenIndex());
return expr;
}
return null;
}
/**
* Matches a conditional || expression
*
* @return
* @throws org.antlr.runtime.RecognitionException
*/
public String conditionalOrExpression() throws RecognitionException {
int first = input.index();
exprParser.conditionalOrExpression();
if (state.failed)
return null;
if (state.backtracking == 0 && input.index() > first) {
// expression consumed something
String expr = input.toString(first,
input.LT(-1).getTokenIndex());
return expr;
}
return null;
}
/**
* Matches a chunk started by the leftDelimiter and ended by the rightDelimiter.
*
* @param leftDelimiter
* @param rightDelimiter
* @param location
* @return the matched chunk without the delimiters
*/
public String chunk(final int leftDelimiter,
final int rightDelimiter,
final int location) {
String chunk = "";
int first = -1, last = first;
try {
match(input,
leftDelimiter,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return chunk;
if (state.backtracking == 0 && location >= 0) {
helper.emit(location);
}
int nests = 0;
first = input.index();
while (input.LA(1) != DRL6Lexer.EOF && (input.LA(1) != rightDelimiter || nests > 0)) {
if (input.LA(1) == rightDelimiter) {
nests--;
} else if (input.LA(1) == leftDelimiter) {
nests++;
}
input.consume();
}
last = input.LT(-1).getTokenIndex();
for (int i = first; i < last + 1; i++) {
helper.emit(input.get(i), DroolsEditorType.CODE_CHUNK);
}
match(input,
rightDelimiter,
null,
null,
DroolsEditorType.SYMBOL);
if (state.failed)
return chunk;
} catch (RecognitionException re) {
reportError(re);
} finally {
if (last >= first) {
chunk = input.toString(first,
last);
}
}
return chunk;
}
/* ------------------------------------------------------------------------------------------------
* GENERAL UTILITY METHODS
* ------------------------------------------------------------------------------------------------ */
/**
* Match current input symbol against ttype and optionally
* check the text of the token against text. Attempt
* single token insertion or deletion error recovery. If
* that fails, throw MismatchedTokenException.
*/
Token match( TokenStream input,
int ttype,
String text,
int[] follow,
DroolsEditorType etype ) throws RecognitionException {
Token matchedSymbol = null;
matchedSymbol = input.LT(1);
if (input.LA(1) == ttype && (text == null || text.equals(matchedSymbol.getText()))) {
input.consume();
state.errorRecovery = false;
state.failed = false;
helper.emit(matchedSymbol,
etype);
return matchedSymbol;
}
if (state.backtracking > 0) {
state.failed = true;
return matchedSymbol;
}
matchedSymbol = recoverFromMismatchedToken(input,
ttype,
text,
follow);
helper.emit(matchedSymbol,
etype);
return matchedSymbol;
}
/** Attempt to recover from a single missing or extra token.
*
* EXTRA TOKEN
*
* LA(1) is not what we are looking for. If LA(2) has the right token,
* however, then assume LA(1) is some extra spurious token. Delete it
* and LA(2) as if we were doing a normal match(), which advances the
* input.
*
* MISSING TOKEN
*
* If current token is consistent with what could come after
* ttype then it is ok to "insert" the missing token, else throw
* exception For example, Input "i=(3;" is clearly missing the
* ')'. When the parser returns from the nested call to expr, it
* will have call chain:
*
* stat -> expr -> atom
*
* and it will be trying to match the ')' at this point in the
* derivation:
*
* => ID '=' '(' INT ')' ('+' atom)* ';'
* ^
* match() will see that ';' doesn't match ')' and report a
* mismatched token error. To recover, it sees that LA(1)==';'
* is in the set of tokens that can follow the ')' token
* reference in rule atom. It can assume that you forgot the ')'.
*/
protected Token recoverFromMismatchedToken(TokenStream input,
int ttype,
String text,
int[] follow)
throws RecognitionException {
RecognitionException e = null;
// if next token is what we are looking for then "delete" this token
if (mismatchIsUnwantedToken(input,
ttype,
text)) {
e = new UnwantedTokenException(ttype,
input);
input.consume(); // simply delete extra token
reportError(e); // report after consuming so AW sees the token in the exception
// we want to return the token we're actually matching
Token matchedSymbol = input.LT(1);
input.consume(); // move past ttype token as if all were ok
return matchedSymbol;
}
// can't recover with single token deletion, try insertion
if (mismatchIsMissingToken(input,
follow)) {
e = new MissingTokenException(ttype,
input,
null);
reportError(e); // report after inserting so AW sees the token in the exception
return null;
}
// even that didn't work; must throw the exception
if (text != null) {
e = new DroolsMismatchedTokenException(ttype,
text,
input);
} else {
e = new MismatchedTokenException(ttype,
input);
}
throw e;
}
public boolean mismatchIsUnwantedToken(TokenStream input,
int ttype,
String text) {
return (input.LA(2) == ttype && (text == null || text.equals(input.LT(2).getText())));
}
public boolean mismatchIsMissingToken(TokenStream input,
int[] follow) {
if (follow == null) {
// we have no information about the follow; we can only consume
// a single token and hope for the best
return false;
}
// TODO: implement this error recovery strategy
return false;
}
private String safeStripDelimiters(String value,
String left,
String right) {
if (value != null) {
value = value.trim();
if (value.length() >= left.length() + right.length() &&
value.startsWith(left) && value.endsWith(right)) {
value = value.substring(left.length(),
value.length() - right.length());
}
}
return value;
}
private String safeStripStringDelimiters(String value) {
if (value != null) {
value = value.trim();
if (value.length() >= 2 && value.startsWith("\"") && value.endsWith("\"")) {
value = value.substring(1,
value.length() - 1);
}
}
return value;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy