Printer File
Grammar File
AST file
Value file
Evaluator File
Other Files in the project
Reader
Interpreter
5. (26 pt) (ArithLang interpreter advanced] Implement an interpreter for Abstract Lang described as follows. You can modify the ArithLang code provided. (a) This language contains only six terminals, p, n, u, +, - (b) p represents positve numbers, n represents negative numbers and u represent unknown values (c) There are two operators + and - that can be applied on the terminals, their syntactic rules are similar to + and - in ArithLang, except that each operator only can take two operands () The semantics of AbstractLang are defined by the following rules (the first column in the table represents the first operand and the first row in the table represents the second operand of the operation): + p nu pnu ppuu pupu n n n u u u u u u u u u u e.g. (+ pp) =p (- np) = n (- (+ n u) p) = u (+ PPP) = error (+34) = error (* 2 p) = error (+ a b) = error You will need to modify the following files: (6 pt) Grammar file (Abstract Lang.g) . (4 pt) AST file (AST.java) (3 pt) Printer file (Printer.java) (3 pt) Value file (Value.java) (10 pt) Evaluator (Evaluator.java) 7 - 1 n 1 package arithlang; 2 3 import static arithlang. AST.*; 4 5 public class Printer { 6 public void print (Value v) { System.out.println(v.toString()); } 10 public static class Formatter implements AST.Visitor
{ 11 12 public String visit (Program p) { 13 return (String) p.e().accept(this); 14 } 15 16 public String visit (NumExp e) { 17 return "" + e.v(); 18 } 19 20 public String visit (AddExp e) { 21 String result = "(+"; 22 for (AST.Exp exp: e.all()) 23 result += "" + exp.accept(this); 24 return result + ")"; 25 } 26 27 public String visit (SubExp e) { 28 String result = "(-"; 29 for (AST.Exp exp: e.all()) 30 result += " + exp.accept(this); 31 return result + ")"; 32 } 33 34 public String visit (MultExp e) { 35 String result = "(*"; 36 for (AST.Exp exp : e.all()) 37 result += "" + exp.accept(this); 38 return result + "); 39 } 40 41 public String visit (DivExp e) { 42 String result = "/"; 43 for (AST. Exp exp : e.all()) 44 result += " + exp.accept(this); 45 return result + ")"; 46 47 48 49 HITE grammar ArithLang; 1/ Grammar of this Programming Language // - grammar rules start with lowercase program returns (Program ast] : e=exp{ $ast = new Program (Se.ast); } ; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 exp returns [Exp ast]: n=numexp{ $ast = $n.ast; } | a=addexp { $ast Sa.ast; } | s=subexp { $ast = $s.ast; } | m=multexp { $ast = $m.ast; } | d=divexp { $ast $d.ast;) ; numexp returns [NumExp ast]: n0=Number { $ast = new NumExp (Integer.parseInt($no.text)); } | '-' n0=Number { $ast = new NumExp(-Integer.parseInt($no.text)); } | n0=Number Dot nl=Number { $ast = new NumExp (Double.parseDouble ($no.text+","+$nl.text)); } | '-' n0=Number Dot nl=Number { $ast = new NumExp (Double.parseDouble("-" + $no.text+"."+$nl.text)); } 23 24 25 26 27 28 addexp returns [AddExp ast] locals [ArrayList list] @init { $list = new ArrayList(); } : '(''+' e=exp { $list.add($e.ast); } (e=exp { $list.add($e.ast); } ) + '' { $ast = new AddExp ($list); } 29 ; subexp returns (SubExp ast] locals [ArrayList list] @init { $list = new ArrayList(); } : "('' e=exp{ $list.add($e.ast); } (e=exp { $list.add($e.ast); } ) + ' { $ast = new SubExp ($list); } 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 multexp returns (MultExp ast] locals [ArrayList list] @init { $list = new ArrayList(); } : e=exp{ $list.add($e.ast); } (e=exp { $list.add($e.ast); } ) + ' { $ast = new MultExp (slist); } divexp returns [DivExp ast] locals [ArrayList list] @init { $list = new ArrayList(); } e=exp{ $list.add($e.ast); } (e=exp { $list.add($e.ast); } ) + '' { $ast = new DivExp (list); } ; 60 // Lexical Specification of this programming Language lexical specification rules start with uppercase Define : 'define'; Let : 'let'; Dot :'.'; Number : DIGIT+; Identifier : Letter LetterorDigit*; 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 Letter: [a-zA-Z$_] -[\u0000-\u00FF\UD800-\uDBFF] Character.is JavaIdentifierStart_input.LA(-1)) }? [\uD800-\uDBFF] [\UDC00-\UDFFF] {Character.isJavaIdentifierStart (Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1))))? ; LetterOrDigit: [a-zA-Z0-9$_] 1 -[\u0000-\u00FF\UD800-\uDBFF) {Character.is JavaIdentifierPart_input.LA(-1)) }? [\UD800-\uDBFF] [\UDC00-\UDFFF] {Character.isJavaIdentifierPart (Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1))))?: fragment DIGIT: ('0'..'9'); AT : '@'; ELLIPSIS : WS : [ \t \u000C] + -> skip; Comment : '/' .*? '*/' -> skip; Line_Comment: '//' -[ ]* -> skip; + * 1 package arithlang; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 /** 7 * This class hierarchy represents expressions in the abstract syntax tree 8 * manipulated by this interpreter. 9 10 * @author hridesh 11 12 13 @SuppressWarnings ("rawtypes") 14 public interface AST { 15 public static abstract class ASTNode { 16 public abstract Object accept (Visitor visitor); 17 } 18 public static class Program extends ASTNode 19 Exp_e; 20 21 public Program (Expe) { 22 Le = e; 23 } 24 25 public Exp e() { 26 return _e; 27 } 28 29 public Object accept (Visitor visitor) { 30 return visitor.visit(this); 31 } 32 } 33 public static abstract class Exp extends ASTNode { 34 35 } 36 37 public static class NumExp extends Exp { 38 39 double val; 39 40 public NumExp (double v) { 41 _val = v; 42 } 43 44 public double v() { 45 return val; 46 } 47 48 public Object accept (Visitor visitor) { 49 return visitor.visit(this); 50 } 51 } 52 53 public static abstract class CompoundArithExp extends Exp { 54 List _rep; 55 public CompoundArithExp (List args) { 56 _rep = new ArrayList(); 57 _rep.addAll(args); 58 } 59 public List all() { 60 return _rep; 61 } 62 } 63 64 public static class AddExp extends CompoundArithExp { 65 public AddExp (List args) { 66 super (args); 67 } 68 public Object accept (Visitor visitor) { 69 return visitor.visit(this); 70 } 71 } 74 75 76 77 78 79 80 public static class SubExp extends CompoundArithExp { public SubExp (List args) { super (args); } public Object accept (Visitor visitor) { return visitor.visit(this); } } 81 82 83 84 T - public static class DivExp extends CompoundArithExp { public DivExp (List args) { super (args); } public Object accept (Visitor visitor) { return visitor.visit(this); } } HD - 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 public static class MultExp extends CompoundArithExp{ public MultExp (List args) { super (args); } public Object accept (Visitor visitor) { return visitor.visit(this); } } public interface Visitor { // This interface should contain a signature for each concrete Ast node. public T visit (AST.NumExp e); public T visit (AST.AddExp e); public T visit (AST. SubExpe); public T visit (AST.MultExp e); public T visit (AST. DivExp e); public T visit (AST. Program p); 107 108 109 110 8 1 package arithlang; 2 3 public interface Value { 4 public String toString(); 5 static class Numval implements Value { private double val; public Numval (double v) { _val = v; } public double v() { return val; } 9 public String toString() { 10 int tmp = (int) _val; 11 if (tmp == _val) return + tmp: 12 return + val; 13 14 } 15 16 static class DynamicError implements Value ! 17 private String _errorMsg; 18 public DynamicError (String v) { 19 _errorMsg = v; 20 } 21 public String v() { 22 return _errorMsg; 23 } 24 public String toString() { 25 String tmp = _errorMsg; 26 if (tmp == _errorMsg) return + tmp; return + _errorMsg; 28 -T 27 30 31 package arithlang; import static arithlang.AST.*; import static arithlang.Value.*; import java.util.List; public class Evaluator implements Visitor { private Numval record = new Numval(); Printer. Formatter ts = new Printer. Formatter(); Value valueof (Program p) { // Value of a program in this language is the value of the expression return (value) p.accept(this); } 13 14 15 17 18 19 20 @Override public Value visit (AddExp e) { List operands = e.all(); double result = 0; for (Exp exp: operands) { Numval intermediate = (Numval) exp.accept(this); // Dynamic type-checking result += intermediate.v(); //Semantics of AddExp in terms of the target language. } return new NumVal (result); } 22 @Override public Value visit (NumExp e) { return new Numval (e.v()); } 37 38 39 40 41 42 43 @Override public Value visit (DivExp e) { List operands = e.all(); Numval ival = (Numval) operands.get().accept(this); double result = lval.v(); for (int i=1; i operands = e.all(); double result = 1; for (Exp exp: operands) { Numval intermediate = (NumVal) exp.accept(this); // Dynamic type-checking result *= intermediate.v(); //Semantics of MultExp. } return new Numval (result); } @Override public Value visit (Program p) { return (Value) p.e().accept(this); } 63 64 65 66 67 68 69 70 71 72 73 74 @Override public Value visit (SubExp e) { List operands = e.all(); NumVal lVal = (NumVal) operands.get().accept(this); double result = lval.v(); for (int i=1; i { 11 12 public String visit (Program p) { 13 return (String) p.e().accept(this); 14 } 15 16 public String visit (NumExp e) { 17 return "" + e.v(); 18 } 19 20 public String visit (AddExp e) { 21 String result = "(+"; 22 for (AST.Exp exp: e.all()) 23 result += "" + exp.accept(this); 24 return result + ")"; 25 } 26 27 public String visit (SubExp e) { 28 String result = "(-"; 29 for (AST.Exp exp: e.all()) 30 result += " + exp.accept(this); 31 return result + ")"; 32 } 33 34 public String visit (MultExp e) { 35 String result = "(*"; 36 for (AST.Exp exp : e.all()) 37 result += "" + exp.accept(this); 38 return result + "); 39 } 40 41 public String visit (DivExp e) { 42 String result = "/"; 43 for (AST. Exp exp : e.all()) 44 result += " + exp.accept(this); 45 return result + ")"; 46 47 48 49 HITE grammar ArithLang; 1/ Grammar of this Programming Language // - grammar rules start with lowercase program returns (Program ast] : e=exp{ $ast = new Program (Se.ast); } ; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 exp returns [Exp ast]: n=numexp{ $ast = $n.ast; } | a=addexp { $ast Sa.ast; } | s=subexp { $ast = $s.ast; } | m=multexp { $ast = $m.ast; } | d=divexp { $ast $d.ast;) ; numexp returns [NumExp ast]: n0=Number { $ast = new NumExp (Integer.parseInt($no.text)); } | '-' n0=Number { $ast = new NumExp(-Integer.parseInt($no.text)); } | n0=Number Dot nl=Number { $ast = new NumExp (Double.parseDouble ($no.text+","+$nl.text)); } | '-' n0=Number Dot nl=Number { $ast = new NumExp (Double.parseDouble("-" + $no.text+"."+$nl.text)); } 23 24 25 26 27 28 addexp returns [AddExp ast] locals [ArrayList list] @init { $list = new ArrayList(); } : '(''+' e=exp { $list.add($e.ast); } (e=exp { $list.add($e.ast); } ) + '' { $ast = new AddExp ($list); } 29 ; subexp returns (SubExp ast] locals [ArrayList list] @init { $list = new ArrayList(); } : "('' e=exp{ $list.add($e.ast); } (e=exp { $list.add($e.ast); } ) + ' { $ast = new SubExp ($list); } 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 multexp returns (MultExp ast] locals [ArrayList list] @init { $list = new ArrayList(); } : e=exp{ $list.add($e.ast); } (e=exp { $list.add($e.ast); } ) + ' { $ast = new MultExp (slist); } divexp returns [DivExp ast] locals [ArrayList list] @init { $list = new ArrayList(); } e=exp{ $list.add($e.ast); } (e=exp { $list.add($e.ast); } ) + '' { $ast = new DivExp (list); } ; 60 // Lexical Specification of this programming Language lexical specification rules start with uppercase Define : 'define'; Let : 'let'; Dot :'.'; Number : DIGIT+; Identifier : Letter LetterorDigit*; 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 Letter: [a-zA-Z$_] -[\u0000-\u00FF\UD800-\uDBFF] Character.is JavaIdentifierStart_input.LA(-1)) }? [\uD800-\uDBFF] [\UDC00-\UDFFF] {Character.isJavaIdentifierStart (Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1))))? ; LetterOrDigit: [a-zA-Z0-9$_] 1 -[\u0000-\u00FF\UD800-\uDBFF) {Character.is JavaIdentifierPart_input.LA(-1)) }? [\UD800-\uDBFF] [\UDC00-\UDFFF] {Character.isJavaIdentifierPart (Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1))))?: fragment DIGIT: ('0'..'9'); AT : '@'; ELLIPSIS : WS : [ \t \u000C] + -> skip; Comment : '/' .*? '*/' -> skip; Line_Comment: '//' -[ ]* -> skip; + * 1 package arithlang; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 /** 7 * This class hierarchy represents expressions in the abstract syntax tree 8 * manipulated by this interpreter. 9 10 * @author hridesh 11 12 13 @SuppressWarnings ("rawtypes") 14 public interface AST { 15 public static abstract class ASTNode { 16 public abstract Object accept (Visitor visitor); 17 } 18 public static class Program extends ASTNode 19 Exp_e; 20 21 public Program (Expe) { 22 Le = e; 23 } 24 25 public Exp e() { 26 return _e; 27 } 28 29 public Object accept (Visitor visitor) { 30 return visitor.visit(this); 31 } 32 } 33 public static abstract class Exp extends ASTNode { 34 35 } 36 37 public static class NumExp extends Exp { 38 39 double val; 39 40 public NumExp (double v) { 41 _val = v; 42 } 43 44 public double v() { 45 return val; 46 } 47 48 public Object accept (Visitor visitor) { 49 return visitor.visit(this); 50 } 51 } 52 53 public static abstract class CompoundArithExp extends Exp { 54 List _rep; 55 public CompoundArithExp (List args) { 56 _rep = new ArrayList(); 57 _rep.addAll(args); 58 } 59 public List all() { 60 return _rep; 61 } 62 } 63 64 public static class AddExp extends CompoundArithExp { 65 public AddExp (List args) { 66 super (args); 67 } 68 public Object accept (Visitor visitor) { 69 return visitor.visit(this); 70 } 71 } 74 75 76 77 78 79 80 public static class SubExp extends CompoundArithExp { public SubExp (List args) { super (args); } public Object accept (Visitor visitor) { return visitor.visit(this); } } 81 82 83 84 T - public static class DivExp extends CompoundArithExp { public DivExp (List args) { super (args); } public Object accept (Visitor visitor) { return visitor.visit(this); } } HD - 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 public static class MultExp extends CompoundArithExp{ public MultExp (List args) { super (args); } public Object accept (Visitor visitor) { return visitor.visit(this); } } public interface Visitor { // This interface should contain a signature for each concrete Ast node. public T visit (AST.NumExp e); public T visit (AST.AddExp e); public T visit (AST. SubExpe); public T visit (AST.MultExp e); public T visit (AST. DivExp e); public T visit (AST. Program p); 107 108 109 110 8 1 package arithlang; 2 3 public interface Value { 4 public String toString(); 5 static class Numval implements Value { private double val; public Numval (double v) { _val = v; } public double v() { return val; } 9 public String toString() { 10 int tmp = (int) _val; 11 if (tmp == _val) return + tmp: 12 return + val; 13 14 } 15 16 static class DynamicError implements Value ! 17 private String _errorMsg; 18 public DynamicError (String v) { 19 _errorMsg = v; 20 } 21 public String v() { 22 return _errorMsg; 23 } 24 public String toString() { 25 String tmp = _errorMsg; 26 if (tmp == _errorMsg) return + tmp; return + _errorMsg; 28 -T 27 30 31 package arithlang; import static arithlang.AST.*; import static arithlang.Value.*; import java.util.List; public class Evaluator implements Visitor { private Numval record = new Numval(); Printer. Formatter ts = new Printer. Formatter(); Value valueof (Program p) { // Value of a program in this language is the value of the expression return (value) p.accept(this); } 13 14 15 17 18 19 20 @Override public Value visit (AddExp e) { List operands = e.all(); double result = 0; for (Exp exp: operands) { Numval intermediate = (Numval) exp.accept(this); // Dynamic type-checking result += intermediate.v(); //Semantics of AddExp in terms of the target language. } return new NumVal (result); } 22 @Override public Value visit (NumExp e) { return new Numval (e.v()); } 37 38 39 40 41 42 43 @Override public Value visit (DivExp e) { List operands = e.all(); Numval ival = (Numval) operands.get().accept(this); double result = lval.v(); for (int i=1; i operands = e.all(); double result = 1; for (Exp exp: operands) { Numval intermediate = (NumVal) exp.accept(this); // Dynamic type-checking result *= intermediate.v(); //Semantics of MultExp. } return new Numval (result); } @Override public Value visit (Program p) { return (Value) p.e().accept(this); } 63 64 65 66 67 68 69 70 71 72 73 74 @Override public Value visit (SubExp e) { List operands = e.all(); NumVal lVal = (NumVal) operands.get().accept(this); double result = lval.v(); for (int i=1; i