Skip to content

Commit 0163b90

Browse files
committed
week6 kodutöö lahendus
1 parent 0bdc968 commit 0163b90

2 files changed

Lines changed: 247 additions & 0 deletions

File tree

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package week6;
2+
3+
import week5.AktkHandwrittenLexer;
4+
import week5.AktkToken;
5+
6+
import java.io.StringReader;
7+
8+
import static week5.AktkToken.Type.*;
9+
10+
public class AktkHandwrittenParser {
11+
12+
private final AktkHandwrittenLexer lexer;
13+
private AktkToken current;
14+
15+
public AktkHandwrittenParser(AktkHandwrittenLexer lexer) {
16+
this.lexer = lexer;
17+
}
18+
19+
private void consume() {
20+
current = lexer.readNextToken();
21+
}
22+
23+
private AktkToken.Type peek() {
24+
return current.type();
25+
}
26+
27+
private void match(AktkToken.Type t) {
28+
if (peek() != t) throw new AktkParseException(current, t);
29+
consume();
30+
}
31+
32+
private AktkNode expression() {
33+
AktkNode left = term();
34+
AktkToken.Type next = peek();
35+
while (next == PLUS || next == MINUS) {
36+
consume();
37+
left = new AktkNode.BinOp(next, left, term());
38+
next = peek();
39+
}
40+
if (next == EOF || next == RPAREN) {
41+
return left;
42+
}
43+
throw new AktkParseException(current, PLUS, MINUS, TIMES, DIV, EOF, RPAREN);
44+
}
45+
46+
private AktkNode term() {
47+
AktkNode left = factor();
48+
AktkToken.Type next = peek();
49+
while (next == TIMES || next == DIV) {
50+
consume();
51+
left = new AktkNode.BinOp(next, left, factor());
52+
next = peek();
53+
}
54+
return left;
55+
}
56+
57+
private AktkNode factor() {
58+
AktkToken.Type t = peek();
59+
AktkNode result;
60+
switch (t) {
61+
case VARIABLE:
62+
result = new AktkNode.Variable((String) current.data());
63+
consume();
64+
break;
65+
case INTEGER:
66+
result = new AktkNode.IntLiteral((int) current.data());
67+
consume();
68+
break;
69+
case LPAREN:
70+
match(LPAREN);
71+
result = expression();
72+
match(RPAREN);
73+
break;
74+
default:
75+
throw new AktkParseException(current, VARIABLE, INTEGER, LPAREN);
76+
}
77+
return result;
78+
}
79+
80+
public AktkNode parse() {
81+
consume();
82+
AktkNode result = expression();
83+
if (peek() != EOF) {
84+
throw new AktkParseException(current, EOF);
85+
}
86+
return result;
87+
}
88+
89+
public static AktkNode parse(String input) {
90+
AktkHandwrittenLexer lexer = new AktkHandwrittenLexer(new StringReader(input));
91+
AktkHandwrittenParser parser = new AktkHandwrittenParser(lexer);
92+
return parser.parse();
93+
}
94+
95+
}

sols/week6/AktkNode.java

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package week6;
2+
3+
import week5.AktkToken;
4+
5+
import java.util.Map;
6+
7+
import static week5.AktkToken.Type.*;
8+
9+
public interface AktkNode {
10+
11+
static AktkNode num(int value) {
12+
return new IntLiteral(value);
13+
}
14+
15+
static AktkNode var(String name) {
16+
return new Variable(name);
17+
}
18+
19+
private static AktkNode binop(AktkToken.Type type, AktkNode left, AktkNode right) {
20+
return new BinOp(type, left, right);
21+
}
22+
23+
static AktkNode plus(AktkNode left, AktkNode right) {
24+
return binop(PLUS, left, right);
25+
}
26+
27+
static AktkNode minus(AktkNode left, AktkNode right) {
28+
return binop(MINUS, left, right);
29+
}
30+
31+
static AktkNode mul(AktkNode left, AktkNode right) {
32+
return binop(TIMES, left, right);
33+
}
34+
35+
static AktkNode div(AktkNode left, AktkNode right) {
36+
return binop(DIV, left, right);
37+
}
38+
39+
int eval(Map<String, Integer> env);
40+
41+
default String toPrettyString() {
42+
return toPrettyString(0);
43+
}
44+
45+
String toPrettyString(int contextPriority);
46+
47+
record IntLiteral(int value) implements AktkNode {
48+
49+
@Override
50+
public int eval(Map<String, Integer> env) {
51+
return value;
52+
}
53+
54+
55+
@Override
56+
public String toString() {
57+
return "num(" + value + ")";
58+
}
59+
60+
@Override
61+
public String toPrettyString(int contextPriority) {
62+
return Integer.toString(value);
63+
}
64+
}
65+
66+
record Variable(String name) implements AktkNode {
67+
68+
@Override
69+
public int eval(Map<String, Integer> env) {
70+
return env.get(name());
71+
}
72+
73+
74+
@Override
75+
public String toString() {
76+
return "var(\"" + name + "\")";
77+
}
78+
79+
80+
@Override
81+
public String toPrettyString(int contextPriority) {
82+
return name;
83+
}
84+
}
85+
86+
record BinOp(AktkToken.Type op, AktkNode left, AktkNode right) implements AktkNode {
87+
88+
public BinOp {
89+
if (!isOperator(op)) throw new IllegalArgumentException();
90+
}
91+
92+
private boolean isOperator(AktkToken.Type token) {
93+
return switch (token) {
94+
case PLUS, MINUS, TIMES, DIV -> true;
95+
default -> false;
96+
};
97+
}
98+
99+
@Override
100+
public int eval(Map<String, Integer> env) {
101+
int l = left.eval(env);
102+
int r = right.eval(env);
103+
return switch (op) {
104+
case PLUS -> l + r;
105+
case MINUS -> l - r;
106+
case TIMES -> l * r;
107+
case DIV -> l / r;
108+
default -> throw new AssertionError("Impossible!");
109+
};
110+
}
111+
112+
113+
@Override
114+
public String toString() {
115+
return op.toString().toLowerCase() + "(" + left + ", " + right + ")";
116+
}
117+
118+
@Override
119+
public String toPrettyString(int contextPriority) {
120+
int prio = priorityOf(op);
121+
int assoc = prio + (isAssoc(op) ? 0 : 1);
122+
String content = left.toPrettyString(prio) + symbolOf(op) + right.toPrettyString(assoc);
123+
if (contextPriority > prio) return "(" + content + ")";
124+
else return content;
125+
}
126+
127+
private boolean isAssoc(AktkToken.Type op) {
128+
return switch (op) {
129+
case MINUS, DIV -> false;
130+
default -> true;
131+
};
132+
}
133+
134+
private String symbolOf(AktkToken.Type op) {
135+
return switch (op) {
136+
case PLUS -> "+";
137+
case MINUS -> "-";
138+
case TIMES -> "*";
139+
case DIV -> "/";
140+
default -> null;
141+
};
142+
}
143+
144+
private int priorityOf(AktkToken.Type op) {
145+
return switch (op) {
146+
case PLUS, MINUS -> 1;
147+
case TIMES, DIV -> 2;
148+
default -> 0;
149+
};
150+
}
151+
}
152+
}

0 commit comments

Comments
 (0)