Skip to content

Commit

Permalink
Functions abstract syntax trees hide functions existence.
Browse files Browse the repository at this point in the history
  • Loading branch information
meri committed Sep 29, 2011
1 parent 94fc716 commit bf8f2b5
Show file tree
Hide file tree
Showing 21 changed files with 2,357 additions and 18 deletions.
@@ -0,0 +1,107 @@
grammar S008FunctionsNiceTree;

options
{
// antlr will generate java lexer and parser
language = Java;
// generated parser should create abstract syntax tree
output = AST;
}

//as the generated lexer will reside in org.meri.antlr_step_by_step.parsers
//package, we have to add package declaration on top of it
@lexer::header {
package org.meri.antlr_step_by_step.parsers;
import org.meri.antlr_step_by_step.parsers.S008FunctionsNiceTreeCompiler.S008Error;
}

//as the generated parser will reside in org.meri.antlr_step_by_step.parsers
//package, we have to add package declaration on top of it
@parser::header {
package org.meri.antlr_step_by_step.parsers;
import org.meri.antlr_step_by_step.parsers.S008FunctionsNiceTreeCompiler.S008Error;
}

//override some methods and add new members to generated lexer
@lexer::members {
//override method
public void reportError(RecognitionException e) {
displayRecognitionError(this.getTokenNames(), e);
throw new S008Error(":(", e);
}

}

//override some methods and add new members to generated parser
@parser::members {
//override method
public void reportError(RecognitionException e) {
displayRecognitionError(this.getTokenNames(), e);
throw new S008Error(":(", e);
}

}

// ***************** lexer rules:
//the grammar must contain at least one lexer rule
LPAREN : '(' ;
RPAREN : ')' ;
AND : '&&';
OR : '||';
NOT : '!';

ALL : 'all';
ATLEASTONE : 'atleastone';
NEITHER : 'neither';
NOTALL : 'notall';

NAME : ('a'..'z' | '0'..'9')+;
WS : ( ' ' | '\t' | '\r' | '\n' )+ { $channel = HIDDEN; };

// ***************** parser rules:
//This looks useless, but ANTLR would complain about "no start rule (...)"
//without it. As this rule is not referenced by any other rule, ANTLR will
//start rule and the warning disappears.
//
//start rule
expression : andexpression;
//first, we try to match all first level && (e.g. && not included in some sub-expression)
andexpression : orexpression (AND^ orexpression)*;
//second, we try to match all first level || (e.g. || not included in some sub-expression)
orexpression : notexpression (OR^ notexpression)*;
//third, there may or may not be first level ! in front of an expression
notexpression : NOT^ atom | atom;
//finally, we found either name, functions, or a sub-expression
atom : function | NAME | LPAREN! andexpression RPAREN!;
//functions definition
function : allFunction | atleastoneFunction | neitherFunction | notallFunction;

//the function all(p1, p2, ..., pn) is equivalent to p1 && p2 && ... && pn
allFunction : ALL LPAREN b=andexpression (',' a+=andexpression)* RPAREN
//if the list $a is empty, use only first argument
-> {$a==null || $a.isEmpty()}? $b
//otherwise create a flat tree
-> ^(AND $b $a*);

//the function ateastone(p1, p2, ..., pn) is equivalent to p1 || p2 || ... || pn
atleastoneFunction : ATLEASTONE LPAREN b=andexpression (',' a+=andexpression)* RPAREN
//if the list $a is empty, use only first argument
-> {$a==null || $a.isEmpty()}? $b
//otherwise create a flat tree
-> ^(OR $b $a*);

//the function neither(p1, p2, ..., pn) is equivalent to !p1 && !p2 && ... && !pn
neitherFunction : NEITHER LPAREN b=andexpression (',' a+=andexpression)* RPAREN
//if the list $a is empty, use only first argument
-> {$a==null || $a.isEmpty()}? ^(NOT $b)
//otherwise create a flat tree
-> ^(AND ^(NOT $b) ^(NOT $a)*);

//the function notall(p1, p2, ..., pn) is equivalent to !p1 || !p2 || ... || !pn
notallFunction : NOTALL LPAREN b=andexpression (',' a+=andexpression)* RPAREN
//if the list $a is empty, use only first argument
-> {$a==null || $a.isEmpty()}? ^(NOT $b)
//otherwise create a flat tree
-> ^(OR ^(NOT $b) ^(NOT $a)*);


@@ -0,0 +1,38 @@
package org.meri.antlr_step_by_step.parsers;

import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.TokenStream;
import org.antlr.runtime.tree.CommonTree;

public class S008FunctionsNiceTreeCompiler extends AbstractCompiler {

public CommonTree compile(String expression) {
try {
//lexer splits input into tokens
ANTLRStringStream input = new ANTLRStringStream(expression);
TokenStream tokens = new CommonTokenStream(new S008FunctionsNiceTreeLexer(input));

//parser generates abstract syntax tree
S008FunctionsNiceTreeParser parser = new S008FunctionsNiceTreeParser(tokens);
S008FunctionsNiceTreeParser.expression_return ret = parser.expression();

//acquire parse result
CommonTree ast = (CommonTree) ret.tree;
printTree(ast);
return ast;
} catch (RecognitionException e) {
throw new IllegalStateException("Recognition exception is never thrown, only declared.");
}
}

@SuppressWarnings("serial")
public static class S008Error extends RuntimeException {

public S008Error(String arg0, Throwable arg1) {
super(arg0, arg1);
}

}
}

0 comments on commit bf8f2b5

Please sign in to comment.