Hej devs,

here is the patch for the grammar and the tree-grammar.

Marc

On Thursday 29 May 2008 17:57:30 Alex Boisvert wrote:
> Hi Marc,
>
> Yes, you're right about the cardinality issue in the grammar.  A patch
> would be greatly appreciated!
>
> alex
>
> On Thu, May 29, 2008 at 8:23 AM, Marc Bischof <[EMAIL PROTECTED]> wrote:
> > Hello devs,
> >
> > I'am a student at the IAAS and working on a BPEL2SimPEL translator.
> >
> > I looked at the SimPEL-Grammar and I think you've missed something when
> > modeling non-empty lists.
> >
> > I also propose that the rewrite-rules should be correct in the grammar
> > so the translation into tree-grammar would be clearer and less error
> > prone.
> >
> > Here a short example:
> >
> > In the param_block-rule you've modeled an optional ID-list. But in the
> > rewrite-rule this is missing. So I think that there should be $in* (in
> > general this should be a $in+, but in this special case the complete list
> > is
> > optional).
> > When this was done in the proposed way in the grammar, it would also
> > affect the tree-grammar. There, the param-block-rule is currently modeled
> > with $ID+
> > instead of $ID*.
> >
> > So I went over the grammar and looked for these errors (changes in
> > tree-grammar analog):
> >
> > * param_block : '{' ('|' in+=ID (',' in+=ID)* '|')? proc_stmt+ '}' ->
> > ^(SEQUENCE $in proc_stmt+);
> >
> > > param_block : '{' ('|' in+=ID (',' in+=ID)* '|')? proc_stmt+ '}' ->
> >
> > ^(SEQUENCE $in* proc_stmt+);
> >
> > * flow : 'parallel' b+=body ('and' b+=body)* -> ^(FLOW $b);
> >
> > >    flow : 'parallel' b+=body ('and' b+=body)* -> ^(FLOW $b+);
> >
> > * join : 'join' '(' k+=ID (',' k+=ID)* (',' expr)? ')' -> ^(JOIN $k
> > expr?);
> >
> > >    join : 'join' '(' k+=ID (',' k+=ID)* (',' expr)? ')' -> ^(JOIN $k+
> >
> > expr?);
> >
> > * with_ex : 'with' '(' wm+=with_map (',' wm+=with_map)* ')' body ->
> > ^(WITH $wm* body);
> >
> > >    with_ex : 'with' '(' wm+=with_map (',' wm+=with_map)* ')' body ->
> >
> > ^(WITH
> > $wm+ body);
> >
> > * partner_link : 'partnerLink' pl+=ID (',' pl+=ID)* -> ^(PARTNERLINK
> > $pl);
> >
> > >    partner_link : 'partnerLink' pl+=ID (',' pl+=ID)* -> ^(PARTNERLINK
> >
> > $pl+);
> >
> > * correlation : '{' corr_mapping (',' corr_mapping)* '}' -> ^(CORRELATION
> > corr_mapping*);
> >
> >  >   correlation : '{' corr_mapping (',' corr_mapping)* '}' ->
> >
> > ^(CORRELATION
> > corr_mapping+);
> >
> > * path_expr : pelmt+=ns_id ('.' pelmt+=ns_id)* -> ^(PATH $pelmt);
> >
> > >    path_expr : pelmt+=ns_id ('.' pelmt+=ns_id)* -> ^(PATH $pelmt+);
> >
> > Do you think, I'm right. Should I file a patch?
> >
> > Kind regards
> >     Marc Bischof


grammar SimPEL;

options {
    output=AST; 
    language=Java;
    ASTLabelType=LinkedListTree;
}
tokens {
    ROOT; PROCESS; PICK; SEQUENCE; FLOW; IF; ELSEIF; ELSE; WHILE; UNTIL; FOREACH; FORALL; INVOKE;
    RECEIVE; REPLY; ASSIGN; THROW; WAIT; EXIT; TIMEOUT; TRY; CATCH; CATCH_ALL; SCOPE; EVENT;
    ALARM; COMPENSATION; COMPENSATE; CORRELATION; CORR_MAP; PARTNERLINK; VARIABLE; BLOCK_PARAM; 
    SIGNAL; JOIN; WITH; MAP;
    EXPR; EXT_EXPR; XML_LITERAL; CALL; NAMESPACE; NS; PATH;
}
@parser::header {
package org.apache.ode.simpel.antlr;

import uk.co.badgersinfoil.e4x.antlr.LinkedListTokenStream;
import uk.co.badgersinfoil.e4x.antlr.LinkedListTree;
import uk.co.badgersinfoil.e4x.E4XHelper;
import org.apache.ode.simpel.ErrorListener;
import org.apache.ode.simpel.util.JSHelper;
}
@lexer::header {
package org.apache.ode.simpel.antlr;
import org.apache.ode.simpel.ErrorListener;
}

@lexer::members {
    private ErrorListener el;

    public void setErrorListener(ErrorListener el) {
        this.el = el;
    }
    public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
        el.reportRecognitionError(tokenNames, e.line, getErrorMessage(e, tokenNames), e);
    }
}

@parser::members {
    public static final int CHANNEL_PLACEHOLDER = 999;

    private SimPELLexer lexer;
    private CharStream cs;
    private ErrorListener el;
    
    public void setInput(SimPELLexer lexer, CharStream cs) {
        this.lexer = lexer;
        this.cs = cs;
    }
    public void setErrorListener(ErrorListener el) {
        this.el = el;
    }

    /** Handle 'island grammar' for embeded XML-literal elements. */
    private LinkedListTree parseXMLLiteral() throws RecognitionException {
        return E4XHelper.parseXMLLiteral(lexer, cs, (LinkedListTokenStream)input);
    }
    /** Handle 'island grammar' for embeded JavaScript-literal elements. */
    private LinkedListTree parseJSLiteral() throws RecognitionException {
        return JSHelper.parseJSLiteral(lexer, cs, (LinkedListTokenStream)input);
    }
    
    public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
        el.reportRecognitionError(tokenNames, e.line, getErrorMessage(e, tokenNames), e);
    }
    
    public String getErrorMessage(RecognitionException e, String[] tokenNames) {
        List stack = getRuleInvocationStack(e, this.getClass().getName());
        String msg = null;
        if ( e instanceof NoViableAltException ) {
            NoViableAltException nvae = (NoViableAltException)e;
            msg = " no viable alt; token="+e.token+" (decision="+nvae.decisionNumber+" state "+nvae.stateNumber+")"+
                  " decision=<<"+nvae.grammarDecisionDescription+">>";
        } else {
           msg = super.getErrorMessage(e, tokenNames);
        }
        return stack+" "+msg;
    }
    
    public String getTokenErrorDisplay(Token t) {
        return t.toString();
    }
}

// MAIN BPEL SYNTAX

program :       declaration+ -> ^(ROOT declaration+);
declaration
        :       funct | process | namespace;

// Process
process :       'process' ns_id body -> ^(PROCESS ns_id body);

proc_stmt
        :       pick | flow | if_ex | while_ex | until_ex | foreach | forall | try_ex | scope_ex | with_ex
                | receive | ((invoke | reply | assign | throw_ex | wait_ex | exit | signal | join
                | variables | partner_link) SEMI!);

block   :       '{' proc_stmt+ '}' -> ^(SEQUENCE proc_stmt+);

param_block 
        :	     '{' ('|' in+=ID (',' in+=ID)* '|')? proc_stmt+ '}' -> ^(SEQUENCE $in* proc_stmt+);
        
body    :       block | proc_stmt;

// Structured activities
pick    :       'pick' '{' receive* timeout* '}' -> ^(PICK receive* timeout*);
timeout :       'timeout' '(' expr ')' block -> ^(TIMEOUT expr block); 

flow : 'parallel' b+=body ('and' b+=body)* -> ^(FLOW $b+);
signal  :       'signal' '('ID (',' expr)? ')' -> ^(SIGNAL ID expr?);
join    :       'join' '(' k+=ID (',' k+=ID)* (',' expr)? ')' -> ^(JOIN $k+ expr?);

if_ex   :       'if' '(' expr ')' ifb=body ('else' eb=body)? -> ^(IF expr $ifb (^(ELSE $eb))?);

while_ex:       'while' '(' expr ')' body -> ^(WHILE expr body);

until_ex:       'do' body 'until' '(' expr ')' -> ^(UNTIL expr body);

foreach :       'for' '(' ID '=' init=expr ';' cond=expr ';' assign ')' body -> ^(FOREACH ID $init $cond assign body);
forall  :       'forall' '(' ID '=' from=expr 'to' to=expr ')' body -> ^(FORALL ID $from $to body);

try_ex  :       'try' body catch_ex* -> ^(TRY body catch_ex*);          
catch_ex:       'catch' '(' ns_id ')' param_block -> ^(CATCH ns_id param_block);

scope_ex:       'scope' ('(' ID ')')? body scope_stmt* -> ^(SCOPE ID? body scope_stmt*);
scope_stmt
        :       event | alarm | compensation;

event   :       'event' '(' p=ID ',' o=ID ')' param_block -> ^(EVENT $p $o param_block);
alarm   :       'alarm' '(' expr ')' body -> ^(ALARM expr body);
compensation
        :       'compensation' body -> ^(COMPENSATION body);

with_ex : 'with' '(' wm+=with_map (',' wm+=with_map)* ')' body -> ^(WITH $wm+ body);
with_map:       ID ':' path_expr -> ^(MAP ID path_expr);

// Simple activities
invoke  :       'invoke' '(' p=ID ',' o=ID (',' in=ID)? ')' -> ^(INVOKE $p $o $in?);

receive 
options {backtrack=true;}
        :       receive_base SEMI -> ^(RECEIVE receive_base) |
                receive_base param_block -> ^(RECEIVE receive_base) param_block;
receive_base
        :       'receive' '(' p=ID ',' o=ID (',' correlation)? ')' -> ^($p $o correlation?);

reply   :       'reply' '(' ID (',' ID ',' ID)? ')' -> ^(REPLY ID (ID ID)?);

assign  :       path_expr '=' rvalue -> ^(ASSIGN path_expr rvalue);
rvalue
        :        receive_base -> ^(RECEIVE receive_base)
                | invoke | expr | xml_literal;
        
throw_ex:       'throw' '('? ns_id ')'? -> ^(THROW ns_id);

wait_ex :       'wait' '('expr')' -> ^(WAIT expr);

compensate
        :       'compensate' ('(' ID ')')? -> ^(COMPENSATE ID?);

exit    :       'exit' -> ^(EXIT);


// Others
namespace
        :       'namespace' ID '=' STRING SEMI -> ^(NAMESPACE ID STRING);
                
variables
        :       'var'! v+=variable (','! v+=variable)*;
variable:       ID VAR_MODS* -> ^(VARIABLE ID VAR_MODS*);

partner_link : 'partnerLink' pl+=ID (',' pl+=ID)* -> ^(PARTNERLINK $pl+);

correlation : '{' corr_mapping (',' corr_mapping)* '}' -> ^(CORRELATION corr_mapping+);
corr_mapping
        :       f1=ID ':' expr -> ^(CORR_MAP $f1 expr);

funct   :       'function'^ f=ID '(' ID? (','! ID)* ')' js_block;

// Expressions
expr    :       s_expr | EXT_EXPR | funct_call;

funct_call
        :       p+=ID '(' p+=ID* ')' -> ^(CALL ID+);
// TODO add && || !
s_expr  :       condExpr;
condExpr:       aexpr ( ('==' ^|'!=' ^|'<' ^|'>' ^|'<=' ^|'>=' ^) aexpr )?;
aexpr   :       mexpr (('+'|'-') ^ mexpr)*;
mexpr   :       atom (('*'|'/') ^ atom)* | STRING;
atom    :       path_expr | INT | '(' s_expr ')' -> s_expr;
path_expr : pelmt+=ns_id ('.' pelmt+=ns_id)* -> ^(PATH $pelmt+);

ns_id   :       (pr=ID '::')? loc=ID -> ^(NS $pr? $loc);

// In-line XML

xml_literal
@init { LinkedListTree xml = null; }
        :       // We have to have the LT in the outer grammar for lookahead
                // in AS3Parser to be able to predict that the xmlLiteral rule
                // should be used.
                '<' { xml=parseXMLLiteral(); } -> { xml };

js_block
@init { LinkedListTree js = null; }
        :       '{' { js=parseJSLiteral(); } -> { js };

EXT_EXPR
        :       '[' (options {greedy=false;} : .)* ']';

// Basic tokens
VAR_MODS:       'unique' | 'external' | ('string' | 'int' | 'float');
SEMI    :       ';';
ID      :       (LETTER | '_' ) (LETTER | DIGIT | '_' | '-' )*;
INT     :       (DIGIT )+ ;
STRING  :       '"' ( ESCAPE_SEQ | ~('\\'|'"') )* '"';
ESCAPE_SEQ
        :       '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\');

SL_COMMENTS
        :       ('#'|'//') .* CR { $channel = HIDDEN; };
CR      :       ('\r' | '\n' )+ { $channel = HIDDEN; };
WS      :       ( ' ' | '\t' )+ { skip(); };
fragment DIGIT
    :    '0'..'9';
fragment LETTER
    : 'a'..'z' | 'A'..'Z';
tree grammar SimPELWalker;

options {
    tokenVocab=SimPEL;
    ASTLabelType=LinkedListTree;
}
tokens {
    XML_ELEMENT; XML_ATTRIBUTE; XML_NAME; XML_ATTRIBUTE_VALUE; XML_TEXT; XML_WS; XML_COMMENT; XML_CDATA; XML_PI;
}
scope BPELScope { OScope oscope; }
scope Parent { OBuilder.StructuredActivity activity; }
scope ReceiveBlock { OPickReceive receive; }
scope ExprContext { SimPELExpr expr; }

@header {
package org.apache.ode.simpel.antlr;
import uk.co.badgersinfoil.e4x.antlr.LinkedListTree;
import uk.co.badgersinfoil.e4x.antlr.LinkedListToken;
import org.apache.ode.simpel.ErrorListener;
import org.apache.ode.simpel.omodel.OBuilder;
import org.apache.ode.simpel.omodel.SimPELExpr;
import org.apache.ode.bpel.o.*;
}

@members {
    // Grammar level members
    
    private ErrorListener el;
    
    public void setErrorListener(ErrorListener el) {
        this.el = el;
    }
    public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
        el.reportRecognitionError(tokenNames, e.line, getErrorMessage(e, tokenNames), e);
    }
    
    public String getErrorMessage(RecognitionException e, String[] tokenNames) {
        List stack = getRuleInvocationStack(e, this.getClass().getName());
        String msg = null;
        if ( e instanceof NoViableAltException ) {
            NoViableAltException nvae = (NoViableAltException)e;
            msg = " no viable alt; token="+e.token+" (decision="+nvae.decisionNumber+" state "+nvae.stateNumber+")"+
                  " decision=<<"+nvae.grammarDecisionDescription+">>";
        } else {
           msg = super.getErrorMessage(e, tokenNames);
        }
        return stack+" "+msg;
    }
    
    public String getTokenErrorDisplay(Token t) {
        return t.toString();
    }
    
    // Lamguage level members
    
    private OBuilder builder = new OBuilder();

    public OBuilder getBuilder() {
        return builder;
    }
    
    private String text(org.antlr.runtime.tree.Tree t) {
        if (t == null) return null;
        else return t.getText();
    }

    private String deepText(org.antlr.runtime.tree.Tree t) {
        LinkedListTree llt = ((LinkedListTree)t);
        StringBuffer b = new StringBuffer();
        LinkedListToken tok = ((LinkedListTree)t).getStartToken();
        b.append(tok.getText());
        while(tok != llt.getStopToken() && (tok = tok.getNext()) != null)
            if (tok.getText() != null) b.append(tok.getText());
        return b.toString();
    }

}

program :       ^(ROOT declaration+);
declaration
        :       process | namespace;

namespace
        :       ^(NAMESPACE ID STRING);

// Process
process
scope BPELScope Parent;
        :       ^(PROCESS ^(NS pr=ID? nm=ID) 
                { OBuilder.StructuredActivity<OScope> scope = builder.buildProcess(text($pr), text($nm));
                  $BPELScope::oscope = scope.getOActivity(); 
                  $Parent::activity = scope;
                } 
                body);

proc_stmt
        :       pick | flow | if_ex | while_ex | until_ex | foreach | forall | try_ex | scope_ex | with_ex
                | invoke | receive | reply | assign | throw_ex | wait_ex | exit | signal | join
                | variable | partner_link;
block
scope Parent;
        :       ^(SEQUENCE 
                { OBuilder.StructuredActivity seq = builder.build(OSequence.class, $BPELScope::oscope, $Parent[-1]::activity); 
                  $Parent::activity = seq;
                }
                proc_stmt+);
param_block
scope Parent;
        :       ^(SEQUENCE ID*
                { OBuilder.StructuredActivity seq = builder.build(OSequence.class, $BPELScope::oscope, $Parent[-1]::activity); 
                  $Parent::activity = seq;
                  builder.setBlockParam($BPELScope::oscope, (OActivity) $Parent[-1]::activity.getOActivity(), $ID.text); 
                }
                proc_stmt+);
body    :       block | proc_stmt;
                

// Structured activities
pick    
        :       ^(PICK receive* timeout*);
timeout :       ^(TIMEOUT expr block); 

// TODO links
flow    
        :       ^(FLOW body+);
