/** 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