tree grammar Interpreter; options{ tokenVocab = SampleC; ASTLabelType = CommonTree; } @header{ import java.util.List; import java.util.ArrayList; } @members{ CommonTreeNodeStream stream = (CommonTreeNodeStream)input; } program : ^(PROGRAM definition+ call) EOF ; definition : functionDefintion | ^(VARDEF INT i=IDENTIFIER) ; functionDefintion : ^(FUNC INT i=IDENTIFIER .*) ; compoundStatement @init{ Engine.symtab.enterBlock(); } @after{ Engine.symtab.exitBlock(); } : ^(BLOCK declarations statements) ; declarations : declaration* ; declaration : ^(VARDEF INT i=IDENTIFIER { Engine.symtab.declareLocalVariable($i.text, "int"); } ) ; statements : statement* ; statement @init{ try{ if((! $call::can_run) || $whileStmt::breaked || $whileStmt::continued){ matchAny(input); return null; } }catch(java.util.EmptyStackException ignore){} CommonTree node=(CommonTree)$statement.start; System.out.println(node.toStringTree()); } : expression | ^(EXPR expression CLEAR) | NOP | CLEAR | BREAK { $whileStmt::breaked = true; } | CONTINUE { $whileStmt::continued = true; } | RETURN { $call::can_run = false; } | ^(RETURN e=expression) { $call::return_val = $e.value; $call::can_run = false; } | c=compoundStatement | ifStmt | whileStmt ; whileStmt scope{ Boolean breaked; Boolean continued; } @after{ CommonTree stmtNode=(CommonTree)$whileStmt.start.getChild(1); CommonTree exprNode=(CommonTree)$whileStmt.start.getChild(0); int test; $whileStmt::breaked=false; $whileStmt::continued=false; while($whileStmt::breaked==false){ stream.push(stream.getNodeIndex(exprNode)); test=expression().value; stream.pop(); if (test==0) break; stream.push(stream.getNodeIndex(stmtNode)); statement(); stream.pop(); } } : ^(WHILE . .) ; ifStmt @after{ CommonTree stmtNode; if ($v.value!=0){ stmtNode = (CommonTree)$ifStmt.start.getChild(1); }else{ stmtNode = (CommonTree)$ifStmt.start.getChild(2); } stream.push(stream.getNodeIndex(stmtNode)); statement(); stream.pop(); } : ^(IF v=expression . .) ; expression returns [int value] @init { CommonTree node=(CommonTree)$expression.start; // System.out.println(node.toStringTree()); } : ^(ALU_EQ e1=expression e2=expression) { $value = ($e1.value == $e2.value)? 1 : 0; } | ^(ALU_NE e1=expression e2=expression) { $value = ($e1.value != $e2.value)? 1 : 0; } | ^(ALU_GT e1=expression e2=expression) { $value = ($e1.value > $e2.value)? 1 : 0; } | ^(ALU_LT e1=expression e2=expression) { $value = ($e1.value < $e2.value)? 1 : 0; } | ^(ALU_LE e1=expression e2=expression) { $value = ($e1.value <= $e2.value)? 1 : 0; } | ^(ALU_GE e1=expression e2=expression) { $value = ($e1.value >= $e2.value)? 1 : 0; } | ^(ALU_ADD e1=expression e2=expression) { $value = $e1.value + $e2.value; } | ^(ALU_SUB e1=expression e2=expression) { $value = $e1.value - $e2.value; } | ^(ALU_MUL e1=expression e2=expression) { $value = $e1.value * $e2.value; } | ^(ALU_DIV e1=expression e2=expression) { $value = $e1.value / $e2.value; } | ^(ALU_AND e1=expression e2=expression) { $value = $e1.value & $e2.value; } | ^(ALU_OR e1=expression e2=expression) { $value = $e1.value | $e2.value; } | ^(ALU_XOR e1=expression e2=expression) { $value = $e1.value ^ $e2.value; } | ^(NOT e1=expression) { $value = ($e1.value!=0)? 0 : 1; } | ^(NEGATE e1=expression) { $value = -$e1.value; } | ^(ASSIGN i=IDENTIFIER e=expression) { Engine.symtab.setValue($i.text, $e.value); $value = $e.value; System.out.println("set " + $i.text + "=" + $e.value); } | ^(PREFIX i=IDENTIFIER PP) { int v = Engine.symtab.getValue($i.text); Engine.symtab.setValue($i.text, ++v); $value = v; } | ^(PREFIX i=IDENTIFIER MM) { int v = Engine.symtab.getValue($i.text); Engine.symtab.setValue($i.text, --v); $value = v; } | call | i=IDENTIFIER { $value = Engine.symtab.getValue($i.text); } | c=CONSTANT { $value = Integer.parseInt($c.text); } ; call returns [int value] scope{ int return_val; Boolean can_run; } @init { int argCnt=0; List parmList; String parm; CommonTree blockNode; $call::can_run=true; } : ^(CALL i=IDENTIFIER { argCnt = 0; parmList = Engine.symtab.getFunctionParmList($i.text); blockNode = Engine.symtab.getFunctionBlock($i.text); Engine.symtab.enterFunction($i.text); System.out.println("enter " + $i.text); } ^(ARG (e=expression { parm = (String)parmList.get(argCnt++); Engine.symtab.declareParameter(parm, "int"); Engine.symtab.setValue(parm, $e.value); System.out.println("arg " + parm + "=" + $e.value); } )*) { stream.push(stream.getNodeIndex(blockNode)); compoundStatement(); stream.pop(); $value = $call::return_val; Engine.symtab.exitFunction(); System.out.println("exit " + $i.text + " return=" + $value); } ) ;