-
Notifications
You must be signed in to change notification settings - Fork 0
/
Program.java
105 lines (98 loc) · 2.96 KB
/
Program.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package nz.ac.aut.wbz8656.dsa2017.assignment02;
/**
* Compiles a string into a program, and allows a user to run it.
* @author Guan Wang
* @version 1.0
*/
public class Program {
//Private
private ArrayList<Instruction> instructions;
private Program(ArrayList<Instruction> instructions) {
this.instructions = instructions;
}
//Factory
/**
* Takes the string src, and a printable. After checking that it represents a valid program,
* it returns a Program which can be executed.
* @param src The string that represents a program
* @param printer A printable
* @return a Program that is compiled and is prepared to be run
* @throws IllegalArgumentException
*/
public static Program compile (String src, Printable printer) throws IllegalArgumentException {
ArrayList<Instruction> instructions = ArrayList.empty();
String[] parts = src.split("#")[0].split(" ");
int index = 0;
int count = 0;
for (String p : parts) {
if (p.length() > 0) {
boolean isNumber = false;
boolean isOperator = false;
boolean isDot = false;
try {
Long value = Long.valueOf(p);
instructions.add(Literal.of(value), index);
isNumber = true;
} catch (NumberFormatException e) {
if (p.equals("+")) {
instructions.add(Plus.make(), index);
isOperator = true;
} else if (p.equals("-")) {
instructions.add(Minus.make(), index);
isOperator = true;
} else if (p.equals("*")) {
instructions.add(Times.make(), index);
isOperator = true;
} else if (p.equals("/")) {
instructions.add(Divide.make(), index);
isOperator = true;
} else if (p.equals("^")) {
instructions.add(Pow.make(), index);
isOperator = true;
} else if (p.equals(".")) {
instructions.add(Dot.make(printer), index);
isDot = true;
} else {
throw new IllegalArgumentException("Invalid token: " + p);
}
}
if (count == 0) {
if (!isNumber) {
throw new IllegalArgumentException("Expected number at positon " + count + " instead got: " + p);
}
} else if (count == 1) {
if (!isNumber && !isDot) {
throw new IllegalArgumentException("Expected number or dot at position " + count + " instead got: " + p);
} else if (isDot) {
count++;
}
} else if (isDot) {
count++;
} else {
if (count % 2 == 0) { // even
if (!isOperator) {
throw new IllegalArgumentException("Expected operator at position " + count + " instead got: " + p);
}
} else { // odd
if (!isNumber) {
throw new IllegalArgumentException("Expected number at position " + count + " instead got: " + p);
}
}
}
count++;
index++;
}
}
return new Program(instructions);
}
//Command
/**
* Runs the program
* @param stack Given stack that instructions are to be executed on
*/
public void run (Stack<Long> stack) {
for (int i=0; i<instructions.size(); i++) {
instructions.unsafeAt(i).execute(stack);
}
}
}