[jboss-svn-commits] JBL Code SVN: r5456 - in labs/jbossrules/trunk/drools-compiler/src: main/java/org/drools/compiler main/java/org/drools/lang/descr main/java/org/drools/semantics/java main/resources/META-INF main/resources/org/drools/lang test/java/org/drools/compiler
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Thu Aug 3 20:22:49 EDT 2006
Author: mark.proctor at jboss.com
Date: 2006-08-03 20:22:41 -0400 (Thu, 03 Aug 2006)
New Revision: 5456
Added:
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/FactTemplateError.java
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/FieldTemplateError.java
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/descr/FactTemplateDescr.java
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/descr/FieldTemplateDescr.java
labs/jbossrules/trunk/drools-compiler/src/main/resources/org/drools/lang/drl.g
Modified:
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/PackageBuilder.java
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/descr/PackageDescr.java
labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/RuleBuilder.java
labs/jbossrules/trunk/drools-compiler/src/main/resources/META-INF/drools-3.0.xsd
labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/compiler/PackageBuilderTest.java
Log:
JBRULES-328 FactTemplates
-Rule/Package Builder now works FactTemplates
Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/FactTemplateError.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/FactTemplateError.java 2006-08-04 00:03:47 UTC (rev 5455)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/FactTemplateError.java 2006-08-04 00:22:41 UTC (rev 5456)
@@ -0,0 +1,77 @@
+package org.drools.compiler;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * 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.
+ */
+
+import org.apache.commons.jci.problems.CompilationProblem;
+import org.drools.lang.descr.PatternDescr;
+import org.drools.rule.Rule;
+import org.drools.rule.Package;
+
+public class FactTemplateError extends DroolsError {
+ private Package pkg;
+ private PatternDescr descr;
+ private Object object;
+ private String message;
+
+ public FactTemplateError(final Package pkg,
+ final PatternDescr descr,
+ final Object object,
+ final String message) {
+ super();
+ this.pkg = pkg;
+ this.descr = descr;
+ this.object = object;
+ this.message = message;
+ }
+
+ public Package getPackage() {
+ return this.pkg;
+ }
+
+ public PatternDescr getDescr() {
+ return this.descr;
+ }
+
+ public Object getObject() {
+ return this.object;
+ }
+
+ /**
+ * This will return the line number of the error, if possible
+ * Otherwise it will be -1
+ */
+ public int getLine() {
+ if ( this.descr != null ) {
+ return this.descr.getLine();
+ } else {
+ return -1;
+ }
+ }
+
+ public String getMessage() {
+ String summary = this.message;
+ if ( this.object instanceof CompilationProblem[] ) {
+ final CompilationProblem[] problem = (CompilationProblem[]) this.object;
+ for ( int i = 0; i < problem.length; i++ ) {
+ summary = summary + " " + problem[i].getMessage();
+ }
+
+ }
+ return summary;
+ }
+
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/FieldTemplateError.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/FieldTemplateError.java 2006-08-04 00:03:47 UTC (rev 5455)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/FieldTemplateError.java 2006-08-04 00:22:41 UTC (rev 5456)
@@ -0,0 +1,76 @@
+package org.drools.compiler;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * 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.
+ */
+
+import org.apache.commons.jci.problems.CompilationProblem;
+import org.drools.lang.descr.PatternDescr;
+import org.drools.rule.Rule;
+import org.drools.rule.Package;
+
+public class FieldTemplateError extends DroolsError {
+ private Package pkg;
+ private PatternDescr descr;
+ private Object object;
+ private String message;
+
+ public FieldTemplateError(final Package pkg,
+ final PatternDescr descr,
+ final Object object,
+ final String message) {
+ this.pkg = pkg;
+ this.descr = descr;
+ this.object = object;
+ this.message = message;
+ }
+
+ public Package getPackage() {
+ return this.pkg;
+ }
+
+ public PatternDescr getDescr() {
+ return this.descr;
+ }
+
+ public Object getObject() {
+ return this.object;
+ }
+
+ /**
+ * This will return the line number of the error, if possible
+ * Otherwise it will be -1
+ */
+ public int getLine() {
+ if ( this.descr != null ) {
+ return this.descr.getLine();
+ } else {
+ return -1;
+ }
+ }
+
+ public String getMessage() {
+ String summary = this.message;
+ if ( this.object instanceof CompilationProblem[] ) {
+ final CompilationProblem[] problem = (CompilationProblem[]) this.object;
+ for ( int i = 0; i < problem.length; i++ ) {
+ summary = summary + " " + problem[i].getMessage();
+ }
+
+ }
+ return summary;
+ }
+
+}
\ No newline at end of file
Modified: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/PackageBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/PackageBuilder.java 2006-08-04 00:03:47 UTC (rev 5455)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/compiler/PackageBuilder.java 2006-08-04 00:22:41 UTC (rev 5456)
@@ -37,6 +37,12 @@
import org.apache.commons.jci.readers.ResourceReader;
import org.drools.RuntimeDroolsException;
import org.drools.base.ClassFieldExtractorCache;
+import org.drools.facttemplates.FactTemplate;
+import org.drools.facttemplates.FactTemplateImpl;
+import org.drools.facttemplates.FieldTemplate;
+import org.drools.facttemplates.FieldTemplateImpl;
+import org.drools.lang.descr.FactTemplateDescr;
+import org.drools.lang.descr.FieldTemplateDescr;
import org.drools.lang.descr.FunctionDescr;
import org.drools.lang.descr.PackageDescr;
import org.drools.lang.descr.PatternDescr;
@@ -185,6 +191,10 @@
//only try to compile if there are no parse errors
if ( !hasErrors() ) {
+ for ( final Iterator it = packageDescr.getFactTemplates().iterator(); it.hasNext(); ) {
+ addFactTemplate( (FactTemplateDescr) it.next() );
+ }
+
//iterate and compile
for ( final Iterator it = packageDescr.getFunctions().iterator(); it.hasNext(); ) {
addFunction( (FunctionDescr) it.next() );
@@ -293,6 +303,30 @@
}
+ private void addFactTemplate(final FactTemplateDescr factTemplateDescr) {
+ List fields = new ArrayList();
+ int index = 0;
+ for ( final Iterator it = factTemplateDescr.getFields().iterator(); it.hasNext(); ) {
+ FieldTemplateDescr fieldTemplateDescr = (FieldTemplateDescr) it.next();
+ FieldTemplate fieldTemplate = null;
+ try {
+ fieldTemplate = new FieldTemplateImpl( fieldTemplateDescr.getName(),
+ index++,
+ getTypeResolver().resolveType( fieldTemplateDescr.getClassType() ) );
+ } catch ( ClassNotFoundException e ) {
+ this.results.add( new FieldTemplateError( this.pkg,
+ fieldTemplateDescr,
+ null,
+ "Unable to resolve Class '" + fieldTemplateDescr.getClassType() + "'" ) );
+ }
+ fields.add( fieldTemplate );
+ }
+
+ FactTemplate factTemplate = new FactTemplateImpl( this.pkg,
+ factTemplateDescr.getName(),
+ (FieldTemplate[]) fields.toArray( new FieldTemplate[fields.size()] ) );
+ }
+
private void addRule(final RuleDescr ruleDescr) {
final String ruleClassName = getUniqueLegalName( this.pkg.getName(),
@@ -421,11 +455,11 @@
if ( result.getErrors().length > 0 ) {
for ( int i = 0; i < result.getErrors().length; i++ ) {
CompilationProblem err = result.getErrors()[i];
-
+
ErrorHandler handler = (ErrorHandler) this.errorHandlers.get( err.getFileName() );
- if (handler instanceof RuleErrorHandler) {
+ if ( handler instanceof RuleErrorHandler ) {
RuleErrorHandler rh = (RuleErrorHandler) handler;
-
+
}
handler.addError( err );
}
@@ -433,14 +467,14 @@
Collection errors = this.errorHandlers.values();
for ( Iterator iter = errors.iterator(); iter.hasNext(); ) {
ErrorHandler handler = (ErrorHandler) iter.next();
- if (handler.isInError()) {
+ if ( handler.isInError() ) {
if ( !(handler instanceof RuleInvokerErrorHandler) ) {
this.results.add( handler.getError() );
} else {
//we don't really want to report invoker errors.
//mostly as they can happen when there is a syntax error in the RHS
//and otherwise, it is a programmatic error in drools itself.
- System.err.println( "Warning: An error occurred compiling a semantic invoker. Errors should have been reported elsewhere.");
+ System.err.println( "Warning: An error occurred compiling a semantic invoker. Errors should have been reported elsewhere." );
}
}
}
@@ -554,15 +588,15 @@
* that originally spawned the code to be compiled.
*/
public abstract static class ErrorHandler {
- private List errors = new ArrayList();
+ private List errors = new ArrayList();
protected String message;
- private boolean inError = false;
+ private boolean inError = false;
/** This needes to be checked if there is infact an error */
public boolean isInError() {
return inError;
}
-
+
public void addError(CompilationProblem err) {
this.errors.add( err );
this.inError = true;
Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/descr/FactTemplateDescr.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/descr/FactTemplateDescr.java 2006-08-04 00:03:47 UTC (rev 5455)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/descr/FactTemplateDescr.java 2006-08-04 00:22:41 UTC (rev 5456)
@@ -0,0 +1,29 @@
+package org.drools.lang.descr;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FactTemplateDescr extends PatternDescr {
+ private static final long serialVersionUID = 320;
+
+ String name;
+ List fields = new ArrayList( 1 );
+
+ public FactTemplateDescr(String name) {
+ this.name = name;
+ }
+
+ public void addFieldTemplate(FieldTemplateDescr fieldTemplate) {
+ this.fields.add( fieldTemplate );
+ }
+
+ public List getFields() {
+ return this.fields;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+
+}
Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/descr/FieldTemplateDescr.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/descr/FieldTemplateDescr.java 2006-08-04 00:03:47 UTC (rev 5455)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/descr/FieldTemplateDescr.java 2006-08-04 00:22:41 UTC (rev 5456)
@@ -0,0 +1,20 @@
+package org.drools.lang.descr;
+
+public class FieldTemplateDescr extends PatternDescr {
+ private final String name;
+ private final String classType;
+ public FieldTemplateDescr(final String name,
+ final String type) {
+ super();
+ this.name = name;
+ this.classType = type;
+ }
+ public String getName() {
+ return this.name;
+ }
+ public String getClassType() {
+ return this.classType;
+ }
+
+
+}
Modified: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/descr/PackageDescr.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/descr/PackageDescr.java 2006-08-04 00:03:47 UTC (rev 5455)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/lang/descr/PackageDescr.java 2006-08-04 00:22:41 UTC (rev 5456)
@@ -27,14 +27,15 @@
*
*/
private static final long serialVersionUID = 4491974850482281807L;
- private final String name;
- private final String documentation;
+ private final String name;
+ private final String documentation;
- private List imports = Collections.EMPTY_LIST;
- private List attributes = Collections.EMPTY_LIST;
- private Map globals = Collections.EMPTY_MAP;
- private List functions = Collections.EMPTY_LIST;
- private List rules = Collections.EMPTY_LIST;
+ private List imports = Collections.EMPTY_LIST;
+ private List attributes = Collections.EMPTY_LIST;
+ private Map globals = Collections.EMPTY_MAP;
+ private List factTemplates = Collections.EMPTY_LIST;
+ private List functions = Collections.EMPTY_LIST;
+ private List rules = Collections.EMPTY_LIST;
public PackageDescr(final String name) {
this( name,
@@ -77,7 +78,7 @@
public Map getGlobals() {
return this.globals;
- }
+ }
public void addAttribute(final AttributeDescr attribute) {
if ( this.attributes == Collections.EMPTY_LIST ) {
@@ -89,6 +90,17 @@
public List getAttributes() {
return this.attributes;
}
+
+ public void addFactTemplate(final FactTemplateDescr factTemplate) {
+ if ( this.factTemplates == Collections.EMPTY_LIST ) {
+ this.factTemplates = new ArrayList( 1 );
+ }
+ this.factTemplates.add( factTemplate );
+ }
+
+ public List getFactTemplates() {
+ return this.factTemplates;
+ }
public void addFunction(final FunctionDescr function) {
if ( this.functions == Collections.EMPTY_LIST ) {
Modified: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/RuleBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/RuleBuilder.java 2006-08-04 00:03:47 UTC (rev 5455)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/RuleBuilder.java 2006-08-04 00:22:41 UTC (rev 5456)
@@ -37,6 +37,9 @@
import org.drools.base.ValueType;
import org.drools.base.evaluators.Operator;
import org.drools.compiler.RuleError;
+import org.drools.facttemplates.FactTemplate;
+import org.drools.facttemplates.FactTemplateFieldExtractor;
+import org.drools.facttemplates.FactTemplateObjectType;
import org.drools.lang.descr.AndDescr;
import org.drools.lang.descr.AttributeDescr;
import org.drools.lang.descr.ColumnDescr;
@@ -81,6 +84,7 @@
import org.drools.spi.Extractor;
import org.drools.spi.FieldExtractor;
import org.drools.spi.FieldValue;
+import org.drools.spi.ObjectType;
import org.drools.spi.Restriction;
import org.drools.spi.TypeResolver;
@@ -382,24 +386,30 @@
return null;
}
- Class clazz = null;
-
- try {
- //clazz = Class.forName( columnDescr.getObjectType() );
- clazz = this.typeResolver.resolveType( columnDescr.getObjectType() );
- } catch ( final ClassNotFoundException e ) {
- this.errors.add( new RuleError( this.rule,
- columnDescr,
- null,
- "Unable to resolve ObjectType '" + columnDescr.getObjectType() + "'" ) );
- return null;
+ ObjectType objectType = null;
+
+ FactTemplate factTemplate = this.pkg.getFactTemplate( columnDescr.getObjectType() );
+
+ if ( factTemplate != null ){
+ objectType = new FactTemplateObjectType( factTemplate );
+ } else {
+ try {
+ //clazz = Class.forName( columnDescr.getObjectType() );
+ objectType = new ClassObjectType( this.typeResolver.resolveType( columnDescr.getObjectType() )) ;
+ } catch ( final ClassNotFoundException e ) {
+ this.errors.add( new RuleError( this.rule,
+ columnDescr,
+ null,
+ "Unable to resolve ObjectType '" + columnDescr.getObjectType() + "'" ) );
+ return null;
+ }
}
Column column;
if ( columnDescr.getIdentifier() != null && !columnDescr.getIdentifier().equals( "" ) ) {
column = new Column( this.columnCounter.getNext(),
this.columnOffset,
- new ClassObjectType( clazz ),
+ objectType,
columnDescr.getIdentifier() );;
this.declarations.put( column.getDeclaration().getIdentifier(),
column.getDeclaration() );
@@ -411,7 +421,7 @@
} else {
column = new Column( this.columnCounter.getNext(),
this.columnOffset,
- new ClassObjectType( clazz ),
+ objectType,
null );
}
@@ -434,10 +444,8 @@
private void build(final Column column,
final FieldConstraintDescr fieldConstraintDescr) {
- final Class clazz = ((ClassObjectType) column.getObjectType()).getClassType();
-
final FieldExtractor extractor = getFieldExtractor( fieldConstraintDescr,
- clazz,
+ column.getObjectType(),
fieldConstraintDescr.getFieldName() );
if ( extractor == null ) {
// @todo log error
@@ -603,10 +611,8 @@
return;
}
- final Class clazz = ((ClassObjectType) column.getObjectType()).getClassType();
-
final FieldExtractor extractor = getFieldExtractor( fieldBindingDescr,
- clazz,
+ column.getObjectType(),
fieldBindingDescr.getFieldName() );
if ( extractor == null ) {
return;
@@ -780,10 +786,8 @@
final String classMethodName = "predicate" + this.counter++;
predicateDescr.setClassMethodName( classMethodName );
- final Class clazz = ((ClassObjectType) column.getObjectType()).getClassType();
-
final FieldExtractor extractor = getFieldExtractor( predicateDescr,
- clazz,
+ column.getObjectType(),
predicateDescr.getFieldName() );
if ( extractor == null ) {
return;
@@ -1062,17 +1066,24 @@
}
private FieldExtractor getFieldExtractor(final PatternDescr descr,
- final Class clazz,
+ final ObjectType objectType,
final String fieldName) {
FieldExtractor extractor = null;
- try {
- extractor = classFieldExtractorCache.getExtractor( clazz,
- fieldName );
- } catch ( final RuntimeDroolsException e ) {
- this.errors.add( new RuleError( this.rule,
- descr,
- e,
- "Unable to create Field Extractor for '" + fieldName + "'" ) );
+
+ if ( objectType.getValueType() == ValueType.FACTTEMPLATE_TYPE ) {
+ //@todo use extractor cache
+ FactTemplate factTemplate = ( ( FactTemplateObjectType ) objectType ).getFactTemplate();
+ extractor = new FactTemplateFieldExtractor( factTemplate, factTemplate.getFieldTemplateIndex( fieldName ));
+ } else {
+ try {
+ extractor = classFieldExtractorCache.getExtractor( ( ( ClassObjectType ) objectType ).getClassType(),
+ fieldName );
+ } catch ( final RuntimeDroolsException e ) {
+ this.errors.add( new RuleError( this.rule,
+ descr,
+ e,
+ "Unable to create Field Extractor for '" + fieldName + "'" ) );
+ }
}
return extractor;
Modified: labs/jbossrules/trunk/drools-compiler/src/main/resources/META-INF/drools-3.0.xsd
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/resources/META-INF/drools-3.0.xsd 2006-08-04 00:03:47 UTC (rev 5455)
+++ labs/jbossrules/trunk/drools-compiler/src/main/resources/META-INF/drools-3.0.xsd 2006-08-04 00:22:41 UTC (rev 5456)
@@ -180,6 +180,7 @@
<xs:element name="field-constraint">
<xs:complexType>
<xs:choice maxOccurs="unbounded" minOccurs="0">
+ <xs:element ref="drools:connective-restriction"/>
<xs:element ref="drools:literal-restriction"/>
<xs:element ref="drools:variable-restriction"/>
<xs:element ref="drools:return-value-restriction"/>
Added: labs/jbossrules/trunk/drools-compiler/src/main/resources/org/drools/lang/drl.g
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/resources/org/drools/lang/drl.g 2006-08-04 00:03:47 UTC (rev 5455)
+++ labs/jbossrules/trunk/drools-compiler/src/main/resources/org/drools/lang/drl.g 2006-08-04 00:22:41 UTC (rev 5456)
@@ -0,0 +1,1136 @@
+grammar RuleParser;
+
+ at parser::header {
+ package org.drools.lang;
+ import java.util.List;
+ import java.util.ArrayList;
+ import java.util.Iterator;
+ import java.util.StringTokenizer;
+ import org.drools.lang.descr.*;
+}
+
+ at parser::members {
+ private ExpanderResolver expanderResolver;
+ private Expander expander;
+ private boolean expanderDebug = false;
+ private PackageDescr packageDescr;
+ private List errors = new ArrayList();
+ private String source = "unknown";
+ private int lineOffset = 0;
+
+ private boolean parserDebug = false;
+
+ public void setParserDebug(boolean parserDebug) {
+ this.parserDebug = parserDebug;
+ }
+
+ public void debug(String message) {
+ if ( parserDebug )
+ System.err.println( "drl parser: " + message );
+ }
+
+ public void setSource(String source) {
+ this.source = source;
+ }
+
+ /**
+ * This may be set to enable debuggin of DSLs/expanders.
+ * If set to true, expander stuff will be sent to the Std out.
+ */
+ public void setExpanderDebug(boolean status) {
+ expanderDebug = status;
+ }
+ public String getSource() {
+ return this.source;
+ }
+
+ public PackageDescr getPackageDescr() {
+ return packageDescr;
+ }
+
+ private int offset(int line) {
+ return line + lineOffset;
+ }
+
+ /**
+ * This will set the offset to record when reparsing. Normally is zero of course
+ */
+ public void setLineOffset(int i) {
+ this.lineOffset = i;
+ }
+
+ public void setExpanderResolver(ExpanderResolver expanderResolver) {
+ this.expanderResolver = expanderResolver;
+ }
+
+ public ExpanderResolver getExpanderResolver() {
+ return expanderResolver;
+ }
+
+ /** Expand the LHS */
+ private String runWhenExpander(String text, int line) throws RecognitionException {
+ String expanded = text.trim();
+ if (expanded.startsWith(">")) {
+ expanded = expanded.substring(1); //escape !!
+ } else {
+ try {
+ expanded = expander.expand( "when", text );
+ } catch (Exception e) {
+ this.errors.add(new ExpanderException("Unable to expand: " + text + ". Due to " + e.getMessage(), line));
+ return "";
+ }
+ }
+ if (expanderDebug) {
+ System.out.println("Expanding LHS: " + text + " ----> " + expanded + " --> from line: " + line);
+ }
+ return expanded;
+
+ }
+
+ /** Reparse the results of the expansion */
+ private void reparseLhs(String text, AndDescr descrs) throws RecognitionException {
+ CharStream charStream = new ANTLRStringStream( text );
+ RuleParserLexer lexer = new RuleParserLexer( charStream );
+ TokenStream tokenStream = new CommonTokenStream( lexer );
+ RuleParser parser = new RuleParser( tokenStream );
+ parser.setLineOffset( descrs.getLine() );
+ parser.normal_lhs_block(descrs);
+
+ if (parser.hasErrors()) {
+ this.errors.addAll(parser.getErrors());
+ }
+ if (expanderDebug) {
+ System.out.println("Reparsing LHS: " + text + " --> successful:" + !parser.hasErrors());
+ }
+
+ }
+
+ /** Expand a line on the RHS */
+ private String runThenExpander(String text, int startLine) {
+ //System.err.println( "expand THEN [" + text + "]" );
+ StringTokenizer lines = new StringTokenizer( text, "\n\r" );
+
+ StringBuffer expanded = new StringBuffer();
+
+ String eol = System.getProperty( "line.separator" );
+
+ while ( lines.hasMoreTokens() ) {
+ startLine++;
+ String line = lines.nextToken();
+ line = line.trim();
+ if ( line.length() > 0 ) {
+ if ( line.startsWith( ">" ) ) {
+ expanded.append( line.substring( 1 ) );
+ expanded.append( eol );
+ } else {
+ try {
+ expanded.append( expander.expand( "then", line ) );
+ expanded.append( eol );
+ } catch (Exception e) {
+ this.errors.add(new ExpanderException("Unable to expand: " + line + ". Due to " + e.getMessage(), startLine));
+ }
+ }
+ }
+ }
+
+ if (expanderDebug) {
+ System.out.println("Expanding RHS: " + text + " ----> " + expanded.toString() + " --> from line starting: " + startLine);
+ }
+
+ return expanded.toString();
+ }
+
+
+
+ private String getString(Token token) {
+ String orig = token.getText();
+ return orig.substring( 1, orig.length() -1 );
+ }
+
+ public void reportError(RecognitionException ex) {
+ // if we've already reported an error and have not matched a token
+ // yet successfully, don't report any errors.
+ if ( errorRecovery ) {
+ return;
+ }
+ errorRecovery = true;
+
+ ex.line = offset(ex.line); //add the offset if there is one
+ errors.add( ex );
+ }
+
+ /** return the raw RecognitionException errors */
+ public List getErrors() {
+ return errors;
+ }
+
+ /** Return a list of pretty strings summarising the errors */
+ public List getErrorMessages() {
+ List messages = new ArrayList();
+ for ( Iterator errorIter = errors.iterator() ; errorIter.hasNext() ; ) {
+ messages.add( createErrorMessage( (RecognitionException) errorIter.next() ) );
+ }
+ return messages;
+ }
+
+ /** return true if any parser errors were accumulated */
+ public boolean hasErrors() {
+ return ! errors.isEmpty();
+ }
+
+ /** This will take a RecognitionException, and create a sensible error message out of it */
+ public String createErrorMessage(RecognitionException e)
+ {
+ StringBuffer message = new StringBuffer();
+ message.append( source + ":"+e.line+":"+e.charPositionInLine+" ");
+ if ( e instanceof MismatchedTokenException ) {
+ MismatchedTokenException mte = (MismatchedTokenException)e;
+ message.append("mismatched token: "+
+ e.token+
+ "; expecting type "+
+ tokenNames[mte.expecting]);
+ }
+ else if ( e instanceof MismatchedTreeNodeException ) {
+ MismatchedTreeNodeException mtne = (MismatchedTreeNodeException)e;
+ message.append("mismatched tree node: "+
+ mtne.foundNode+
+ "; expecting type "+
+ tokenNames[mtne.expecting]);
+ }
+ else if ( e instanceof NoViableAltException ) {
+ NoViableAltException nvae = (NoViableAltException)e;
+ message.append( "Unexpected token '" + e.token.getText() + "'" );
+ /*
+ message.append("decision=<<"+nvae.grammarDecisionDescription+">>"+
+ " state "+nvae.stateNumber+
+ " (decision="+nvae.decisionNumber+
+ ") no viable alt; token="+
+ e.token);
+ */
+ }
+ else if ( e instanceof EarlyExitException ) {
+ EarlyExitException eee = (EarlyExitException)e;
+ message.append("required (...)+ loop (decision="+
+ eee.decisionNumber+
+ ") did not match anything; token="+
+ e.token);
+ }
+ else if ( e instanceof MismatchedSetException ) {
+ MismatchedSetException mse = (MismatchedSetException)e;
+ message.append("mismatched token '"+
+ e.token+
+ "' expecting set "+mse.expecting);
+ }
+ else if ( e instanceof MismatchedNotSetException ) {
+ MismatchedNotSetException mse = (MismatchedNotSetException)e;
+ message.append("mismatched token '"+
+ e.token+
+ "' expecting set "+mse.expecting);
+ }
+ else if ( e instanceof FailedPredicateException ) {
+ FailedPredicateException fpe = (FailedPredicateException)e;
+ message.append("rule "+fpe.ruleName+" failed predicate: {"+
+ fpe.predicateText+"}?");
+ } else if (e instanceof GeneralParseException) {
+ message.append(" " + e.getMessage());
+ }
+ return message.toString();
+ }
+
+ void checkTrailingSemicolon(String text, int line) {
+ if (text.trim().endsWith( ";" ) ) {
+ this.errors.add( new GeneralParseException( "Trailing semi-colon not allowed", offset(line) ) );
+ }
+ }
+
+}
+
+ at lexer::header {
+ package org.drools.lang;
+}
+
+opt_eol :
+ (';'|EOL)*
+ ;
+
+compilation_unit
+ : opt_eol
+ prolog
+ ( r=rule {this.packageDescr.addRule( r ); }
+ | q=query {this.packageDescr.addRule( q ); }
+ | extra_statement
+ )*
+ ;
+
+prolog
+ @init {
+ String packageName = "";
+ }
+ : opt_eol
+ ( name=package_statement { packageName = name; } )?
+ {
+ this.packageDescr = new PackageDescr( name );
+ }
+ ( extra_statement
+ | expander
+ )*
+
+ opt_eol
+ ;
+
+package_statement returns [String packageName]
+ @init{
+ packageName = null;
+ }
+ :
+ 'package' opt_eol name=dotted_name ';'? opt_eol
+ {
+ packageName = name;
+ }
+ ;
+
+import_statement
+ : 'import' opt_eol name=import_name ';'? opt_eol
+ {
+ if (packageDescr != null)
+ packageDescr.addImport( name );
+ }
+ ;
+
+import_name returns [String name]
+ @init {
+ name = null;
+ }
+ :
+ id=ID { name=id.getText(); } ( '.' id=ID { name = name + "." + id.getText(); } )* (star='.*' { name = name + star.getText(); })?
+ ;
+expander
+ @init {
+ String config=null;
+ }
+ : 'expander' (name=dotted_name)? ';'? opt_eol
+ {
+ if (expanderResolver == null)
+ throw new IllegalArgumentException("Unable to use expander. Make sure a expander or dsl config is being passed to the parser. [ExpanderResolver was not set].");
+ if ( expander != null )
+ throw new IllegalArgumentException( "Only one 'expander' statement per file is allowed" );
+ expander = expanderResolver.get( name, config );
+ }
+ ;
+
+global
+ @init {
+ }
+ :
+ 'global' type=dotted_name id=ID ';'? opt_eol
+ {
+ packageDescr.addGlobal( id.getText(), type );
+ }
+ ;
+
+function
+ @init {
+ FunctionDescr f = null;
+ }
+ :
+ 'function' opt_eol (retType=dotted_name)? opt_eol name=ID opt_eol
+ {
+ //System.err.println( "function :: " + name.getText() );
+ f = new FunctionDescr( name.getText(), retType );
+ }
+ '(' opt_eol
+ ( (paramType=dotted_name)? opt_eol paramName=argument opt_eol
+ {
+ f.addParameter( paramType, paramName );
+ }
+ ( ',' opt_eol (paramType=dotted_name)? opt_eol paramName=argument opt_eol
+ {
+ f.addParameter( paramType, paramName );
+ }
+ )*
+ )?
+ ')'
+ opt_eol
+ '{'
+ body=curly_chunk
+ {
+ f.setText( body );
+ }
+ '}'
+ {
+ packageDescr.addFunction( f );
+ }
+ opt_eol
+ ;
+
+
+query returns [QueryDescr query]
+ @init {
+ query = null;
+ }
+ :
+ opt_eol
+ loc='query' queryName=word opt_eol
+ {
+ query = new QueryDescr( queryName, null );
+ query.setLocation( offset(loc.getLine()), loc.getCharPositionInLine() );
+ AndDescr lhs = new AndDescr(); query.setLhs( lhs );
+ lhs.setLocation( offset(loc.getLine()), loc.getCharPositionInLine() );
+ }
+ (
+ { expander != null }? expander_lhs_block[lhs]
+ | normal_lhs_block[lhs]
+ )
+
+ 'end' opt_eol
+ ;
+
+rule returns [RuleDescr rule]
+ @init {
+ rule = null;
+ String consequence = "";
+ }
+ :
+ opt_eol
+ loc='rule' ruleName=word opt_eol
+ {
+ debug( "start rule: " + ruleName );
+ rule = new RuleDescr( ruleName, null );
+ rule.setLocation( offset(loc.getLine()), loc.getCharPositionInLine() );
+ }
+ ( rule_attributes[rule]
+ )?
+ opt_eol
+ (( loc='when' ':'? opt_eol
+ {
+ AndDescr lhs = new AndDescr(); rule.setLhs( lhs );
+ lhs.setLocation( offset(loc.getLine()), loc.getCharPositionInLine() );
+ }
+ (
+ { expander != null }? expander_lhs_block[lhs]
+ | normal_lhs_block[lhs]
+ )
+
+ )?
+ ( opt_eol loc='then' ':'? opt_eol
+ ( options{greedy=false;} : any=.
+ {
+ consequence = consequence + " " + any.getText();
+ }
+ )*
+ {
+ if ( expander != null ) {
+ String expanded = runThenExpander( consequence, offset(loc.getLine()) );
+ rule.setConsequence( expanded );
+ } else {
+ rule.setConsequence( consequence );
+ }
+ rule.setConsequenceLocation(offset(loc.getLine()), loc.getCharPositionInLine());
+ })?
+ )?
+ 'end' opt_eol
+ {
+ debug( "end rule: " + ruleName );
+ }
+ ;
+
+extra_statement
+ :
+ ( import_statement
+ | global
+ | function
+ )
+ ;
+
+rule_attributes[RuleDescr rule]
+ :
+ 'attributes'? ':'? opt_eol
+ ( ','? a=rule_attribute opt_eol
+ {
+ rule.addAttribute( a );
+ }
+ )*
+ ;
+
+rule_attribute returns [AttributeDescr d]
+ @init {
+ d = null;
+ }
+ :
+ a=salience { d = a; }
+ | a=no_loop { d = a; }
+ | a=agenda_group { d = a; }
+ | a=duration { d = a; }
+ | a=activation_group { d = a; }
+ | a=auto_focus { d = a; }
+
+ ;
+
+salience returns [AttributeDescr d ]
+ @init {
+ d = null;
+ }
+ :
+ loc='salience' opt_eol i=INT ';'? opt_eol
+ {
+ d = new AttributeDescr( "salience", i.getText() );
+ d.setLocation( offset(loc.getLine()), loc.getCharPositionInLine() );
+ }
+ ;
+
+no_loop returns [AttributeDescr d]
+ @init {
+ d = null;
+ }
+ :
+ (
+ loc='no-loop' opt_eol ';'? opt_eol
+ {
+ d = new AttributeDescr( "no-loop", "true" );
+ d.setLocation( offset(loc.getLine()), loc.getCharPositionInLine() );
+ }
+ )
+ |
+ (
+ loc='no-loop' t=BOOL opt_eol ';'? opt_eol
+ {
+ d = new AttributeDescr( "no-loop", t.getText() );
+ d.setLocation( offset(loc.getLine()), loc.getCharPositionInLine() );
+ }
+
+ )
+
+ ;
+
+auto_focus returns [AttributeDescr d]
+ @init {
+ d = null;
+ }
+ :
+ (
+ loc='auto-focus' opt_eol ';'? opt_eol
+ {
+ d = new AttributeDescr( "auto-focus", "true" );
+ d.setLocation( offset(loc.getLine()), loc.getCharPositionInLine() );
+ }
+ )
+ |
+ (
+ loc='auto-focus' t=BOOL opt_eol ';'? opt_eol
+ {
+ d = new AttributeDescr( "auto-focus", t.getText() );
+ d.setLocation( offset(loc.getLine()), loc.getCharPositionInLine() );
+ }
+
+ )
+
+ ;
+
+activation_group returns [AttributeDescr d]
+ @init {
+ d = null;
+ }
+ :
+ loc='activation-group' opt_eol name=STRING ';'? opt_eol
+ {
+ d = new AttributeDescr( "activation-group", getString( name ) );
+ d.setLocation( offset(loc.getLine()), loc.getCharPositionInLine() );
+ }
+ ;
+
+agenda_group returns [AttributeDescr d]
+ @init {
+ d = null;
+ }
+ :
+ loc='agenda-group' opt_eol name=STRING ';'? opt_eol
+ {
+ d = new AttributeDescr( "agenda-group", getString( name ) );
+ d.setLocation( offset(loc.getLine()), loc.getCharPositionInLine() );
+ }
+ ;
+
+
+duration returns [AttributeDescr d]
+ @init {
+ d = null;
+ }
+ :
+ loc='duration' opt_eol i=INT ';'? opt_eol
+ {
+ d = new AttributeDescr( "duration", i.getText() );
+ d.setLocation( offset(loc.getLine()), loc.getCharPositionInLine() );
+ }
+ ;
+
+
+normal_lhs_block[AndDescr descrs]
+ :
+ ( d=lhs opt_eol
+ { descrs.addDescr( d ); }
+ )* opt_eol
+ ;
+
+
+
+
+expander_lhs_block[AndDescr descrs]
+ @init {
+ String lhsBlock = null;
+ String eol = System.getProperty( "line.separator" );
+ }
+ :
+ (options{greedy=false;} :
+ text=paren_chunk loc=EOL
+ {
+ //only expand non null
+ if (text != null) {
+ if (lhsBlock == null) {
+ lhsBlock = runWhenExpander( text, offset(loc.getLine()));
+ } else {
+ lhsBlock = lhsBlock + eol + runWhenExpander( text, offset(loc.getLine()));
+ }
+ text = null;
+ }
+ }
+
+ )*
+
+ {
+ if (lhsBlock != null) {
+ reparseLhs(lhsBlock, descrs);
+ }
+ }
+
+ ;
+
+
+
+lhs returns [PatternDescr d]
+ @init {
+ d=null;
+ }
+ : l=lhs_or { d = l; }
+ ;
+
+
+lhs_column returns [PatternDescr d]
+ @init {
+ d=null;
+ }
+ : f=fact_binding { d = f; }
+ | f=fact { d = f; }
+ ;
+
+fact_binding returns [PatternDescr d]
+ @init {
+ d=null;
+ boolean multi=false;
+ }
+ :
+ id=ID
+
+ opt_eol ':' opt_eol fe=fact_expression[id.getText()]
+ {
+ d=fe;
+ }
+ ;
+
+ fact_expression[String id] returns [PatternDescr pd]
+ @init {
+ pd = null;
+ boolean multi = false;
+ }
+ : '(' opt_eol fe=fact_expression[id]opt_eol ')' { pd=fe; }
+ | f=fact opt_eol
+ {
+ ((ColumnDescr)f).setIdentifier( id );
+ pd = f;
+ }
+ ( ('or'|'||') opt_eol
+ { if ( ! multi ) {
+ PatternDescr first = pd;
+ pd = new OrDescr();
+ ((OrDescr)pd).addDescr( first );
+ multi=true;
+ }
+ }
+ f=fact
+ {
+ ((ColumnDescr)f).setIdentifier( id );
+ ((OrDescr)pd).addDescr( f );
+ }
+ )*
+ ;
+
+fact returns [PatternDescr d]
+ @init {
+ d=null;
+ }
+ : id=dotted_name
+ {
+ d = new ColumnDescr( id );
+ } opt_eol
+ loc='(' {
+ d.setLocation( offset(loc.getLine()), loc.getCharPositionInLine() );
+ }opt_eol ( c=constraints
+ {
+ for ( Iterator cIter = c.iterator() ; cIter.hasNext() ; ) {
+ ((ColumnDescr)d).addDescr( (PatternDescr) cIter.next() );
+ }
+ }
+
+ )? opt_eol endLoc=')' opt_eol
+ {
+ d.setEndLocation( offset(endLoc.getLine()), endLoc.getCharPositionInLine() );
+ }
+ ;
+
+
+constraints returns [List constraints]
+ @init {
+ constraints = new ArrayList();
+ }
+ : opt_eol
+ (constraint[constraints]|predicate[constraints])
+ ( opt_eol ',' opt_eol (constraint[constraints]|predicate[constraints]))*
+ opt_eol
+ ;
+
+constraint[List constraints]
+ @init {
+ PatternDescr d = null;
+ }
+ : opt_eol
+ ( fb=ID opt_eol ':' opt_eol )?
+ f=ID
+ {
+
+ if ( fb != null ) {
+ //System.err.println( "fb: " + fb.getText() );
+ //System.err.println( " f: " + f.getText() );
+ d = new FieldBindingDescr( f.getText(), fb.getText() );
+ //System.err.println( "fbd: " + d );
+
+ d.setLocation( offset(f.getLine()), f.getCharPositionInLine() );
+ constraints.add( d );
+ }
+ FieldConstraintDescr fc = new FieldConstraintDescr(f.getText());
+ fc.setLocation( offset(f.getLine()), f.getCharPositionInLine() );
+
+
+ }
+ opt_eol ( op=operator opt_eol
+
+ ( bvc=ID
+ {
+
+
+
+ VariableRestrictionDescr vd = new VariableRestrictionDescr(op, bvc.getText());
+ fc.addRestriction(vd);
+ constraints.add(fc);
+
+ }
+ |
+ lc=enum_constraint
+ {
+
+ LiteralRestrictionDescr lrd = new LiteralRestrictionDescr(op, lc, true);
+ fc.addRestriction(lrd);
+ constraints.add(fc);
+
+ }
+ |
+ lc=literal_constraint
+ {
+
+ LiteralRestrictionDescr lrd = new LiteralRestrictionDescr(op, lc);
+ fc.addRestriction(lrd);
+ constraints.add(fc);
+
+ }
+ | rvc=retval_constraint
+ {
+
+
+
+ ReturnValueRestrictionDescr rvd = new ReturnValueRestrictionDescr(op, rvc);
+ fc.addRestriction(rvd);
+ constraints.add(fc);
+
+ }
+ )
+ (
+ con=('&'|'|')
+ {
+ if (con.getText().equals("&") ) {
+ fc.addRestriction(new RestrictionConnectiveDescr(RestrictionConnectiveDescr.AND));
+ } else {
+ fc.addRestriction(new RestrictionConnectiveDescr(RestrictionConnectiveDescr.OR));
+ }
+ }
+
+ op=operator
+ ( bvc=ID
+ {
+ VariableRestrictionDescr vd = new VariableRestrictionDescr(op, bvc.getText());
+ fc.addRestriction(vd);
+ }
+ |
+ lc=enum_constraint
+ {
+ LiteralRestrictionDescr lrd = new LiteralRestrictionDescr(op, lc, true);
+ fc.addRestriction(lrd);
+
+ }
+ |
+ lc=literal_constraint
+ {
+ LiteralRestrictionDescr lrd = new LiteralRestrictionDescr(op, lc);
+ fc.addRestriction(lrd);
+
+ }
+ | rvc=retval_constraint
+ {
+ ReturnValueRestrictionDescr rvd = new ReturnValueRestrictionDescr(op, rvc);
+ fc.addRestriction(rvd);
+
+ }
+ )
+
+ )*
+ )?
+ opt_eol
+ ;
+
+literal_constraint returns [String text]
+ @init {
+ text = null;
+ }
+ : ( t=STRING { text = getString( t ); } //t.getText(); text=text.substring( 1, text.length() - 1 ); }
+ | t=INT { text = t.getText(); }
+ | t=FLOAT { text = t.getText(); }
+ | t=BOOL { text = t.getText(); }
+ | t='null' { text = null; }
+ )
+ ;
+
+enum_constraint returns [String text]
+ @init {
+ text = null;
+ }
+ : (cls=ID '.' en=ID) { text = cls.getText() + "." + en.getText(); }
+ ;
+
+retval_constraint returns [String text]
+ @init {
+ text = null;
+ }
+ :
+ '(' c=paren_chunk ')' { text = c; }
+ ;
+
+predicate[List constraints]
+ :
+ decl=ID ':' field=ID '->' '(' text=paren_chunk ')'
+ {
+ PredicateDescr d = new PredicateDescr(field.getText(), decl.getText(), text );
+ constraints.add( d );
+ }
+ ;
+
+paren_chunk returns [String text]
+ @init {
+ text = null;
+ }
+
+ :
+ ( options{greedy=false;} :
+ '(' c=paren_chunk ')'
+ {
+ if ( c == null ) {
+ c = "";
+ }
+ if ( text == null ) {
+ text = "( " + c + " )";
+ } else {
+ text = text + " ( " + c + " )";
+ }
+ }
+ | any=.
+ {
+ if ( text == null ) {
+ text = any.getText();
+ } else {
+ text = text + " " + any.getText();
+ }
+ }
+ )*
+ ;
+
+//NOTE: this is needed as there is a bug in antlr if you sometimes use the same sub rule in multiple places
+paren_chunk2 returns [String text]
+ @init {
+ text = null;
+ }
+
+ :
+ ( options{greedy=false;} :
+ '(' c=paren_chunk2 ')'
+ {
+ if ( c == null ) {
+ c = "";
+ }
+ if ( text == null ) {
+ text = "( " + c + " )";
+ } else {
+ text = text + " ( " + c + " )";
+ }
+ }
+ | any=.
+ {
+ if ( text == null ) {
+ text = any.getText();
+ } else {
+ text = text + " " + any.getText();
+ }
+ }
+ )*
+ ;
+
+curly_chunk returns [String text]
+ @init {
+ text = null;
+ }
+
+ :
+ ( options{greedy=false;} :
+ '{' c=curly_chunk '}'
+ {
+ //System.err.println( "chunk [" + c + "]" );
+ if ( c == null ) {
+ c = "";
+ }
+ if ( text == null ) {
+ text = "{ " + c + " }";
+ } else {
+ text = text + " { " + c + " }";
+ }
+ }
+ | any=.
+ {
+ //System.err.println( "any [" + any.getText() + "]" );
+ if ( text == null ) {
+ text = any.getText();
+ } else {
+ text = text + " " + any.getText();
+ }
+ }
+ )*
+ ;
+
+lhs_or returns [PatternDescr d]
+ @init{
+ d = null;
+ }
+ :
+ { OrDescr or = null; }
+ left=lhs_and {d = left; }
+ ( ('or'|'||') opt_eol
+ right=lhs_and
+ {
+ if ( or == null ) {
+ or = new OrDescr();
+ or.addDescr( left );
+ d = or;
+ }
+
+ or.addDescr( right );
+ }
+ )*
+ ;
+
+lhs_and returns [PatternDescr d]
+ @init{
+ d = null;
+ }
+ :
+ { AndDescr and = null; }
+ left=lhs_unary { d = left; }
+ ( ('and'|'&&') opt_eol
+ right=lhs_unary
+ {
+ if ( and == null ) {
+ and = new AndDescr();
+ and.addDescr( left );
+ d = and;
+ }
+
+ and.addDescr( right );
+ }
+ )*
+ ;
+
+lhs_unary returns [PatternDescr d]
+ @init {
+ d = null;
+ }
+ : ( u=lhs_exist
+ | u=lhs_not
+ | u=lhs_eval
+ | u=lhs_column
+ | '(' opt_eol u=lhs opt_eol ')'
+ ) { d = u; }
+ ;
+
+lhs_exist returns [PatternDescr d]
+ @init {
+ d = null;
+ }
+ : loc='exists' ('(' column=lhs_column ')' | column=lhs_column)
+ {
+ d = new ExistsDescr( (ColumnDescr) column );
+ d.setLocation( offset(loc.getLine()), loc.getCharPositionInLine() );
+ }
+ ;
+
+lhs_not returns [NotDescr d]
+ @init {
+ d = null;
+ }
+ : loc='not' ('(' column=lhs_column ')' | column=lhs_column)
+ {
+ d = new NotDescr( (ColumnDescr) column );
+ d.setLocation( offset(loc.getLine()), loc.getCharPositionInLine() );
+ }
+ ;
+
+lhs_eval returns [PatternDescr d]
+ @init {
+ d = null;
+ String text = "";
+ }
+ : 'eval' loc='('
+ c=paren_chunk2
+ ')'
+ {
+ checkTrailingSemicolon( c, offset(loc.getLine()) );
+ d = new EvalDescr( c );
+ }
+ ;
+
+dotted_name returns [String name]
+ @init {
+ name = null;
+ }
+ :
+ id=ID { name=id.getText(); } ( '.' id=ID { name = name + "." + id.getText(); } )* ( '[' ']' { name = name + "[]";})*
+ ;
+
+argument returns [String name]
+ @init {
+ name = null;
+ }
+ :
+ id=ID { name=id.getText(); } ( '[' ']' { name = name + "[]";})*
+ ;
+
+
+word returns [String word]
+ @init{
+ word = null;
+ }
+ : id=ID { word=id.getText(); }
+ | 'import' { word="import"; }
+ | 'use' { word="use"; }
+ | 'rule' { word="rule"; }
+ | 'query' { word="query"; }
+ | 'salience' { word="salience"; }
+ | 'no-loop' { word="no-loop"; }
+ | 'when' { word="when"; }
+ | 'then' { word="then"; }
+ | 'end' { word="end"; }
+ | str=STRING { word=getString(str);} //str.getText(); word=word.substring( 1, word.length()-1 ); }
+ ;
+
+operator returns [String str]
+ @init {
+ str = null;
+ }
+ :
+
+ '==' {str= "==";}
+ |'=' {str="==";}
+ |'>' {str=">";}
+ |'>=' {str=">=";}
+ |'<' {str="<";}
+ |'<=' {str="<=";}
+ |'!=' {str="!=";}
+ |'contains' {str="contains";}
+ |'matches' {str="matches";}
+ |'excludes' {str="excludes";}
+
+
+ ;
+
+
+
+MISC :
+ '!' | '@' | '$' | '%' | '^' | '&' | '*' | '_' | '-' | '+' | '?'
+ | '|' | ',' | '{' | '}' | '[' | ']' | '=' | '/' | '(' | ')' | '\'' | '\\'
+ | '||' | '&&' | '<<<' | '++' | '--' | '>>>' | '==' | '+=' | '=+' | '-=' | '=-' |'*=' | '=*'
+ | '/=' | '=/' | '>>='
+
+ ;
+
+WS : ( ' '
+ | '\t'
+ | '\f'
+ )
+ { channel=99; }
+ ;
+
+EOL :
+ ( ( '\r\n' )=> '\r\n' // Evil DOS
+ | '\r' // Macintosh
+ | '\n' // Unix (the right way)
+ )
+ ;
+
+INT
+ : ('-')?('0'..'9')+
+ ;
+
+FLOAT
+ : ('-')?('0'..'9')+ '.' ('0'..'9')+
+ ;
+
+STRING
+ : ('"' ( options{greedy=false;} : .)* '"' ) | ('\'' ( options{greedy=false;} : .)* '\'')
+ ;
+
+BOOL
+ : ('true'|'false')
+ ;
+
+ID
+ : ('a'..'z'|'A'..'Z'|'_'|'$' | '\u00c0'..'\u00ff')('a'..'z'|'A'..'Z'|'_'|'0'..'9' | '\u00c0'..'\u00ff')*
+ ;
+
+
+SH_STYLE_SINGLE_LINE_COMMENT
+ : '#' ( options{greedy=false;} : .)* EOL /* ('\r')? '\n' */
+ { channel=99; }
+ ;
+
+
+C_STYLE_SINGLE_LINE_COMMENT
+ : '//' ( options{greedy=false;} : .)* EOL // ('\r')? '\n'
+ { channel=99; }
+ ;
+
+MULTI_LINE_COMMENT
+ : '/*' (options{greedy=false;} : .)* '*/'
+ { channel=99; }
+ ;
Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/compiler/PackageBuilderTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/compiler/PackageBuilderTest.java 2006-08-04 00:03:47 UTC (rev 5455)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/compiler/PackageBuilderTest.java 2006-08-04 00:22:41 UTC (rev 5456)
@@ -43,13 +43,16 @@
import org.drools.common.ActivationGroupNode;
import org.drools.common.InternalFactHandle;
import org.drools.common.LogicalDependency;
+import org.drools.facttemplates.Fact;
import org.drools.lang.descr.AndDescr;
import org.drools.lang.descr.ColumnDescr;
import org.drools.lang.descr.ConditionalElementDescr;
import org.drools.lang.descr.EvalDescr;
import org.drools.lang.descr.ExistsDescr;
+import org.drools.lang.descr.FactTemplateDescr;
import org.drools.lang.descr.FieldBindingDescr;
import org.drools.lang.descr.FieldConstraintDescr;
+import org.drools.lang.descr.FieldTemplateDescr;
import org.drools.lang.descr.LiteralRestrictionDescr;
import org.drools.lang.descr.NotDescr;
import org.drools.lang.descr.OrDescr;
@@ -280,7 +283,54 @@
} catch ( final RuntimeException e ) {
assertNotNull( e.getMessage() );
}
+ }
+
+ public void testFactTemplate() {
+ final PackageBuilder builder = new PackageBuilder();
+ final PackageDescr packageDescr = new PackageDescr( "p1" );
+ final RuleDescr ruleDescr = new RuleDescr( "rule-1" );
+ packageDescr.addRule( ruleDescr );
+
+ final AndDescr lhs = new AndDescr();
+ ruleDescr.setLhs( lhs );
+
+ FactTemplateDescr cheese = new FactTemplateDescr( "Cheese" );
+ cheese.addFieldTemplate( new FieldTemplateDescr( "name", "String" ) );
+ cheese.addFieldTemplate(new FieldTemplateDescr( "price", "Integer" ) );
+
+ packageDescr.addFactTemplate( cheese );
+
+ final ColumnDescr column = new ColumnDescr( "Cheese",
+ "stilton" );
+ lhs.addDescr( column );
+
+ FieldConstraintDescr literalDescr = new FieldConstraintDescr( "name" );
+ literalDescr.addRestriction( new LiteralRestrictionDescr("==", "stilton") );
+
+ column.addDescr( literalDescr );
+
+ ruleDescr.setConsequence( "System.out.println( stilton.getFieldValue( \"name\" ) + \" \" + stilton.getFieldValue( \"price\" ) );" );
+
+ builder.addPackage( packageDescr );
+
+ assertLength( 0,
+ builder.getErrors() );
+
+ RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+ Package pkg = builder.getPackage();
+ try {
+ ruleBase.addPackage( pkg );
+ } catch ( Exception e ) {
+ e.printStackTrace();
+ }
+ WorkingMemory workingMemory = ruleBase.newWorkingMemory();
+ Fact stilton = pkg.getFactTemplate( "Cheese" ).createFact( 1 );
+ stilton.setFieldValue( "name", "stilton" );
+ stilton.setFieldValue( "price", new Integer( 200 ) );
+ workingMemory.assertObject( stilton );
+ workingMemory.fireAllRules();
+
}
public void testLiteral() throws Exception {
@@ -298,7 +348,7 @@
lhs.addDescr( column );
FieldConstraintDescr literalDescr = new FieldConstraintDescr( "type" );
- literalDescr.addRestriction( new VariableRestrictionDescr("==", "stilton") );
+ literalDescr.addRestriction( new LiteralRestrictionDescr("==", "stilton") );
column.addDescr( literalDescr );
More information about the jboss-svn-commits
mailing list