Skip to content

Commit 381962e

Browse files
committed
week7 demos lahendused
1 parent 0163b90 commit 381962e

4 files changed

Lines changed: 268 additions & 0 deletions

File tree

sols/week7/demos/Arith.g4

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
grammar Arith; // grammatika nimi peab klappima failinimega
2+
@header { package week7.demos; } // Seda on vaja, et loodud failid läheks õige paketti.
3+
4+
// parseri reeglid algavad väikeste tähtedega
5+
expr
6+
: expr op='+' term #BinaryExpr
7+
| expr op='-' term #BinaryExpr
8+
| term #SimpleExpr
9+
;
10+
11+
term
12+
: term op='*' factor #BinaryTerm
13+
| term op='/' factor #BinaryTerm
14+
| factor #SimpleTerm
15+
;
16+
17+
factor
18+
: '(' expr ')' #Paren
19+
| Variable #Variable
20+
| Literal #Literal
21+
;
22+
23+
// lekseri reeglid algavad suurte tähtedega
24+
Variable
25+
: [a-zA-Z_][a-zA-Z_0-9]*
26+
;
27+
28+
Literal
29+
: [0-9]|[1-9][0-9]+
30+
;
31+
32+
// Järgmise lekseemi suuname ära (-> skip).
33+
WS: [ \t\r\n]+ -> skip;

sols/week7/demos/ArithAst.java

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package week7.demos;
2+
3+
import org.antlr.v4.runtime.CharStreams;
4+
import org.antlr.v4.runtime.CommonTokenStream;
5+
import org.antlr.v4.runtime.tree.ParseTree;
6+
import org.antlr.v4.runtime.tree.TerminalNode;
7+
import week6.parsers.Node;
8+
9+
import java.util.HashMap;
10+
import java.util.Map;
11+
12+
import static week7.demos.ArithParser.*;
13+
14+
public class ArithAst {
15+
16+
private static ParseTree createParseTree(String program, boolean debug) {
17+
ArithLexer lexer = new ArithLexer(CharStreams.fromString(program));
18+
ArithParser parser = new ArithParser(new CommonTokenStream(lexer));
19+
ParseTree tree = parser.expr();
20+
if (debug) System.out.println(tree.toStringTree(parser));
21+
return tree;
22+
}
23+
24+
private static int eval(ParseTree tree, Map<String, Integer> env) {
25+
ArithVisitor<Integer> visitor = new ArithBaseVisitor<>() {
26+
27+
@Override
28+
public Integer visitParen(ParenContext ctx) {
29+
return visit(ctx.expr());
30+
}
31+
32+
@Override
33+
public Integer visitVariable(VariableContext ctx) {
34+
return env.get(ctx.getText());
35+
}
36+
37+
@Override
38+
public Integer visitLiteral(LiteralContext ctx) {
39+
return Integer.parseInt(ctx.getText());
40+
}
41+
42+
43+
// Defineerime abifunktsiooni, et sama struktuuriga reegleid koos käsitleda:
44+
// expr -> expr '+' term #BinaryExpr
45+
// expr -> expr '-' term #BinaryExpr
46+
// term -> term '*' factor #BinaryTerm
47+
// term -> term '/' factor #BinaryTerm
48+
private Integer handleBinop(ParseTree ctx) {
49+
50+
// Küsime homogeense liidese kaudu tipude alluvad
51+
ParseTree leftChild = ctx.getChild(0);
52+
String operator = ctx.getChild(1).getText();
53+
ParseTree rightChild = ctx.getChild(2);
54+
55+
// Visit saab eri tüüpi alluvatega hakkama:
56+
int leftValue = visit(leftChild);
57+
int rightValue = visit(rightChild);
58+
59+
return switch (operator) {
60+
case "+" -> leftValue + rightValue;
61+
case "-" -> leftValue - rightValue;
62+
case "*" -> leftValue * rightValue;
63+
case "/" -> leftValue / rightValue;
64+
default -> throw new RuntimeException("Tundmatu operaator");
65+
};
66+
}
67+
68+
@Override
69+
public Integer visitBinaryExpr(BinaryExprContext ctx) {
70+
return handleBinop(ctx);
71+
}
72+
73+
@Override
74+
public Integer visitBinaryTerm(BinaryTermContext ctx) {
75+
return handleBinop(ctx);
76+
}
77+
78+
// Aga kus on järgmised reeglid?
79+
// expr -> term #SimpleExpr
80+
// term -> factor #SimpleTerm
81+
// BaseVisitor hoolitseb nende eest. Kui mõni reegel on defineerimata,
82+
// siis külastatakse alluvad järjest ja tagastatakse viimase tulemus.
83+
// (Seda käitumist saab aggregateResult ja defaultResult kaudu ka muuta.)
84+
85+
};
86+
return visitor.visit(tree);
87+
}
88+
89+
private static Node parseTreeToAst(ParseTree tree) {
90+
ArithVisitor<Node> visitor = new ArithBaseVisitor<>() {
91+
92+
@Override
93+
public Node visitTerminal(TerminalNode node) {
94+
return new Node(node.getText());
95+
}
96+
97+
@Override
98+
public Node visitBinaryExpr(BinaryExprContext ctx) {
99+
return new Node(ctx.op.getText(), visit(ctx.expr()), visit(ctx.term()));
100+
}
101+
102+
@Override
103+
public Node visitBinaryTerm(BinaryTermContext ctx) {
104+
return new Node(ctx.op.getText(), visit(ctx.term()), visit(ctx.factor()));
105+
}
106+
107+
@Override
108+
public Node visitParen(ParenContext ctx) {
109+
return visit(ctx.expr());
110+
}
111+
};
112+
return visitor.visit(tree);
113+
}
114+
115+
// testide jaoks...
116+
public static int eval(String expr) {
117+
return eval(createParseTree(expr, false), new HashMap<>());
118+
}
119+
120+
public static Node makeAst(String expr) {
121+
return parseTreeToAst(createParseTree(expr, false));
122+
}
123+
124+
// Ise katsetamiseks:
125+
static void main() {
126+
ParseTree parseTree = createParseTree("20 - x * 2 - 1", true);
127+
HashMap<String, Integer> env = new HashMap<>(); env.put("x", 3);
128+
System.out.println(eval(parseTree, env)); // 13
129+
System.out.println(parseTreeToAst(parseTree)); // -(-(20,*(x,2)),1)
130+
}
131+
132+
}

sols/week7/demos/Kala.g4

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
grammar Kala;
2+
@header { package week7.demos; }
3+
4+
// Ära seda reeglit ümber nimeta, selle kaudu testitakse grammatikat
5+
init : list EOF;
6+
7+
list : '(' elements? ')';
8+
9+
elements : element (',' element)*;
10+
11+
element
12+
: Variable # Variable
13+
| Null # Null
14+
| list # ListElement
15+
;
16+
17+
Null : 'null';
18+
19+
Variable : [a-z]+;
20+
21+
WS : [ \t] -> skip;

sols/week7/demos/KalaAst.java

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package week7.demos;
2+
3+
import org.antlr.v4.runtime.BailErrorStrategy;
4+
import org.antlr.v4.runtime.CharStreams;
5+
import org.antlr.v4.runtime.CommonTokenStream;
6+
import org.antlr.v4.runtime.tree.ParseTree;
7+
import utils.ExceptionErrorListener;
8+
import week6.kalaparser.KalaNode;
9+
import week7.demos.KalaParser.*;
10+
11+
import java.util.ArrayList;
12+
import java.util.HashMap;
13+
import java.util.List;
14+
import java.util.Map;
15+
16+
public class KalaAst {
17+
18+
public static KalaNode makeKalaAst(String sisend) {
19+
KalaLexer lexer = new KalaLexer(CharStreams.fromString(sisend));
20+
lexer.removeErrorListeners();
21+
lexer.addErrorListener(new ExceptionErrorListener());
22+
23+
KalaParser parser = new KalaParser(new CommonTokenStream(lexer));
24+
parser.removeErrorListeners();
25+
parser.setErrorHandler(new BailErrorStrategy());
26+
27+
ParseTree tree = parser.init();
28+
return parseTreeToAst(tree);
29+
}
30+
31+
// Põhimeetod, mida tuleks implementeerida
32+
private static KalaNode parseTreeToAst(ParseTree tree) {
33+
KalaBaseVisitor<KalaNode> visitor = new KalaBaseVisitor<>() {
34+
@Override
35+
public KalaNode visitInit(InitContext ctx) {
36+
return visit(ctx.list());
37+
}
38+
39+
@Override
40+
public KalaNode visitList(ListContext ctx) {
41+
if (ctx.elements() != null) return visit(ctx.elements());
42+
else return KalaNode.mkList();
43+
}
44+
45+
@Override
46+
public KalaNode visitElements(ElementsContext ctx) {
47+
List<KalaNode> list = new ArrayList<>();
48+
for (ElementContext element : ctx.element()) list.add(visit(element));
49+
// Ehk: List<KalaNode> = ctx.element().stream().map(this::visit).toList();
50+
return KalaNode.mkList(list);
51+
}
52+
53+
@Override
54+
public KalaNode visitVariable(VariableContext ctx) {
55+
return KalaNode.mkIdent(ctx.getText());
56+
}
57+
58+
@Override
59+
public KalaNode visitNull(NullContext ctx) {
60+
return KalaNode.mkNull();
61+
}
62+
63+
@Override
64+
public KalaNode visitListElement(ListElementContext ctx) {
65+
return visit(ctx.list());
66+
}
67+
};
68+
return visitor.visit(tree);
69+
}
70+
71+
static void main() {
72+
KalaNode kalaAst = makeKalaAst("(kala, (x,y , null, (), (kala,()) ))");
73+
System.out.println(kalaAst); // (kala, (x, y, NULL, (), (kala, ())))
74+
75+
Map<String, Integer> env = new HashMap<>();
76+
env.put("kala", 1);
77+
env.put("x", 2);
78+
env.put("y", 3);
79+
80+
System.out.println(kalaAst.sum(env)); // 7
81+
}
82+
}

0 commit comments

Comments
 (0)