Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial compiler version

  • Loading branch information...
commit 9c93709372823c72f4dfb775f0bcc8944eb68030 0 parents
@markflorisson authored
7 .classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="lib" path="antlr-3.3-complete.jar"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
17 .project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>SELMA</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
BIN  antlr-3.3-complete.jar
Binary file not shown
31 comm_dec_ass_print.SELMA
@@ -0,0 +1,31 @@
+ //Comment Testen
+/* dit is
+een comment
+met meerdere
+regels
+*/
+begin //start program
+2*3;
+ //compound expression
+var i: integer; //single var int decaration
+
+5*8;
+2*3*4;
+5*i;
+5>=6;
+if true; then 5; fi;
+if false; then 8; else 3; fi;
+i := i := 5; //single assignment
+print(i); //single print
+var x,y: boolean; //double var bool declaration
+var j: integer; //single var int declaration
+j := i := j := 7; //double int assignment
+print(i,j); //double print
+const a: character = 'g'; //single const declaration
+//const b: integer = 'l'; //single const declaration
+const c: integer = 1; //single const declaration
+j := i := 5*c; //double assignment & arith
+j := i := 5;//true;
+j := j := i;
+print(i,j,c); //triple print
+end. //end program
68 g-files/Copy of SELMACode.stg
@@ -0,0 +1,68 @@
+//SELMA string template
+
+group SELMA;
+
+program(instructions) ::= <<
+; TAM assembler code generated by SELMACompiler
+; comments at 50 whitespaces
+ ; start of program
+<instructions>
+HALT ; end of program
+>>
+
+compound(instructions) ::= <<
+ ; start compound
+<instructions; separator="\n">
+ ; end compound
+>>
+
+
+//Calculations
+Expr(e1,op)::=<<
+<e1> ; e1 for operation <op>
+CALL <op> ; operation <op>
+>>
+
+biExpr(e1,e2,op)::=<<
+<e1> ; e1 for operation <op>
+<e2> ; e2 for operation <op>
+CALL <op> ; operation <op>
+>>
+
+//Declare
+declareConst(id,val,type,addr)::=<<
+LOADL <val> ; declare var <id>: <type> = <val> @ <addr>[SB]
+>>
+
+declareVar(id,type,addr)::=<<
+PUSH 1 ; declare var <id>: <type> @ <addr>[SB]
+>>
+
+//Load
+loadNum(val)::=<<
+LOADL <val> ; loadNum <val>
+>>
+
+loadVal(id,addr)::=<<
+LOAD(1) <addr>[SB] ; loadVal <id> from <addr>[SB]
+>>
+
+//Assign
+assign(id,type,addr,e1)::=<<
+<e1> ; e1 right hand for assignment
+STORE(1) <addr>[SB] ; assign e1 to <id>: <type> @ <addr>[SB]
+>>
+
+//conditionals
+if(ec1,ec2,ec3)::=<<
+<ec1> ; e1 right hand for assignment
+<ec2> ; e2 right hand for assignment
+<ec3> ; e3 right hand for assignment
+hier hoort een if
+>>
+
+while(ec1,ec2)::=<<
+//<ec1> ; e1 right hand for assignment
+//<ec2> ; e2 right hand for assignment
+//hier hoort een while
+>>
280 g-files/SELMA.g
@@ -0,0 +1,280 @@
+grammar SELMA;
+
+
+options {
+ k=1; // LL(1) - do not use LL(*)
+ language=Java; // target language is Java (= default)
+ output=AST; // build an AST
+}
+
+tokens {
+ COLON = ':';
+ SEMICOLON = ';';
+ LPAREN = '(';
+ RPAREN = ')';
+ LCURLY = '{';
+ RCURLY = '}';
+ COMMA = ',';
+ EQ = '=';
+ APOSTROPHE = '\'';
+
+ //arethemithic
+ NOT = '!';
+
+ MULT = '*';
+ DIV = '/';
+ MOD = '%';
+
+ PLUS = '+';
+ MINUS = '-';
+
+ RELS = '<';
+ RELSE = '<=';
+ RELGE = '>=';
+ RELG = '>';
+ RELE = '==';
+ RELNE = '<>';
+
+ AND = '&&';
+
+ OR = '||';
+
+ //expressions
+ BECOMES = ':=';
+ PRINT = 'print';
+ READ = 'read';
+
+ //declaration
+ VAR = 'var';
+ CONST = 'const';
+
+ //types
+ INT = 'integer';
+ BOOL = 'boolean';
+ CHAR = 'character';
+
+ // keywords
+ BEGIN = 'begin';
+ END = 'end.';
+
+ IF = 'if';
+ THEN = 'then';
+ ELSE = 'else';
+ FI = 'fi';
+
+ WHILE = 'while';
+ DO = 'do';
+ OD = 'od';
+
+ PROC = 'procedure';
+ FUNC = 'function';
+
+ UMIN;
+ UPLUS;
+
+ COMPOUND;
+
+}
+
+
+@header {
+ package SELMA;
+}
+
+@lexer::header {
+ package SELMA;
+}
+
+// Parser rules
+
+program
+ : BEGIN compoundexpression END EOF
+ -> ^(BEGIN compoundexpression END)
+ ;
+
+compoundexpression
+ : cmp -> ^(COMPOUND cmp)
+ ;
+
+cmp
+ : ((declaration SEMICOLON!)* expression SEMICOLON!)+
+ ;
+
+//declaration
+
+declaration
+// : VAR^ identifier (COMMA! identifier)* COLON! type
+// | CONST^ identifier (COMMA! identifier)* COLON! type EQ! unsignedConstant
+ : VAR identifier (COMMA identifier)* COLON type
+ -> ^(VAR type identifier)+
+ | CONST identifier (COMMA identifier)* COLON type EQ unsignedConstant
+ -> ^(CONST type unsignedConstant identifier)+
+ ;
+
+type
+ : INT
+ | BOOL
+ | CHAR
+ ;
+
+//expression
+// note:
+// - arithmetic can be "invisible" due to all the *-s that's why it is nested
+// - assignment can be "invisible" due to the ? that's why it can also be only a identifier
+
+expression
+ : expr_assignment
+ ;
+
+expr_assignment
+ : expr_arithmetic (BECOMES^ expression)?
+ ;
+
+expr_arithmetic
+ : expr_al1
+ ;
+
+ expr_al1 //expression arithmetic level 1
+ : expr_al2 (OR^ expr_al2)*
+ ;
+
+ expr_al2
+ : expr_al3 (AND^ expr_al3)*
+ ;
+
+ expr_al3
+ : expr_al4 ((RELS|RELSE|RELG|RELGE|RELE|RELNE)^ expr_al4)*
+ ;
+
+ expr_al4
+ : expr_al5 ((PLUS|MINUS)^ expr_al5)*
+ ;
+
+ expr_al5
+ : expr_al6 ((MULT|DIV|MOD)^ expr_al6)*
+ ;
+
+ expr_al6
+// : (PLUS|MINUS|NOT)? expr_al7
+ : PLUS expr_al7
+ -> UPLUS expr_al7
+ | MINUS expr_al7
+ -> UMIN expr_al7
+ | NOT expr_al7
+ | expr_al7
+ ;
+
+ expr_al7
+ : unsignedConstant
+ | identifier
+// | expr_assignment //can be identifier
+ | expr_read
+ | expr_print
+ | expr_if
+ | expr_while
+ | expr_closedcompound
+ | expr_closed
+ ;
+
+expr_read
+ : READ^ LPAREN! identifier (COMMA! identifier)* RPAREN!
+ ;
+
+expr_print
+ : PRINT^ LPAREN! expression (COMMA! expression)* RPAREN!
+ ;
+
+expr_if
+ : IF^ compoundexpression THEN compoundexpression (ELSE compoundexpression)? FI!
+ ;
+
+expr_while
+ : WHILE^ compoundexpression DO compoundexpression OD
+ ;
+
+expr_closedcompound
+ : LCURLY compoundexpression RCURLY
+ ;
+
+expr_closed
+ : LPAREN! expression RPAREN!
+ ;
+
+unsignedConstant
+ : boolval
+ | charval
+ | intval
+ ;
+
+intval
+ : NUMBER
+ ;
+
+boolval
+ : BOOLEAN
+ ;
+
+charval
+ : CHARV
+ ;
+
+identifier
+ : ID
+ ;
+
+CHARV
+ : APOSTROPHE LETTER APOSTROPHE
+ ;
+
+BOOLEAN
+ : TRUE
+ | FALSE
+ ;
+
+ID
+ : LETTER (LETTER | DIGIT)*
+ ;
+
+NUMBER
+ : DIGIT+
+ ;
+
+COMMENT
+ : '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
+ | '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
+ ;
+WS
+ : ( ' '
+ | '\t'
+ | '\r'
+ | '\n'
+ ) {$channel=HIDDEN;}
+ ;
+
+fragment DIGIT
+ : ('0'..'9')
+ ;
+
+fragment LOWER
+ : ('a'..'z')
+ ;
+
+fragment UPPER
+ : ('A'..'Z')
+ ;
+
+fragment LETTER
+ : LOWER
+ | UPPER
+ ;
+
+fragment TRUE
+ : 'true'
+ ;
+
+fragment FALSE
+ : 'false'
+ ;
+
+
+//EOF
299 g-files/SELMAChecker.g
@@ -0,0 +1,299 @@
+tree grammar SELMAChecker;
+
+options {
+ tokenVocab=SELMA;
+ ASTLabelType=SELMATree;
+ output=AST;
+}
+
+@header {
+ package SELMA;
+ import SELMA.SELMATree.SR_Type;
+ import SELMA.SELMATree.SR_Kind;
+}
+
+// Alter code generation so catch-clauses get replaced with this action.
+@rulecatch {
+ catch (RecognitionException re) {
+ throw re;
+ }
+}
+
+@members {
+ public SymbolTable<CheckerEntry> st = new SymbolTable<CheckerEntry>();
+}
+
+program
+ : ^(BEGIN {st.openScope();} compoundexpression {st.closeScope();} END)
+ ;
+
+compoundexpression //do not open and close scope here (IF/WHILE)
+ : ^(node=COMPOUND (declaration|expression)+)
+ {
+ SELMATree e1 = (SELMATree)node.getChild(node.getChildCount()-1);
+ if (e1.SR_type==SR_Type.VOID) {
+ $node.SR_type=SR_Type.VOID;
+ $node.SR_kind=null;
+ } else {
+ $node.SR_type=e1.SR_type;
+ $node.SR_kind=e1.SR_kind;
+ }
+ }
+ ;
+
+declaration
+ : ^(node=VAR type id=ID)
+ {
+ int type = node.getChild(0).getType();
+
+ switch (type){
+ case INT:
+ st.enter($id,new CheckerEntry(SR_Type.INT,SR_Kind.VAR));
+ break;
+ case BOOL:
+ st.enter($id,new CheckerEntry(SR_Type.BOOL,SR_Kind.VAR));
+ break;
+ case CHAR:
+ st.enter($id,new CheckerEntry(SR_Type.CHAR,SR_Kind.VAR));
+ break;
+ }
+ }
+ | ^(node=CONST type val id=ID)
+ {
+ int type = node.getChild(0).getType();
+ int val = node.getChild(1).getType();
+
+ switch (type){
+ case INT:
+ if (val!=NUMBER) throw new SELMAException(id,"Expecting int-value");
+ st.enter($id,new CheckerEntry(SR_Type.INT,SR_Kind.CONST));
+ break;
+ case BOOL:
+ if (val!=BOOLEAN) throw new SELMAException(id,"Expecting bool-value");
+ st.enter($id,new CheckerEntry(SR_Type.BOOL,SR_Kind.CONST));
+ break;
+ case CHAR:
+ if (val!=CHARV) throw new SELMAException(id,"Expecting char-value");
+ st.enter($id,new CheckerEntry(SR_Type.CHAR,SR_Kind.CONST));
+ break;
+ }
+ }
+ ;
+
+type
+ : INT
+ | BOOL
+ | CHAR
+ ;
+
+val
+ : NUMBER
+ | CHARV
+ | BOOLEAN
+ ;
+
+expression
+ : ^(node=(MULT|DIV|MOD|PLUS|MINUS) expression expression)
+ {
+ SELMATree e1 = (SELMATree)node.getChild(0);
+ SELMATree e2 = (SELMATree)node.getChild(1);
+
+ if (e1.SR_type!=SR_Type.INT || e2.SR_type!=SR_Type.INT)
+ throw new SELMAException($node,"Wrong type must be int");
+ $node.SR_type=SR_Type.INT;
+
+ if (e1.SR_kind==SR_Kind.CONST && e2.SR_kind==SR_Kind.CONST)
+ $node.SR_kind=SR_Kind.CONST;
+ else
+ $node.SR_kind=SR_Kind.VAR;
+ }
+
+ | ^(node=(RELS|RELSE|RELG|RELGE) expression expression)
+ {
+ SELMATree e1 = (SELMATree)node.getChild(0);
+ SELMATree e2 = (SELMATree)node.getChild(1);
+
+ if (e1.SR_type!=SR_Type.INT || e2.SR_type!=SR_Type.INT)
+ throw new SELMAException($node,"Wrong type must be int");
+ $node.SR_type=SR_Type.BOOL;
+
+ if (e1.SR_kind==SR_Kind.CONST && e2.SR_kind==SR_Kind.CONST)
+ $node.SR_kind=SR_Kind.CONST;
+ else
+ $node.SR_kind=SR_Kind.VAR;
+ }
+
+ | ^(node=(OR|AND) expression expression)
+ {
+ SELMATree e1 = (SELMATree)node.getChild(0);
+ SELMATree e2 = (SELMATree)node.getChild(1);
+
+ if (e1.SR_type!=SR_Type.BOOL || e2.SR_type!=SR_Type.BOOL)
+ throw new SELMAException($node,"Wrong type must be bool");
+ $node.SR_type=SR_Type.BOOL;
+
+ if (e1.SR_kind==SR_Kind.CONST && e2.SR_kind==SR_Kind.CONST)
+ $node.SR_kind=SR_Kind.CONST;
+ else
+ $node.SR_kind=SR_Kind.VAR;
+ }
+
+ | ^(node=(RELE|RELNE) expression expression)
+ {
+ SELMATree e1 = (SELMATree)node.getChild(0);
+ SELMATree e2 = (SELMATree)node.getChild(1);
+
+ if (e1.SR_type!=e2.SR_type||e1.SR_type==SR_Type.VOID)
+ throw new SELMAException($node,"Types must match and can't be void");
+ $node.SR_type=SR_Type.BOOL;
+
+ if (e1.SR_kind==SR_Kind.CONST && e2.SR_kind==SR_Kind.CONST)
+ $node.SR_kind=SR_Kind.CONST;
+ else
+ $node.SR_kind=SR_Kind.VAR;
+ }
+
+ | ^(node=(UPLUS|UMIN) expression)
+ {
+ SELMATree e1 = (SELMATree)node.getChild(0);
+
+ if (e1.SR_type!=SR_Type.INT)
+ throw new SELMAException($node,"Wrong type must be int");
+ $node.SR_type=SR_Type.INT;
+
+ $node.SR_kind=e1.SR_kind;
+ }
+
+ | ^(node=(NOT) expression)
+ {
+ SELMATree e1 = (SELMATree)node.getChild(0);
+
+ if (e1.SR_type!=SR_Type.BOOL)
+ throw new SELMAException($node,"Wrong type must be bool");
+ $node.SR_type=SR_Type.BOOL;
+
+ $node.SR_kind=e1.SR_kind;
+ }
+
+ | ^(node=IF {st.openScope();} compoundexpression
+ THEN {st.openScope();} compoundexpression {st.closeScope();}
+ (ELSE {st.openScope();} compoundexpression {st.closeScope();})?
+ {st.closeScope();})
+ {
+ SELMATree e1 = (SELMATree)node.getChild(0);
+ SELMATree e2 = (SELMATree)node.getChild(2);
+ SELMATree e3 = (SELMATree)node.getChild(4);
+
+ if (e1.SR_type!=SR_Type.BOOL)
+ throw new SELMAException(e1,"Expression must be boolean");
+
+ if (e3==null) { //no else
+ $node.SR_type=SR_Type.VOID;
+ $node.SR_kind=null;
+ } else { // there is a else
+ if (e2.SR_type==e3.SR_type) {
+ $node.SR_type=e3.SR_type;
+ if (e2.SR_kind==SR_Kind.CONST && e3.SR_kind==SR_Kind.CONST)
+ $node.SR_kind=SR_Kind.CONST;
+ else
+ $node.SR_kind=SR_Kind.VAR;
+ } else {
+ $node.SR_type=SR_Type.VOID;
+ $node.SR_kind=null;
+ }
+ }
+ }
+
+ | ^(node=WHILE {st.openScope();}compoundexpression
+ DO {st.openScope();} compoundexpression {st.closeScope();}
+ OD{st.closeScope();})
+ {
+ SELMATree e1 = (SELMATree)node.getChild(0);
+ SELMATree e2 = (SELMATree)node.getChild(2);
+
+ if (e1.SR_type!=SR_Type.BOOL)
+ throw new SELMAException(e1,"Expression must be boolean");
+
+ $node.SR_type=SR_Type.VOID;
+ $node.SR_kind=null;
+
+ }
+
+ | ^(node=READ (id=ID
+ {
+ if (st.retrieve($id).kind!=SR_Kind.VAR)
+ throw new SELMAException($id,"Must be a variable");
+ })+
+ {
+ if ($node.getChildCount()==1){
+ $node.SR_type=((SELMATree)node.getChild(0)).SR_type;
+ $node.SR_kind=SR_Kind.VAR;
+ } else {
+ $node.SR_type=SR_Type.VOID;
+ $node.SR_kind=null;
+ }
+ }
+ )
+
+ | ^(node=PRINT expression+
+ {
+ for (int i=0; i<((SELMATree)node).getChildCount(); i++){
+ if (((SELMATree)node.getChild(i)).SR_type==SR_Type.VOID)
+ throw new SELMAException($node,"Can not be of type void");
+ }
+ if ($node.getChildCount()==1){
+ $node.SR_type=((SELMATree)node.getChild(0)).SR_type;
+ $node.SR_kind=SR_Kind.VAR;
+ } else {
+ $node.SR_type=SR_Type.VOID;
+ $node.SR_kind=null;
+ }
+ })
+
+ | ^(node=BECOMES expression expression)
+ {
+ SELMATree e1 = (SELMATree)node.getChild(0);
+ SELMATree e2 = (SELMATree)node.getChild(1);
+ if (e1.getType()!=ID)
+ throw new SELMAException(e1,"Must be a identifier");
+
+ CheckerEntry ident = st.retrieve(e1);
+
+ if (ident.kind!=SR_Kind.VAR)
+ throw new SELMAException(e1,"Must be a variable");
+ if (ident.type!=e2.SR_type)
+ throw new SELMAException(e1,"Right side must be the same type "+ident.type+"/"+e2.SR_type);
+
+ $node.SR_type=ident.type;
+ $node.SR_kind=SR_Kind.VAR;
+ }
+
+ | LCURLY {st.openScope();} compoundexpression {st.closeScope();} RCURLY
+
+ | node=NUMBER
+ {
+ $node.SR_type=SR_Type.INT;
+ $node.SR_kind=SR_Kind.CONST;
+ }
+
+ | node=BOOLEAN
+ {
+ $node.SR_type=SR_Type.BOOL;
+ $node.SR_kind=SR_Kind.CONST;
+ }
+
+ | node=LETTER
+ {
+ $node.SR_type=SR_Type.CHAR;
+ $node.SR_kind=SR_Kind.CONST;
+ }
+
+ | node=ID
+ {
+ CheckerEntry entry = st.retrieve($node);
+ $node.SR_type=entry.type;
+ $node.SR_kind=entry.kind;
+ }
+ ;
+
+
73 g-files/SELMACode.stg
@@ -0,0 +1,73 @@
+//SELMA string template
+
+group SELMA;
+
+program(instructions) ::= <<
+; TAM assembler code generated by SELMACompiler
+; comments at 50 whitespaces
+ ; start of program
+<instructions>
+HALT
+ ; end of program
+>>
+
+compound(instructions) ::= <<
+ ; start compound
+<instructions; separator="\n">
+ ; end compound
+>>
+
+
+//Calculations
+Expr(e1,op)::=<<
+<e1> ; e1 for operation <op>
+CALL <op> ; single operation <op>
+>>
+
+biExpr(e1,e2,op)::=<<
+<e1> ; e1 for operation <op>
+<e2> ; e2 for operation <op>
+CALL <op> ; binary operation <op>
+>>
+
+//Declare
+declareConst(id,val,type,addr)::=<<
+ ; declare var <id>: <type> = <val> @ <addr>[SB]
+LOADL <val>
+>>
+
+declareVar(id,type,addr)::=<<
+ ; declare var <id>: <type> @ <addr>[SB]
+PUSH 1
+>>
+
+//Load
+loadNum(val)::=<<
+ ; loadNum <val>
+LOADL <val>
+>>
+
+loadVal(id,addr)::=<<
+ ; loadVal <id> from <addr>[SB]
+LOAD(1) <addr>[SB]
+>>
+
+//Assign
+assign(id,type,addr,e1)::=<<
+<e1> ; e1 right hand for assignment
+STORE(1) <addr>[SB] ; assign e1 to <id>: <type> @ <addr>[SB]
+>>
+
+//conditionals
+if(ec1,ec2,ec3)::=<<
+<ec1> ; e1 condition
+<ec2> ; e2 if true expression
+<ec3> ; e3 if false expression
+hier hoort een if
+>>
+
+while(ec1,ec2)::=<<
+<ec1> ; e1 while condition
+<ec2> ; e2 expression to evaluate
+hier hoort een while
+>>
147 g-files/SELMACompiler.g
@@ -0,0 +1,147 @@
+tree grammar SELMACompiler;
+
+options {
+ language = Java;
+ output = template;
+ tokenVocab = SELMA;
+ ASTLabelType = SELMATree;
+}
+
+@header {
+ package SELMA;
+ import SELMA.SELMATree.SR_Type;
+ import SELMA.SELMATree.SR_Kind;
+}
+
+@rulecatch {
+ catch (RecognitionException re) {
+ throw re;
+ }
+}
+
+@members {
+ public SymbolTable<CompilerEntry> st = new SymbolTable<CompilerEntry>();
+}
+
+program
+ : ^(BEGIN {st.openScope();} compoundexpression {st.closeScope();} END)
+ -> program( instructions={$compoundexpression.st} )
+ ;
+
+compoundexpression
+ : ^(node=COMPOUND (s+=declaration | s+=expression)+)
+ -> compound(instructions={$s})
+ ;
+
+declaration
+ : ^(node=VAR INT id=ID)
+ {st.enter($id,new CompilerEntry(SR_Type.INT,SR_Kind.VAR,st.nextAddr())); }
+ -> declareVar(id={$id.text},type={"INT"},addr={st.nextAddr()-1})
+
+ | ^(node=VAR BOOL id=ID)
+ {st.enter($id,new CompilerEntry(SR_Type.BOOL,SR_Kind.VAR,st.nextAddr())); }
+ -> declareVar(id={$id.text},type={"BOOL"},addr={st.nextAddr()-1})
+
+ | ^(node=VAR CHAR id=ID)
+ {st.enter($id,new CompilerEntry(SR_Type.CHAR,SR_Kind.VAR,st.nextAddr())); }
+ -> declareVar(id={$id.text},type={"CHAR"},addr={st.nextAddr()-1})
+
+ // store the const at a address? LOAD Or just copy LOADL?
+ | ^(node=CONST INT val=NUMBER (id=ID)+)
+ {st.enter($id,new CompilerEntry(SR_Type.INT,SR_Kind.CONST,st.nextAddr())); }
+ -> declareConst(id={$id.text},value={$val.text},type={"INT"},addr={st.nextAddr()-1})
+
+ | ^(node=CONST BOOL BOOLEAN (id=ID)+)
+ {st.enter($id,new CompilerEntry(SR_Type.BOOL,SR_Kind.CONST,st.nextAddr()-1)); }
+ -> declareConst(id={$id.text},value={($val.text.equals("true"))?"1":"0"},type={"BOOL"},addr={st.nextAddr()})
+
+ | ^(node=CONST CHAR CHARV (id=ID)+)
+ {st.enter($id,new CompilerEntry(SR_Type.CHAR,SR_Kind.CONST,st.nextAddr())); }
+ -> declareConst(id={$id.text},value={Character.getNumericValue($val.text.charAt(1))},type={"CHAR"},addr={st.nextAddr()-1})
+ ;
+
+expression
+//double arg expression
+ : ^(MULT e1=expression e2=expression)
+ -> biExpr(e1={$e1.st},e2={$e2.st},op={"mult"})
+
+ | ^(DIV e1=expression e2=expression)
+ -> biExpr(e1={$e1.st},e2={$e2.st},op={"div"})
+
+ | ^(MOD e1=expression e2=expression)
+ -> biExpr(e1={$e1.st},e2={$e2.st},op={"mod"})
+
+ | ^(PLUS e1=expression e2=expression)
+ -> biExpr(e1={$e1.st},e2={$e2.st},op={"add"})
+
+ | ^(MINUS e1=expression e2=expression)
+ -> biExpr(e1={$e1.st},e2={$e2.st},op={"sub"})
+
+ | ^(RELS e1=expression e2=expression)
+ -> biExpr(e1={$e1.st},e2={$e2.st},op={"lt"})
+
+ | ^(RELSE e1=expression e2=expression)
+ -> biExpr(e1={$e1.st},e2={$e2.st},op={"le"})
+
+ | ^(RELG e1=expression e2=expression)
+ -> biExpr(e1={$e1.st},e2={$e2.st},op={"gt"})
+
+ | ^(RELGE e1=expression e2=expression)
+ -> biExpr(e1={$e1.st},e2={$e2.st},op={"ge"})
+
+ | ^(OR e1=expression e2=expression)
+ -> biExpr(e1={$e1.st},e2={$e2.st},op={"or"})
+
+ | ^(AND e1=expression e2=expression)
+ -> biExpr(e1={$e1.st},e2={$e2.st},op={"and"})
+
+ | ^(RELE e1=expression e2=expression)
+ -> biExpr(e1={$e1.st},e2={$e2.st},op={"eq"})
+
+ | ^(RELNE e1=expression e2=expression)
+ -> biExpr(e1={$e1.st},e2={$e2.st},op={"neq"})
+
+//single arg expression
+ | ^(UPLUS e1=expression)
+ {$st=$e1.st;}
+
+ | ^(UMIN e1=expression)
+ -> Expr(e1={$e1.st},op={"neg"})
+
+ | ^(NOT e1=expression)
+ -> Expr(e1={$e1.st},op={"not"})
+
+//CONDITIONAL
+ | ^(IF ec1=compoundexpression THEN ec2=compoundexpression (ELSE ec3=compoundexpression)?)
+ -> if(ec1={$ec1.st},ec2={$ec2.st},ec3={$ec3.st})
+ | ^(WHILE ec1=compoundexpression DO ec2=compoundexpression OD)
+ -> while(ec1={$ec1.st},ec2={$ec2.st})
+
+//IO
+ | ^(READ (id=ID)+)
+
+ | ^(PRINT expression+)
+
+//ASSIGN
+// | ^(BECOMES expression expression)
+ | ^(BECOMES node=ID e1=expression)
+ -> assign(id={$node.text},type={$node.type},addr={st.retrieve($node).addr},e1={$e1.st})
+
+//closedcompound
+ | LCURLY {st.openScope();} compoundexpression {st.closeScope();} RCURLY
+
+//VALUES
+ | node=NUMBER
+ -> loadNum(val={$node.text})
+
+ | node=BOOLEAN
+ -> loadNum(val={($node.type==TRUE)?1:0})
+
+ | node=LETTER
+ -> loadNum(val={Character.getNumericValue($node.text.charAt(1))})
+
+ | node=ID
+ -> loadVal(id={$node.text}, addr={st.retrieve($node).addr})
+ ;
+
+
BIN  jasmin.jar
Binary file not shown
20 simple.SELMA
@@ -0,0 +1,20 @@
+ //Comment Testen
+/* dit is
+een comment
+met meerdere
+regels
+*/
+begin //start program
+var i: integer; //single var int decaration
+2*3;
+i := 1;
+
+5*8;
+2*3*4;
+5*i;
+5>=6;
+while true; do 5; od;
+if true; then 5; else 6; fi;
+if false; then 7; fi;
+
+end. //end program
60 src/SELMA/CheckerEntry.java
@@ -0,0 +1,60 @@
+package SELMA;
+
+import SELMA.SELMATree.SR_Kind;
+import SELMA.SELMATree.SR_Type;
+
+public class CheckerEntry extends IdEntry {
+ public SR_Type type;
+ public SR_Kind kind;
+
+ public CheckerEntry(SR_Type type, SR_Kind kind) {
+ super();
+ this.type=type;
+ this.kind=kind;
+ }
+ public String toString() {
+ String s = "";
+ s += " [";
+
+ s+=level;
+
+ s+=",";
+
+ if (type == null)
+ s+="NULL";
+ else
+ switch (type){
+ case BOOL:
+ s+="bool";
+ break;
+ case INT:
+ s+="int";
+ break;
+ case CHAR:
+ s+="char";
+ break;
+ case VOID:
+ s+="void";
+ break;
+ }
+
+ s+=",";
+
+ if (kind == null)
+ s+="NULL";
+ else
+ switch (kind){
+ case VAR:
+ s+="var";
+ break;
+ case CONST:
+ s+="const";
+ break;
+ }
+
+ s+="]";
+
+ return s;
+ }
+
+}
13 src/SELMA/CompilerEntry.java
@@ -0,0 +1,13 @@
+package SELMA;
+
+import SELMA.SELMATree.SR_Kind;
+import SELMA.SELMATree.SR_Type;
+
+public class CompilerEntry extends CheckerEntry {
+ public int addr;
+ public CompilerEntry(SR_Type type, SR_Kind kind, int addr) {
+ super(type, kind);
+ this.addr=addr;
+ }
+
+}
10 src/SELMA/IdEntry.java
@@ -0,0 +1,10 @@
+package SELMA;
+
+public class IdEntry {
+ public int level = -1;
+ public IdEntry(){
+ }
+ public String toString() {
+ return " ["+level+"]";
+ }
+}
111 src/SELMA/SELMA.java
@@ -0,0 +1,111 @@
+package SELMA;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+
+import org.antlr.runtime.*; // ANTLR runtime library
+import org.antlr.runtime.tree.*; // For ANTLR's Tree classes
+import org.antlr.stringtemplate.*; // For the DOTTreeGenerator
+
+
+
+public class SELMA {
+ private static boolean opt_ast = false,
+ opt_dot = false,
+ opt_no_checker = false,
+ opt_code_generator = false;
+
+ public static void parseOptions(String[] args) {
+ for (int i=0; i<args.length; i++) {
+ if (args[i].equals("-ast"))
+ opt_ast = true;
+ else if (args[i].equals("-dot"))
+ opt_dot = true;
+ else if (args[i].equals("-code_generator")){
+ opt_code_generator = true;
+ }
+ else if (args[i].equals("-no_checker"))
+ opt_no_checker = true;
+ else {
+ System.err.println("error: unknown option '" + args[i] + "'");
+ System.err.println("valid options: -ast -dot " +
+ "-no_checker");
+ System.exit(1);
+ }
+ }
+ }
+
+ public static void main(String[] args) throws FileNotFoundException {
+ System.setIn(new FileInputStream("simple.SELMA"));
+ parseOptions(args);
+ CommonTree tree;
+ try {
+ SELMALexer lexer = new SELMALexer(new ANTLRInputStream(System.in));
+ CommonTokenStream tokens = new CommonTokenStream(lexer);
+
+ if (! opt_no_checker) { // check the AST
+ SELMAParser parser = new SELMAParser(tokens);
+ parser.setTreeAdaptor(new SELMATreeAdaptor());
+
+ SELMAParser.program_return result = parser.program();
+ tree = (SELMATree) result.getTree();
+
+ TreeNodeStream nodes = new CommonTreeNodeStream(tree);
+ SELMAChecker checker = new SELMAChecker(nodes);
+ checker.setTreeAdaptor(new SELMATreeAdaptor());
+ checker.program();
+ } else {
+ SELMAParser parser = new SELMAParser(tokens);
+
+ SELMAParser.program_return result = parser.program();
+ tree = (CommonTree)result.getTree();
+
+ }
+
+
+ if ( opt_code_generator) { // code the AST
+ // generate TAM assembler code using string template
+
+ // read templates (src of code: [Parr 2007, p. 216])
+ FileReader groupFileR = new FileReader("g-files/SELMACode.stg");
+ StringTemplateGroup templates
+ = new StringTemplateGroup(groupFileR);
+ groupFileR.close();
+
+ CommonTreeNodeStream nodes = new CommonTreeNodeStream(tree);
+ SELMACompiler codegenerator
+ = new SELMACompiler(nodes);
+ codegenerator.setTemplateLib(templates);
+ SELMACompiler.program_return r
+ = codegenerator.program();
+ StringTemplate output = (StringTemplate) r.getTemplate();
+ System.out.println(output.toString());
+ }
+
+
+ if (opt_ast) { // print the AST as string
+ System.out.println(tree.toStringTree());
+ } else if (opt_dot) { // print the AST as DOT specification
+ DOTTreeGenerator gen = new DOTTreeGenerator();
+ StringTemplate st = gen.toDOT(tree);
+ System.out.println(st);
+ }
+
+ } catch (SELMAException e) {
+ System.err.print("ERROR: SELMAException thrown by compiler: ");
+ System.err.println(e.getMessage());
+ } catch (SymbolTableException e) {
+ System.err.print("ERROR: SymbolTableException thrown by compiler: ");
+ System.err.println(e.getMessage());
+ } catch (RecognitionException e) {
+ System.err.print("ERROR: recognition exception thrown by compiler: ");
+ System.err.println(e.getMessage());
+ e.printStackTrace();
+ } catch (Exception e) {
+ System.err.print("ERROR: uncaught exception thrown by compiler: ");
+ System.err.println(e.getMessage());
+ e.printStackTrace();
+ }
+ }
+}
28 src/SELMA/SELMAException.java
@@ -0,0 +1,28 @@
+package SELMA;
+import org.antlr.runtime.RecognitionException;
+import org.antlr.runtime.tree.*;
+
+class SELMAException extends RecognitionException {
+ private String msg;
+ public static final long serialVersionUID = 241645436L; // for Serializable
+
+ // Ctor which only requires the error message to be printed.
+ public SELMAException(String msg) {
+ super();
+ this.msg = msg;
+ }
+
+ // Ctor that takes a node of the AST tree (i.e. IDENTIFIER) and
+ // the error message to build a more informative error message.
+ public SELMAException(Tree tree, String msg) {
+ super();
+ this.msg = tree.getText() +
+ " (" + tree.getLine() +
+ ":" + tree.getCharPositionInLine() +
+ ") " + msg;
+ }
+
+ public String getMessage() {
+ return msg;
+ }
+}
102 src/SELMA/SELMATree.java
@@ -0,0 +1,102 @@
+package SELMA;
+import java.util.Arrays;
+
+import org.antlr.runtime.tree.*;
+import org.antlr.runtime.Token;
+
+public class SELMATree extends CommonTree {
+ public SELMATree(){
+ super();
+ }
+
+ public SELMATree(Token t){
+ super(t);
+ }
+
+ public SELMATree(SELMATree t){
+ super(t);
+ }
+
+ public enum SR_Type {INT,BOOL,CHAR,VOID};
+ public enum SR_Kind {VAR, CONST};
+
+ public SR_Type SR_type = null;
+ public SR_Kind SR_kind = null;
+
+ public String toStringTree() {
+ return toStringTree(1);
+ }
+ public String toStringTree(int level) {
+ if ( children==null || children.size()==0 ) {
+ return this.toString();
+ }
+ StringBuffer buf = new StringBuffer();
+ if ( !isNil() ) {
+ buf.append("\n");
+ char[] c = new char[level];
+ Arrays.fill(c, '\t');
+ buf.append(c);
+ buf.append("(");
+ buf.append(this.toString());
+ buf.append(' ');
+ }
+ for (int i = 0; children!=null && i < children.size(); i++) {
+ SELMATree t = (SELMATree)children.get(i);
+ if ( i>0 ) {
+ buf.append(' ');
+ }
+ buf.append(t.toStringTree(level+1));
+ }
+ if ( !isNil() ) {
+ buf.append(")");
+ buf.append("\n");
+ char[] c = new char[level];
+ Arrays.fill(c, '\t');
+ buf.append(c);
+ }
+ return buf.toString();
+ }
+
+
+ public String toString() {
+ String s = super.toString();
+ s += " [";
+
+ if (SR_type == null)
+ s+="NULL";
+ else
+ switch (SR_type){
+ case BOOL:
+ s+="bool";
+ break;
+ case INT:
+ s+="int";
+ break;
+ case CHAR:
+ s+="char";
+ break;
+ case VOID:
+ s+="void";
+ break;
+ }
+
+ s+=",";
+
+ if (SR_kind == null)
+ s+="NULL";
+ else
+ switch (SR_kind){
+ case VAR:
+ s+="var";
+ break;
+ case CONST:
+ s+="const";
+ break;
+ }
+
+ s+="]";
+
+ return s;
+ }
+}
+
12 src/SELMA/SELMATreeAdaptor.java
@@ -0,0 +1,12 @@
+package SELMA;
+import org.antlr.runtime.tree.*;
+import org.antlr.runtime.Token;
+
+public class SELMATreeAdaptor extends CommonTreeAdaptor {
+ public Object create(Token t) {
+ return new SELMATree(t);
+ }
+ public Object dupNode (Object t) {
+ return new SELMATree((SELMATree)t);
+ }
+}
126 src/SELMA/SymbolTable.java
@@ -0,0 +1,126 @@
+package SELMA;
+
+import java.util.*;
+
+import org.antlr.runtime.RecognitionException;
+import org.antlr.runtime.tree.Tree;
+
+public class SymbolTable<Entry extends IdEntry> {
+ private int nextAddr = 0;
+ private int currentLevel;
+ private Map<String, Stack<Entry>> entries;
+
+
+ public int nextAddr(){
+ return nextAddr;
+ }
+
+ /**
+ * Constructor.
+ * @ensure this.currentLevel() == -1
+ */
+ public SymbolTable() {
+ currentLevel = -1;
+ entries = new HashMap<String, Stack<Entry>>();
+ }
+
+ /**
+ * Opens a new scope.
+ * @ensure this.currentLevel() == old.currentLevel()+1
+ */
+ public void openScope() {
+ currentLevel++;
+ }
+
+ /**
+ * Closes the current scope. All identifiers in
+ * the current scope will be removed from the SymbolTable.
+ * @require old.currentLevel() > -1
+ * @ensure this.currentLevel() == old.currentLevel()-1
+ */
+ public void closeScope() {
+ for (Map.Entry<String, Stack<Entry>> entry: entries.entrySet()){
+ Stack<Entry> stack = entry.getValue();
+ if ((stack != null) && (!stack.isEmpty()) && (stack.peek().level >= currentLevel)){
+ stack.pop();
+ nextAddr--;
+ }
+ }
+ currentLevel--;
+ }
+
+ /** Returns the current scope level. */
+ public int currentLevel() {
+ return currentLevel;
+ }
+
+ /**
+ * Enters an id together with an entry into this SymbolTable using the
+ * current scope level. The entry's level is set to currentLevel().
+ * @require String != null && String != "" && entry != null
+ * @ensure this.retrieve(id).getLevel() == currentLevel()
+ * @throws SymbolTableException when there is no valid current scope level,
+ * or when the id is already declared on the current level.
+ */
+ public void enter(Tree tree, Entry entry) throws SymbolTableException {
+ String id = tree.getText();
+ if (currentLevel < 0) {
+ throw new SymbolTableException(tree, "Not in a valid scope.");
+ }
+ Stack<Entry> s = entries.get(id);
+ if (s==null) {
+ s = new Stack<Entry>();
+ entry.level=currentLevel;
+ s.push(entry);
+ entries.put(id, s);
+ nextAddr++;
+ } else if (s.isEmpty() || s.peek().level != currentLevel){
+ entry.level=currentLevel;
+ s.push(entry);
+ nextAddr++;
+ } else {
+ throw new SymbolTableException(tree, "Entry "+id+" already exists in current scope.");
+ }
+ }
+
+
+ /**
+ * Get the Entry corresponding with id whose level is the highest.
+ * In other words, the method returns the Entry that is defined last.
+ * @return Entry of this id on the highest level
+ * null if this SymbolTable does not contain id
+ */
+ public Entry retrieve(Tree tree) throws SymbolTableException{
+ String id = tree.getText();
+ Stack<Entry> s = entries.get(id);
+ if (s==null||s.isEmpty())
+ throw new SymbolTableException(tree, "Entry not found: "+id);
+ return s.peek();
+ }
+
+ public String toString(){
+ String s = "";
+ for (Map.Entry<String, Stack<Entry>> entry: entries.entrySet()){
+ Stack<Entry> stack = entry.getValue();
+ s+=entry.getKey();
+ s+=stack.toString();
+ }
+ return s;
+ }
+}
+
+/** Exception class to signal problems with the SymbolTable */
+class SymbolTableException extends RecognitionException {
+ public static final long serialVersionUID = 24362462L; // for Serializable
+ private String msg;
+ public SymbolTableException(Tree tree, String msg) {
+ super();
+ this.msg = tree.getText() +
+ " (" + tree.getLine() +
+ ":" + tree.getCharPositionInLine() +
+ ") " + msg;
+ }
+ public String getMessage() {
+ return msg;
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.