Oisin Hurley wrote:
Hi Vadim,
Have you got an ANTLR grammar, or BNF of some kind for the DSL? This
is probably a good opportunity for me to learn how to use XText at
long last :) Unless anyone else has made a start...?
--oh
Hi Oisin,
That would be great!
Here is the current grammar (antlr v-3.1):
================================================================
grammar Camel;
options { output = AST; }
tokens {
ROUTES; FUNCTION; PARAMS; THEN; PROCESS; TEXT;
}
@header { package org.mycompany.test; }
@lexer::header { package org.mycompany.test; }
routes :
route+ -> ^(ROUTES route+)
;
/* TODO:
Dead Letter Channel
TransactionErrorHandler
loggingErrorHandler
exception
BAM
Recipient List: to el:'new string[] {'a','b'}' or whatever el syntax is
splitter
aggregator
resequencer
routingSlip
throttler
delayer
loadBalance
multicast
loop
policy/transactions
DelayPolicy
idempotentConsumer
*/
route :
ROUTE from process* -> ^(ROUTE from process*)
;
from :
FROM fromTarget -> ^(FROM fromTarget)
| FROM '{' fromTarget+ '}' -> ^(FROM fromTarget+)
;
fromTarget
: endpoint // TODO: can it be multiple endpoints?
;
to
: TO toTarget -> ^(TO toTarget)
| TO '{' toTarget+ '}' -> ^(TO toTarget+)
;
toTarget
: endpoint
| process
;
/*endpoints :
endpoint
| LCUR_PAREN endpoint+ RCUR_PAREN -> ^(endpoint)+
;
*/
endpoint
: singleLineString
//| ifExpr
;
// TODO: nested IF
ifExpr
options {backtrack=true;} // TODO: make sure that "sliding else" works
correctly
: IF '(' boolExpression ')' p1=processes ELSE p2=processes -> ^(IF
boolExpression ^(THEN $p1) ^(ELSE $p2))
| IF '(' boolExpression ')' processes -> ^(IF boolExpression processes)
;
boolExpression :
//orExpression
boolValue
;
boolFunction:
LITERAL ':' anyString -> ^(FUNCTION LITERAL anyString)
;
boolValue :
boolFunction
| value compare value
| TRUE
| FALSE
;
value
: header
| XPATH singleLineString -> ^(XPATH singleLineString)
| singleLineString
| BODY
;
header
: HEADER singleLineString -> ^(HEADER LITERAL[$singleLineString.text])
| HEADER '.' LITERAL -> ^(HEADER LITERAL[$LITERAL.text])
| HEADER '[' singleLineString ']' -> ^(HEADER
LITERAL[$singleLineString.text])
;
compare :
LT
| GT
| EQ
| LE
| GE
| NE
;
boolOperator :
OR
| AND
| NOT
;
process :
to
|ifExpr
| SET header '=' singleLineString -> ^(SET header singleLineString)
| SET BODY '=' anyString -> ^(SET BODY anyString)
| splitter
| BEAN SINGLE_Q_STRING -> ^(BEAN SINGLE_Q_STRING)
//| MULTICAST '{' process* '}' -> ^(MULTICAST process*)
//| PIPELINE '{' process_list '}'
| SPLIT SINGLE_Q_STRING
//| AGGREGATE expression
| AGGREGATE
//| resequence
;
processes:
process -> ^(PROCESS process)
| '{' process+ '}' -> ^(PROCESS process+)
;
splitter:
SPLITTER '(' list=value token=singleLineString? ')'
/*aggregationStrategy? TODO: */
-> ^(SPLITTER $list $token)
;
/* TODO */
/*aggregationStrategy
:
;*/
/*resequence :
RESEQUENCE BATCH
//| BATCH RESEQUENCE expression
| BATCH RESEQUENCE NUMBER NUMBER
//| BATCH RESEQUENCE NUMBER NUMBER '(' expression_list ')'
//| STREAM RESEQUENCE resequence_options
//| STREAM RESEQUENCE resequence_options '(' expression ')'
;
*/
anyString :
SINGLE_Q_STRING -> ^(TEXT[$SINGLE_Q_STRING.text])
| SINGLE_Q_MULTILINE_STRING -> ^(TEXT[$SINGLE_Q_MULTILINE_STRING.text])
| DOUBLE_Q_STRING -> ^(TEXT[$DOUBLE_Q_STRING.text])
| DOUBLE_Q_MULTILINE_STRING -> ^(TEXT[$DOUBLE_Q_MULTILINE_STRING.text])
;
singleLineString :
SINGLE_Q_STRING
| DOUBLE_Q_STRING
;
/*********************************************
Lexer
*********************************************/
ROUTE : 'route';
FROM : 'from';
TO : 'to';
BEAN : 'bean';
MULTICAST: 'multicast';
PIPELINE: 'pipeline';
SPLIT : 'split';
AGGREGATE: 'aggregate';
RESEQUENCE: 'resequence';
BATCH : 'batch';
STREAM : 'stream';
SET : 'set';
HEADER : 'header';
BODY : 'body';
XPATH : 'xpath';
SPLITTER: 'splitter';
IF : 'if';
ELSE : 'else';
LT : '<';
GT : '>';
EQ : '==';
LE : '<=';
GE : '>=';
NE : ('!='|'<>');
OR : '||'|'or';
AND : '&&'|'and';
NOT : '!'|'not';
TRUE : 'true';
FALSE : 'false';
NUMBER : '0'..'9'+;
SINGLE_Q_STRING : '\'' ~('\''|'\n'|'\r')* '\''
{setText(getText().substring(1, getText().length()-1));} ;
SINGLE_Q_MULTILINE_STRING : '\'' ~('\'')* '\''
{setText(getText().substring(1, getText().length()-1));} ;
DOUBLE_Q_STRING : '"' ~('"'|'\n'|'\r')* '"'
{setText(getText().substring(1, getText().length()-1));} ;
DOUBLE_Q_MULTILINE_STRING : '"' ~('"')* '"'
{setText(getText().substring(1, getText().length()-1));} ;
LITERAL : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*;
WS : (' '|'\r'|'\n'|'\t')+ {$channel = HIDDEN;} ;
COMMENT
: '/*' .* '*/' {$channel=HIDDEN;}
;
LINE_COMMENT
: '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
;