Skip to content

Instantly share code, notes, and snippets.

@nakamura-to
Created August 12, 2012 08:13
Show Gist options
  • Save nakamura-to/3330618 to your computer and use it in GitHub Desktop.
Save nakamura-to/3330618 to your computer and use it in GitHub Desktop.
Translator with ANTLR
i = 1
while i < 10 { // even number?
if i % 2 == 2 {
even = even + 1
} else {
odd = odd + 1
}
i = i + 1
}
even + odd
group Js;
program(vars, text) ::= <<
(function () {
var <vars : {var | <var> = 0}; separator=", ">;
<text>
})();
>>
if(cond, thenBlock, elseBlock) ::= <<
if (<cond>) {
<thenBlock>
} <if(elseBlock)> else {
<elseBlock>
}<endif>
>>
while(cond, block) ::= <<
while (<cond>) {
<block>
}
>>
assign(id, expr) ::= <<
<id> = <expr>
>>
simple(text) ::= <<
<text>;
>>
import java.io.FileReader;
import org.antlr.runtime.ANTLRFileStream;
import org.antlr.runtime.CharStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeNodeStream;
import org.antlr.stringtemplate.StringTemplateGroup;
public class Main {
public static void main(String[] args) throws Exception {
FileReader reader = new FileReader("./bin/Js.stg");
StringTemplateGroup templates = new StringTemplateGroup(reader);
CharStream input = new ANTLRFileStream("./bin/input.txt");
StoneLexer lexer = new StoneLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
StoneParser parser = new StoneParser(tokens);
CommonTree tree = parser.program().tree;
CommonTreeNodeStream nodes = new CommonTreeNodeStream(tree);
nodes.setTokenStream(tokens);
StoneToJs walker = new StoneToJs(nodes);
walker.setTemplateLib(templates);
Object t = walker.program(parser.vars).getTemplate();
System.out.println(t);
}
}
(function () {
var even = 0, odd = 0, i = 0;
i = 1;
while (i < 10) {
if (i % 2 == 2) {
even = even + 1;
} else {
odd = odd + 1;
}
i = i + 1;
}
return even + odd;
})();
grammar Stone;
options {
output=AST;
ASTLabelType=CommonTree;
}
tokens {
UNARY_MINUS;
BLOCK;
SIMPLE;
}
@header {
import java.util.HashSet;
}
@members {
HashSet vars;
}
program
@init {
this.vars = new HashSet();
}
: statement* EOF -> statement*
;
statement
: 'if' expr block ('else' block)? -> ^('if' expr block block?)
| 'while' expr block -> ^('while' expr block)
| simple NL -> ^(SIMPLE simple NL)
;
block
: '{' NL? statement* '}' NL? -> ^(BLOCK statement*)
;
simple
: expr
| assign
;
assign
: IDENTIFIER '=' simple
{
vars.add($IDENTIFIER.text);
}
-> ^('=' IDENTIFIER simple)
;
expr
: (addExpr -> addExpr) ((op='=='|op='>'|op='<') rhs=addExpr -> ^($op $expr $rhs))*
;
addExpr
: (multExpr -> multExpr) ((op='+'|op='-') rhs=multExpr -> ^($op $addExpr $rhs))*
;
multExpr
: (factor -> factor) ((op='*'|op='/'|op='%') rhs=factor -> ^($op $multExpr $rhs))*
;
factor
: '-' primary -> ^(UNARY_MINUS primary)
| primary
;
primary
: '(' expr ')' -> expr
| NUMBER
| IDENTIFIER
| STRING
;
NUMBER
: '0'..'9'+
;
STRING
: '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
;
fragment
ESC_SEQ
: '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
;
IDENTIFIER
: ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
;
NL
: 'r'? '\n'
;
WS
: ( ' '
| '\t'
) {$channel=HIDDEN;}
;
COMMENT
: '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
| '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
;
tree grammar StoneToJs;
options {
output=template;
tokenVocab=Stone;
ASTLabelType=CommonTree;
}
@header {
import java.util.Set;
}
program[Set vars]
: s+=statement*
{
String text = "";
for (int i = 0; i < $s.size(); i++) {
Object t = $s.get(i);
if (i == $s.size() - 1) {
text += "return ";
}
text += t.toString();
}
$st=%program(vars={vars}, text={text});
}
;
statement
: ^('if' expr thenBlock=block elseBlock=block?) -> if(cond={$expr.text}, thenBlock={$thenBlock.st}, elseBlock={$elseBlock.st})
| ^('while' expr block) -> while(cond={$expr.text}, block={$block.st})
| ^(SIMPLE simple NL) -> simple(text={$simple.st})
;
block
: ^(BLOCK s+=statement*)
{
String text = "";
for (Object t: $s) {
text += t.toString();
}
$st=%{text};
}
;
simple
: expr { $st = %{$expr.text}; }
| assign { $st = $assign.st; }
;
assign
: ^('=' IDENTIFIER simple) -> assign(id={$IDENTIFIER.text}, expr={$simple.st})
;
expr
: ^('==' expr expr)
| ^('>' expr expr)
| ^('<' expr expr)
| ^('+' expr expr)
| ^('-' expr expr)
| ^('*' expr expr)
| ^('/' expr expr)
| ^('%' expr expr)
| ^(UNARY_MINUS expr)
| NUMBER
| IDENTIFIER
| STRING
;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment