Skip to content

Commit dec1759

Browse files
committed
week6 praksi lahendused
1 parent 803d5f8 commit dec1759

3 files changed

Lines changed: 246 additions & 0 deletions

File tree

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package week6.kalaparser;
2+
3+
/**
4+
* Kirjutame ise parseri, et saaks parseri abifunktsioonidest aru!
5+
* Testide läbimiseks ei pea ASTi tagastama, seega on parse meetodi tüüp esialgu void.
6+
*/
7+
public class IntroParser {
8+
9+
private final String input;
10+
private int pos;
11+
12+
public IntroParser(String input) {
13+
this.input = input + '$';
14+
this.pos = 0;
15+
}
16+
17+
public static void parse(String input) {
18+
IntroParser parser = new IntroParser(input);
19+
parser.parse();
20+
}
21+
22+
private void parse() {
23+
s();
24+
done();
25+
}
26+
27+
private void done() {
28+
if (peek() != '$') throw new RuntimeException();
29+
}
30+
31+
// S -> a S b
32+
private void s() {
33+
if (peek() == 'a') {
34+
match('a');
35+
s();
36+
match('b');
37+
}
38+
}
39+
40+
private char peek() {
41+
return input.charAt(pos);
42+
}
43+
44+
private void match(char expectedChar) {
45+
char inputChar = input.charAt(pos);
46+
if (inputChar == expectedChar) {
47+
pos++;
48+
} else {
49+
throw new RuntimeException("Unexpected char at " + pos);
50+
}
51+
}
52+
53+
static void main() {
54+
String input = "aaabbb";
55+
System.out.println("Parsing: " + input);
56+
try {
57+
IntroParser.parse(input);
58+
System.out.print("ACCEPT!");
59+
} catch (RuntimeException e) {
60+
System.out.println("REJECT!");
61+
}
62+
}
63+
64+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package week6.kalaparser;
2+
3+
import java.util.Arrays;
4+
import java.util.List;
5+
import java.util.Map;
6+
import java.util.StringJoiner;
7+
8+
import static week6.kalaparser.KalaNode.*;
9+
10+
public sealed interface KalaNode permits KalaIdent, KalaList, KalaNull {
11+
12+
int sum(Map<String, Integer> env);
13+
14+
static KalaNode mkNull() {
15+
return new KalaNull();
16+
}
17+
18+
static KalaNode mkIdent(String name) {
19+
return new KalaIdent(name);
20+
}
21+
22+
static KalaNode mkList(List<KalaNode> args) {
23+
return new KalaList(args);
24+
}
25+
26+
static KalaNode mkList(KalaNode... args) {
27+
return mkList(Arrays.asList(args));
28+
}
29+
30+
31+
// Siit edasi on siis lahendus ette antud, et selle peale mitte jälle liiga palju aega kulutada.
32+
// Nende peidetud "sisemiste" klasside asemel võid kodutöös teha täiesti eraldi avalikud klassid!
33+
34+
record KalaIdent(String name) implements KalaNode {
35+
36+
@Override
37+
public String toString() {
38+
return name;
39+
}
40+
41+
@Override
42+
public int sum(Map<String, Integer> env) {
43+
return env.get(name);
44+
}
45+
}
46+
47+
record KalaList(List<KalaNode> args) implements KalaNode {
48+
49+
@Override
50+
public String toString() {
51+
StringJoiner joiner = new StringJoiner(", ", "(", ")");
52+
for (KalaNode arg : args) joiner.add(arg.toString());
53+
return joiner.toString();
54+
}
55+
56+
@Override
57+
public int sum(Map<String, Integer> env) {
58+
return args.stream().mapToInt(n -> n.sum(env)).sum();
59+
}
60+
}
61+
62+
record KalaNull() implements KalaNode {
63+
64+
@Override
65+
public String toString() {
66+
return "NULL";
67+
}
68+
69+
@Override
70+
public int sum(Map<String, Integer> env) {
71+
return 0;
72+
}
73+
}
74+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package week6.kalaparser;
2+
3+
import week5.kalalexer.KalaLexer;
4+
import week5.kalalexer.KalaToken;
5+
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
9+
import static week5.kalalexer.KalaToken.Type.*;
10+
11+
public class KalaParser {
12+
13+
private final List<KalaToken> tokens;
14+
private int pos;
15+
16+
private KalaParser(KalaLexer lexer) {
17+
this.tokens = lexer.readAllTokens();
18+
this.pos = 0;
19+
}
20+
21+
public static KalaNode parse(String input) {
22+
KalaLexer lexer = new KalaLexer(input);
23+
// Ja kuidagi võiks nüüd seda lekserit kasutada oma parseris...
24+
KalaParser parser = new KalaParser(lexer);
25+
return parser.parse();
26+
}
27+
28+
private KalaNode parse() {
29+
KalaNode node = s();
30+
done();
31+
return node;
32+
}
33+
34+
private void done() {
35+
if (peek().type() != EOF) throw new KalaParseException(peek(), EOF);
36+
}
37+
38+
private KalaToken peek() {
39+
return tokens.get(pos);
40+
}
41+
42+
private void match(KalaToken.Type tokenType) {
43+
if (peek().type() != tokenType) {
44+
throw new KalaParseException(peek(), tokenType);
45+
}
46+
pos++;
47+
}
48+
49+
50+
// S → (L) | ()
51+
// L → A,L | A
52+
// A → w | 0 | S
53+
private KalaNode s() {
54+
match(LPAREN);
55+
if (peek().type() == RPAREN) {
56+
match(RPAREN);
57+
return KalaNode.mkList();
58+
} else {
59+
List<KalaNode> list = l();
60+
match(RPAREN);
61+
return KalaNode.mkList(list);
62+
}
63+
}
64+
65+
private List<KalaNode> l() {
66+
List<KalaNode> list = new ArrayList<>();
67+
list.add(a());
68+
if (peek().type() == COMMA) {
69+
match(COMMA);
70+
list.addAll(l());
71+
return list;
72+
}
73+
return list;
74+
}
75+
76+
// Alternatiivse variandina võib seda iteratiivselt teha.
77+
// L → A,L | A esitame EBNF kujul L → A(,A)*
78+
private List<KalaNode> l_ebnf() {
79+
List<KalaNode> list = new ArrayList<>();
80+
list.add(a());
81+
while (peek().type() == COMMA) {
82+
match(COMMA);
83+
list.add(a());
84+
}
85+
return list;
86+
}
87+
88+
private KalaNode a() {
89+
KalaToken node = peek();
90+
switch (node.type()) {
91+
case IDENT:
92+
match(IDENT);
93+
return KalaNode.mkIdent((String) node.data());
94+
case NULL:
95+
match(NULL);
96+
return KalaNode.mkNull();
97+
case LPAREN:
98+
return s();
99+
default:
100+
throw new KalaParseException(peek(), IDENT, NULL, LPAREN);
101+
}
102+
}
103+
104+
static void main() {
105+
KalaNode ast = parse("(kala, (x,y , null, (), (kala,()) ))");
106+
System.out.println(ast);
107+
}
108+
}

0 commit comments

Comments
 (0)