Skip to content

Commit c2f3431

Browse files
committed
feat: IF ELSE statements
1 parent dd14509 commit c2f3431

File tree

9 files changed

+194
-24
lines changed

9 files changed

+194
-24
lines changed

jlox/.idea/vcs.xml

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/com/jlox/Interpreter.java

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,20 +54,65 @@ Token peek() {
5454
return this.tokens.get(this.current);
5555
}
5656

57-
List<Expr> Parse() {
58-
List<Expr> x = new ArrayList<>();
57+
List<Stmt> Parse() {
58+
List<Stmt> x = new ArrayList<>();
5959
while (!isAtEnd()) {
6060
x.add(declaration());
6161
}
6262
return x;
6363
}
6464

65-
Expr declaration() {
65+
Stmt declaration() {
66+
return statement();
67+
}
68+
69+
Stmt statement() {
70+
if (match(TokenType.PRINT)) return printStatement();
71+
if (match(TokenType.IF)) return ifStatement();
72+
73+
// if (match(TokenType.LEFT_BRACE)) {
74+
// return block();
75+
// }
76+
77+
return expressionStmt();
78+
}
79+
80+
Stmt block() {
81+
List<Stmt> stmts = new ArrayList<>();
82+
this.eat(TokenType.LEFT_BRACE, "");
83+
while (!match(TokenType.RIGHT_BRACE) && !isAtEnd()) {
84+
stmts.add(statement());
85+
}
86+
return new Stmt.Block(stmts);
87+
}
88+
89+
Stmt ifStatement() {
90+
this.eat(TokenType.LEFT_PAREN, "Missing ( at the start of if-condition");
91+
Expr e = expression();
92+
this.eat(TokenType.RIGHT_PAREN, "Missing ) at the end of if-condition");
93+
94+
Stmt ifBlock = block();
95+
Stmt elseBlock = null;
96+
if (match(TokenType.ELSE)) {
97+
elseBlock = block();
98+
}
99+
100+
return new Stmt.IfStmt(e, ifBlock, elseBlock);
101+
}
102+
103+
Stmt printStatement() {
104+
Expr e = expression();
105+
this.eat(TokenType.SEMICOLON, "");
106+
return new Stmt.PrintStmt(e);
107+
}
108+
109+
Stmt expressionStmt() {
66110
Expr expr = expression();
67111
this.eat(TokenType.SEMICOLON, "");
68-
return expr;
112+
return new Stmt.ExpressionStmt(expr);
69113
}
70114

115+
71116
Expr expression() {
72117
return assignment();
73118
}
@@ -112,16 +157,16 @@ Expr and() {
112157
}
113158

114159
Expr equality() {
115-
Expr expr = comparision();
160+
Expr expr = comparison();
116161
while (match(TokenType.EQUALS, TokenType.NOT_EQUALS)) {
117162
Token op = previous();
118-
Expr right = comparision();
163+
Expr right = comparison();
119164
expr = new Expr.Binary(expr, op, right);
120165
}
121166
return expr;
122167
}
123168

124-
Expr comparision() {
169+
Expr comparison() {
125170
Expr expr = term();
126171
while (match(TokenType.GREATER_THAN, TokenType.GREATER_THAN_OR_EQUAL, TokenType.LESS_THAN, TokenType.LESS_THAN_OR_EQUAL)) {
127172
Token op = previous();
@@ -173,7 +218,6 @@ Expr primary() {
173218
}
174219

175220
if (match(TokenType.IDENTIFIER)) {
176-
// System.out.println("prev = " + previous());
177221
return new Expr.Variable(previous());
178222
}
179223
if (match(TokenType.LEFT_PAREN)) {
@@ -184,4 +228,4 @@ Expr primary() {
184228

185229
throw new RuntimeException("Error parsing source");
186230
}
187-
}
231+
}

src/com/jlox/Lox.java

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.jlox;
22

3+
import com.jlox.Stmt.ExpressionStmt;
4+
35
import java.io.IOException;
46
import java.nio.file.Files;
57
import java.nio.file.Paths;
@@ -8,7 +10,7 @@
810
import java.util.Map;
911
import java.util.Objects;
1012

11-
class Lox implements Expr.Visitor<Object> {
13+
class Lox implements Expr.Visitor<Object>, Stmt.Visitor<Void> {
1214
Map<Object, Object> symbolTable;
1315

1416
Lox() {
@@ -20,13 +22,13 @@ private void run(String source) {
2022
List<Token> tokens = s.scanTokens();
2123

2224
Interpreter p = new Interpreter(tokens);
23-
List<Expr> exprs = p.Parse();
25+
List<Stmt> stmts = p.Parse();
2426

25-
for (Expr e : exprs) {
26-
e.accept(this);
27+
for (Stmt stmt : stmts) {
28+
stmt.accept(this);
2729
}
2830

29-
this.printSymbolTable();
31+
// this.printSymbolTable();
3032
}
3133

3234
void printSymbolTable() {
@@ -47,6 +49,10 @@ Object eval(Expr expr) {
4749
return expr.accept(this);
4850
}
4951

52+
void execute(Stmt stmt) {
53+
stmt.accept(this);
54+
}
55+
5056
@Override
5157
public Object visitBinaryExpr(Expr.Binary expr) {
5258
Object l = eval(expr.left);
@@ -208,4 +214,37 @@ public Object visitUnaryExpr(Expr.Unary expr) {
208214
}
209215
return null;
210216
}
217+
218+
@Override
219+
public Void visitExpressionStmt(Stmt.ExpressionStmt stmt) {
220+
eval(stmt.expression);
221+
return null;
222+
}
223+
224+
@Override
225+
public Void visitPrintStmt(Stmt.PrintStmt stmt) {
226+
Object o = eval(stmt.expression);
227+
System.out.println(o);
228+
return null;
229+
}
230+
231+
@Override
232+
public Void visitIfStmt(Stmt.IfStmt stmt) {
233+
Object condition = eval(stmt.condition);
234+
if (isTruth(condition)) {
235+
execute(stmt.thenBranch);
236+
} else {
237+
execute(stmt.elseBranch);
238+
}
239+
240+
return null;
241+
}
242+
243+
@Override
244+
public Void visitBlock(Stmt.Block stmt) {
245+
for (Stmt s: stmt.statements) {
246+
execute(s);
247+
}
248+
return null;
249+
}
211250
}

src/com/jlox/Scanner.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ void buildKeywords() {
2323
this.keywords.put("false", TokenType.FALSE);
2424
this.keywords.put("pass", TokenType.PASS);
2525
this.keywords.put("return", TokenType.RETURN);
26+
this.keywords.put("print", TokenType.PRINT);
2627
}
2728

2829
Scanner(String source) {
@@ -107,16 +108,16 @@ void scanToken() {
107108
this.addToken(TokenType.MINUS);
108109
break;
109110
case '(':
110-
this.addToken(TokenType.LEFT_BRACE);
111+
this.addToken(TokenType.LEFT_PAREN);
111112
break;
112113
case ')':
113-
this.addToken(TokenType.RIGHT_BRACE);
114+
this.addToken(TokenType.RIGHT_PAREN);
114115
break;
115116
case '{':
116-
this.addToken(TokenType.LEFT_PAREN);
117+
this.addToken(TokenType.LEFT_BRACE);
117118
break;
118119
case '}':
119-
this.addToken(TokenType.RIGHT_PAREN);
120+
this.addToken(TokenType.RIGHT_BRACE);
120121
break;
121122
case ',':
122123
this.addToken(TokenType.COMMA);

src/com/jlox/Stmt.java

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package com.jlox;
2+
3+
import java.util.List;
4+
5+
abstract class Stmt {
6+
interface Visitor<R> {
7+
R visitExpressionStmt(ExpressionStmt stmt);
8+
R visitPrintStmt(PrintStmt stmt);
9+
R visitBlock(Block stmt);
10+
R visitIfStmt(IfStmt stmt);
11+
}
12+
13+
abstract <R> R accept(Stmt.Visitor<R> visitor);
14+
15+
static class PrintStmt extends Stmt {
16+
Expr expression;
17+
18+
PrintStmt(Expr expression) {
19+
this.expression = expression;
20+
}
21+
22+
@Override
23+
<R> R accept(Stmt.Visitor<R> visitor) {
24+
return visitor.visitPrintStmt(this);
25+
}
26+
}
27+
28+
static class ExpressionStmt extends Stmt {
29+
Expr expression;
30+
31+
ExpressionStmt(Expr expression) {
32+
this.expression = expression;
33+
}
34+
35+
@Override
36+
<R> R accept(Stmt.Visitor<R> visitor) {
37+
return visitor.visitExpressionStmt(this);
38+
}
39+
}
40+
41+
static class Block extends Stmt {
42+
List<Stmt> statements;
43+
44+
Block(List<Stmt> statements) {
45+
this.statements = statements;
46+
}
47+
48+
@Override
49+
<R> R accept(Stmt.Visitor<R> visitor) {
50+
return visitor.visitBlock(this);
51+
}
52+
}
53+
54+
55+
static class IfStmt extends Stmt {
56+
Expr condition;
57+
Stmt thenBranch;
58+
Stmt elseBranch;
59+
60+
IfStmt(Expr condition, Stmt thenBranch, Stmt elseBranch) {
61+
this.condition = condition;
62+
this.thenBranch = thenBranch;
63+
this.elseBranch = elseBranch;
64+
}
65+
66+
@Override
67+
<R> R accept(Stmt.Visitor<R> visitor) {
68+
return visitor.visitIfStmt(this);
69+
}
70+
}
71+
}

src/com/jlox/TokenType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ enum TokenType {
1919
ELSE,
2020
PASS,
2121
RETURN,
22+
PRINT,
2223

2324
NOT,
2425
EQUALS,

src/com/jlox/jlox.gram

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ expression ::= assignment;
99
assignment ::= or | IDENTIFIER "=" assignment;
1010
or ::= and | ("or" and)*;
1111
and ::= equality | ("and" equality)*;
12-
equality ::= comparision | (("==" | "!=") comparision)*;
13-
comparision ::= term | ( (">=" | "<=" | ">" | "<") term)*;
12+
equality ::= comparison | (("==" | "!=") comparison)*;
13+
comparison ::= term | ( (">=" | "<=" | ">" | "<") term)*;
1414
term ::= factor | (("+" | "-") factor)*;
1515
factor ::= unary | (("*" | "/") unary)*;
1616
unary ::= ("-" | "!") unary | primary;

src/com/jlox/source.jlox

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1-
a = 10;
2-
a = 1 + a;
3-
b = "mano " + "sriram";
1+
a = 100;
2+
3+
if (1 == 1 and 1 == 1) {
4+
a = a;
5+
}
6+
7+
print a;

src/jlox.iml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<module type="JAVA_MODULE" version="4">
3+
<component name="NewModuleRootManager" inherit-compiler-output="true">
4+
<exclude-output />
5+
<content url="file://$MODULE_DIR$">
6+
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
7+
</content>
8+
<orderEntry type="inheritedJdk" />
9+
<orderEntry type="sourceFolder" forTests="false" />
10+
</component>
11+
</module>

0 commit comments

Comments
 (0)