📄 compiler.g
字号:
tree grammar Compiler;options{ tokenVocab = CMinus; ASTLabelType = CommonTree; output = template;}@header{ import java.util.HashMap; import java.util.Vector; import java.util.Map; import java.util.List; import java.io.*; import org.antlr.stringtemplate.*; import org.antlr.stringtemplate.language.*;}@members{ CommonTreeNodeStream stream = (CommonTreeNodeStream)input; Boolean global=true; int next_power_of_two(int v){ //FIXME Currently arrays are set to 2^16, and this function isn't used double t=(double)v; double nv=Math.log(t)/Math.log(2); int res=(int)Math.ceil(nv); return (int)Math.pow(2,res); } StringTemplateGroup mtemplates;}program @init{ Main.symbols.reset_globals();}: ^(PROGRAM ^(VARIABLES (vars+=varDecl)*) ^(FUNCTIONS (funs+=funDecl)*) .) EOF -> wrapper(globals={$vars}, functions={$funs}) ;funDecl@init{ global=false; Main.symbols.enter_frame();}@after{ global=true; Main.symbols.exit_frame();}: ^(FUNCTION TYPE name=ID ^(PARAMATERS (params+=paramDecl)*) b+=block) -> function(name={$name}, params={$params}, content={$b});paramDecl : ^(VARPAR TYPE ID) {Main.symbols.declare_variable($ID.text,$TYPE.text, true);} -> param(name={Main.symbols.get_variable($ID.text).num}) | ^(ARRPAR TYPE name=ID) {Main.symbols.declare_array($name.text,$TYPE.text,65536);} -> array_param(name={Main.symbols.get_variable($ID.text).num});varDecl : ^(VARDEF TYPE name=ID) {Main.symbols.declare_variable($name.text,$TYPE.text,false);} -> {global}? declare_global(r={Main.symbols.get_variable($ID.text).num}) -> declare(r={Main.symbols.get_variable($ID.text).num}) | ^(ARRDEF TYPE name=ID size=INT) {Main.symbols.declare_array($name.text,$TYPE.text,65536);} //next_power_of_two(Integer.parseInt($size.text)) -> {global}? declare_global_array(ref={Main.symbols.get_variable($name.text).num}, size={Main.symbols.get_variable($name.text).length}) -> declare_array(ref={Main.symbols.get_variable($name.text).num}, size={Main.symbols.get_variable($name.text).length}) ; block@init{ Main.symbols.enter_block();}@after { Main.symbols.exit_block();} : ^(BLOCK ^(VARIABLES (vars+=varDecl)*) ^(STMTS (stmts+=stmt)*)) -> block(vars={$vars}, stmts={$stmts}) ; stmt : a=expr -> item(st={$a.st},s={"Start Expression"},e={"End Expression"}) | ^(RETURN expr) -> return(expr={$expr.st}, ref = {$expr.ref}) | ^(READ ID) -> read(ret={Main.symbols.get_variable($ID.text).num}, tmp1 = {Main.symbols.next_var()}, tmp2 = {Main.symbols.next_var()}, tmp3 = {Main.symbols.next_var()}, tmp4 = {Main.symbols.next_var()}, tmp5 = {Main.symbols.next_var()}) | ^(WRITE expr) -> write(expr= {$expr.st}, ref = {$expr.ref}, v1 = {Main.symbols.next_var()}, v2 = {Main.symbols.next_var()}) | WRITELN -> writeln(v = {Main.symbols.next_var()}) | BREAK -> break(lab={$whileStmt::breaked}) | ifStmt -> item(st={$ifStmt.st},s={"Start If Statement"},e={"End If Statement"}) | whileStmt -> item(st={$whileStmt.st},s={"Start While Statement"},e={"End While Statement"}) | block -> item(st={$block.st},s={"Start Block"},e={"End Block"}) | NOP -> ; whileStmtscope{ int breaked;}@init{ $whileStmt::breaked=Main.symbols.next_label();} : ^(WHILE expr stmt) -> while(expr={$expr.st}, ref={$expr.ref}, stmt={$stmt.st}, tmp1={Main.symbols.next_var()},start={Main.symbols.next_label()},block_begin={Main.symbols.next_label()},end={$whileStmt::breaked}) ;ifStmt : ^(IF ^(EXPR expr) t=stmt f=stmt) -> if(expr={$expr.st},ref={$expr.ref},true={$t.st},false={$f.st},tmp1={Main.symbols.next_var()},lab1={Main.symbols.next_label()},lab2={Main.symbols.next_label()},lab3={Main.symbols.next_label()}) ; expr returns [int ref]@init { $ref=Main.symbols.next_var();} : ^(('or'|'||') a=expr b=expr) -> or(ret={$ref},expr1={$a.st},expr2={$b.st},ref1={$a.ref},ref2={$b.ref},tmp1={Main.symbols.next_var()},tmp2={Main.symbols.next_var()},lab1={Main.symbols.next_label()},lab2={Main.symbols.next_label()},lab3={Main.symbols.next_label()},lab4={Main.symbols.next_label()}) | ^(('and'|'&&') a=expr b=expr) -> and(ret={$ref},expr1={$a.st},expr2={$b.st},ref1={$a.ref},ref2={$b.ref},tmp1={Main.symbols.next_var()},tmp2={Main.symbols.next_var()},lab1={Main.symbols.next_label()},lab2={Main.symbols.next_label()},lab3={Main.symbols.next_label()},lab4={Main.symbols.next_label()}) | ^('==' a=expr b=expr) -> comparison(type={"eq"}, expr1={$a.st}, expr2={$b.st},ret={$ref}, ref1={$a.ref}, ref2={$b.ref}) | ^(('!='|'<>') a=expr b=expr) -> comparison(type={"ne"}, expr1={$a.st}, expr2={$b.st},ret={$ref}, ref1={$a.ref}, ref2={$b.ref}) | ^('>' a=expr b=expr) -> comparison(type={"gt"}, expr1={$a.st}, expr2={$b.st},ret={$ref}, ref1={$a.ref}, ref2={$b.ref}) | ^('<' a=expr b=expr) -> comparison(type={"lt"}, expr1={$a.st}, expr2={$b.st},ret={$ref}, ref1={$a.ref}, ref2={$b.ref}) | ^('>=' a=expr b=expr) -> comparison(type={"ge"}, expr1={$a.st}, expr2={$b.st},ret={$ref}, ref1={$a.ref}, ref2={$b.ref}) | ^('<=' a=expr b=expr) -> comparison(type={"le"}, expr1={$a.st}, expr2={$b.st},ret={$ref}, ref1={$a.ref}, ref2={$b.ref}) | ^('+' a=expr b=expr) -> add(ea={$a.st},eb={$b.st},r={$ref}, v1={$a.ref}, v2={$b.ref}) | ^('-' a=expr b=expr) -> subtract(ea={$a.st},eb={$b.st},r={$ref}, v1={$a.ref}, v2={$b.ref}) | ^('*' a=expr b=expr) -> multiply(ea={$a.st},eb={$b.st},r={$ref}, v1={$a.ref}, v2={$b.ref}) | ^('/' a=expr b=expr) -> divide(ea={$a.st},eb={$b.st},r={$ref}, v1={$a.ref}, v2={$b.ref}) | ^(NEGATE a=expr) -> negate(expr={$a.st}, r={$ref}, val={$a.ref}) | ^(NOT a=expr) -> not(expr={$a.st}, ret={$ref}, ref={$a.ref}) | ^(NUM INT) -> create(r={$ref}, val={$INT}) | ^(VAR ID) {if(Main.symbols.get_variable($ID.text).read_only || Main.symbols.get_variable($ID.text).mode=="array") $ref=Main.symbols.get_variable($ID.text).num;} -> {(! Main.symbols.get_variable($ID.text).read_only) && Main.symbols.get_variable($ID.text).mode=="scalar"}? access(target={$ref},source={Main.symbols.get_variable($ID.text).num}) -> //| ^(PREFIX ^(VAR ID) ^(NUM INT)) -> {$value = Main.symbols.get_value($ID.text)+Integer.parseInt($INT.text); Main.symbols.set_value($ID.text,$value); } //| ^(POSTFIX ^(VAR ID) ^(NUM INT)) ->{$value = Main.symbols.get_value($ID.text); Main.symbols.set_value($ID.text,$value+Integer.parseInt($INT.text)); } | ^(INDEX name=ID i=expr) -> access_array(ret={$ref},name={Main.symbols.get_variable($name.text).num}, index_expr={$i.st}, index_ref={i.ref},tmp1={Main.symbols.next_var()},size={Main.symbols.get_variable($name.text).length}) | call[$ref] ->{$call.st} | ^(ASSIGN name=ID a=expr) -> var_assign(ret={$ref}, expr={$a.st}, var={Main.symbols.get_variable($name.text).num}, ref={$a.ref}) | ^(ASSIGN ^(INDEX name=ID i=expr) a=expr) -> array_assign(ret={$ref}, val_expr={$a.st},val_ref={$a.ref}, index_expr={$i.st}, index_ref={i.ref}, var={Main.symbols.get_variable($name.text).num}, size={Main.symbols.get_variable($name.text).values.length},tmp1={Main.symbols.next_var()});call[int ref] @init { int p_i=0; Function fcn; ArrayList prefs=new ArrayList(); ArrayList exprs=new ArrayList();} : ^(CALL ID {fcn=Main.symbols.get_function($ID.text);} ^(EXPRLIST (p=expr { StringTemplate code; if(((FunctionParam)fcn.params.get(p_i)).mode=="array"){ code=mtemplates.getInstanceOf("array_var"); }else{ code=mtemplates.getInstanceOf("int_var"); } code.setAttribute("num", $p.ref); prefs.add(code); exprs.add($p.st); p_i++; })*)) -> call(ret={$ref}, name={$ID.text}, param_expr={exprs}, params={prefs}) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -