📄 drl.g
字号:
grammar RuleParser; @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.*;}@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; } /** This will apply a list of constraints to an LHS block */ private String applyConstraints(List constraints, String block) { //apply the constraints as a comma seperated list inside the previous block //the block will end in something like "foo()" and the constraint patterns will be put in the () if (constraints == null) { return block; } StringBuffer list = new StringBuffer(); for (Iterator iter = constraints.iterator(); iter.hasNext();) { String con = (String) iter.next(); list.append("\n\t\t"); list.append(con); if (iter.hasNext()) { list.append(","); } } if (block.endsWith("()")) { return block.substring(0, block.length() - 2) + "(" + list.toString() + ")"; } else { return block + "(" + list.toString() + ")"; } } /** 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) ) ); } } }@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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -