/** Grammar from tour chapter augmented with actions */
grammar momo5;
// --- compil:
// antlr4 momo5.g4 -no-listener
// or just: antlr4 momo5.g4
options { language = JavaScript; }
@header {
/* some initialization here if required */
}
@parser::members {
/** "memory" for our calculator; variable/value pairs go here */
//mymap = new Object();
myeval = function(left, op, right) {
//function myeval(left, op, right) {
switch ( op ) {
case momo5Parser.MUL : return left * right;
case momo5Parser.DIV : return left / right;
case momo5Parser.ADD : return left + right;
case momo5Parser.SUB : return left - right;
}
return 0;
};
}
startRule: txt ;
txt: stat* EOF;
stat: cmd SEPARATOR
// | e SEPARATOR { output = $e.v; }
// | ID ':' e SEPARATOR { momoVars[mob][$ID.text] = $e.v; }
| SEPARATOR
;
cmd: ID ':' e { momoVars[mob][$ID.text] = $e.v; }
| 'if' c=e 'then' y=stat ( 'else' n=stat )? 'endif'
/* // { if ($c.v) start($y.ctx); }
{
if ( $c.getNextSibling() )
if( $c.getNextSibling().getFirstChild() )
stat($c.getNextSibling().getFirstChild());
}
else {
if( $c.getNextSibling() ) {
if( $c.getNextSibling().getNextSibling() ) {
stat( $c.getNextSibling().getNextSibling() );
}
}
}
} */
;
e returns [float v]
: '(' a=e ')' { $v = $a.v; }
| ID a=e { $v = momoVars[$a.v-1][$ID.text]; }
| ID { $v = momoVars[mob][$ID.text]; }
| a=e op=('*'|'/') b=e { $v = myeval($a.v, $op.type, $b.v); }
| a=e op=('+'|'-') b=e { $v = myeval($a.v, $op.type, $b.v); }
| 'max' '(' a=e ',' b=e ')' { $v = Math.max($a.v, $b.v); }
| 'min' '(' a=e ',' b=e ')' { $v = Math.min($a.v, $b.v); }
| 'ang' '(' a=e ',' b=e ')' { $v = Math.atan2($a.v, $b.v); }
| 'mod' '(' a=e ',' b=e ')' { $v = Math.mod($a.v, $b.v); }
| 'norm' '(' a=e ',' b=e ')' { $v = Math.sqrt($a.v*$a.v+$b.v*$b.v); }
| 'dist' '(' a=e ',' b=e ')' {
var x = momoVars[$b.v-1]['x']-momoVars[$a.v-1]['x'];
var y = momoVars[$b.v-1]['y']-momoVars[$a.v-1]['y'];
$v = Math.sqrt(x*x+y*y); }
| a=e '=' b=e { $v = ($a.v==$b.v) ? 1 : 0; }
| a=e '<>' b=e { $v = ($a.v!=$b.v) ? 1 : 0; }
| a=e '>' b=e { $v = ($a.v> $b.v) ? 1 : 0; }
| a=e '>=' b=e { $v = ($a.v>=$b.v) ? 1 : 0; }
| a=e '<' b=e { $v = ($a.v< $b.v) ? 1 : 0; }
| a=e '<=' b=e { $v = ($a.v<=$b.v) ? 1 : 0; }
| 'abs' '(' a=e ')' { $v = Math.abs($a.v); }
| 'int' '(' a=e ')' { $v = Math.floor($a.v); }
| 'frac' '(' a=e ')' { $v = $a.v-Math.floor($a.v); }
| 'sgn' '(' a=e ')' { $v = Math.sign($a.v); }
| 'sqrt' '(' a=e ')' { $v = Math.sqrt($a.v); }
| 'exp' '(' a=e ')' { $v = Math.exp($a.v); }
| 'log' '(' a=e ')' { $v = Math.log($a.v); }
| 'cos' '(' a=e ')' { $v = Math.cos($a.v); }
| 'sin' '(' a=e ')' { $v = Math.sin($a.v); }
| 'tan' '(' a=e ')' { $v = Math.tan($a.v); }
| 'rnd' { $v = rnd(); }
| 'srnd' { $v = 2*rnd()-1; }
| 'PI' { $v = Math.PI; }
| '-' a=e { $v = - $a.v; }
| INT { $v = $INT.int; }
| FLOAT { $v = parseFloat($FLOAT.text); }
;
MUL : '*' ;
DIV : '/' ;
ADD : '+' ;
SUB : '-' ;
ID : [a-zA-Z]+ ; // match identifiers
INT : [0-9]+ ; // match integers
FLOAT: INT ( '.' INT )? // match floats
| INT '.'
| '.' INT ;
COMMENT: '//' (~('\n'|'\r'))* -> skip ;
SEPARATOR: NEWLINE
| ';'
;
NEWLINE: ('\r'? '\n')+ // return newlines to parser (is end-statement signal)
| '
'
| '
'
| EOF
;
WS : [ \t]+ -> skip ; // toss out whitespace