signal  :       ^(SIGNAL ID expr?);
join    :       ^(JOIN ID+ expr?);

if_ex   
        :       ^(IF expr body (^(ELSE body))?);

while_ex
        :       ^(WHILE expr body);

until_ex
        :       ^(UNTIL expr body);

foreach 
        :       ^(FOREACH ID init=expr cond=expr assign body);
forall  
        :       ^(FORALL ID from=expr to=expr body);

try_ex
scope BPELScope;
        :       ^(TRY body catch_ex*);
catch_ex:       ^(CATCH ^(NS ID ID?) param_block);

scope_ex
scope BPELScope;
        :       ^(SCOPE ID? body scope_stmt*);
scope_stmt
        :       event | alarm | compensation;

event   :       ^(EVENT ID ID param_block);
alarm   :       ^(ALARM expr body);
compensation
        :       ^(COMPENSATION body);

with_ex 
        :       ^(WITH with_map+ body);
with_map:       ^(MAP ID path_expr);

// Simple activities
invoke  :       ^(INVOKE p=ID o=ID in=ID?);


reply   :       ^(REPLY msg=ID (pl=ID var=ID)?) 
                { builder.build(OReply.class, $BPELScope::oscope, $Parent::activity,
                        $ReceiveBlock::receive, text($msg), text($pl), text($var)); };
receive 
scope ReceiveBlock;
        :       ^(RECEIVE ^(p=ID o=ID correlation?))
                { 
                  OBuilder.StructuredActivity<OPickReceive> rec = builder.build(OPickReceive.class, $BPELScope::oscope, 
                      $Parent::activity, text($p), text($o)); 
                  $ReceiveBlock::receive = rec.getOActivity();
                }
                (prb=(param_block))?;
        

assign  
scope ExprContext;
        :       ^(ASSIGN 
                {
                  $ExprContext::expr = new SimPELExpr(builder.getProcess());
                }
                lv=(path_expr) rv=(rvalue)) 
                {
                  $ExprContext::expr.setExpr(deepText($rv));
                  OBuilder.StructuredActivity<OAssign> assign = builder.build(OAssign.class, $BPELScope::oscope, $Parent::activity, deepText($lv), $ExprContext::expr);
                  // The long, winding road of abstraction
                  $ExprContext::expr = (SimPELExpr) ((OAssign.Expression)((OAssign.Copy)assign.getOActivity().operations.get(0)).from).expression;
                };
rvalue  :       receive | invoke | expr | xmlElement;
        
throw_ex:       ^(THROW ns_id);

wait_ex :       ^(WAIT expr);

exit    :       EXIT;

// Other
variable:       ^(VARIABLE ID VAR_MODS*);

partner_link
        :       ^(PARTNERLINK ID+);
correlation
        :       ^(CORRELATION corr_mapping+);
corr_mapping
        :       ^(CORR_MAP ID expr);

// XML
xmlElement
        :       ^(XML_EMPTY_ELEMENT XML_NAME xmlAttribute*) | ^(XML_ELEMENT XML_NAME xmlAttribute* xmlElementContent*) 
                { System.out.println("ELMT " + $XML_NAME.text); };
xmlAttribute
        :       ^(XML_ATTRIBUTE XML_NAME XML_ATTRIBUTE_VALUE) { System.out.println("ATTR " + $XML_NAME.text); };
xmlElementContent
        :       xmlMarkup | xmlText | xmlElement;
xmlText :       XML_TEXT | XML_NAME | XML_WS;
xmlMarkup
        :       XML_COMMENT | XML_CDATA | XML_PI;

// Expressions
expr    :       s_expr | EXT_EXPR | funct_call;

funct_call
        :       ^(CALL ID*);
path_expr
        :       ^(PATH ids=(ns_id+)) { builder.addExprVariable($BPELScope::oscope, $ExprContext::expr, deepText($ids)); };
ns_id   :       ^(NS ID? ID);

s_expr  :       ^('==' s_expr s_expr) 
        |       ^('!=' s_expr s_expr) 
        |       ^('<' s_expr s_expr) 
        |       ^('>' s_expr s_expr) 
        |       ^('>=' s_expr s_expr) 
        |       ^('<=' s_expr s_expr) 
        |       ^('+' s_expr s_expr) 
        |       ^('-' s_expr s_expr) 
        |       ^('*' s_expr s_expr) 
        |       ^('/' s_expr s_expr) 
        |       path_expr | INT | STRING;

Reply via email to