-
Notifications
You must be signed in to change notification settings - Fork 0
/
Parser.java
123 lines (95 loc) · 2.67 KB
/
Parser.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package com.ayomideoyekanmi.explanck.interpreter;
import java.util.List;
/**
* @author: aoyekanmi
* @date: 11/03/2022
*/
public class Parser {
private static class ParseError extends RuntimeException {
}
private final List<Token> tokens;
int current = 0;
Parser(List<Token> tokens) {
this.tokens = tokens;
}
Expr parse() {
try {
return expression();
} catch (ParseError error) {
return null;
}
}
private Expr expression() {
return term();
}
private Expr term() {
Expr expr = factor();
// 2 + 3 + 3 + 4;
while (match(TokenType.MINUS, TokenType.PLUS)) {
Token operator = previous();
Expr right = factor();
expr = new Expr.Binary(expr, operator, right);
}
return expr;
}
private Expr factor() {
Expr expr = power();
while (match(TokenType.STAR, TokenType.SLASH)) {
Token operator = previous();
Expr right = power();
expr = new Expr.Binary(expr, operator, right);
}
return expr;
}
private Expr power() {
Expr expr = primary();
while (match(TokenType.POWER)) {
Token operator = previous();
Expr right = primary();
expr = new Expr.Binary(expr, operator, right);
}
return expr;
}
private Expr primary() {
if (match(TokenType.NUMBER)) {
return new Expr.Literal(previous().literal);
}
if (match(TokenType.LEFT_PAREN)) {
Expr expr = expression();
// Confirm the there's a right parenthesis or throw error
if (peek().type != TokenType.RIGHT_PAREN) {
throw error("Expect ')' after expression");
}
advance();
return new Expr.Grouping(expr);
}
throw error("Expect expression.");
}
// Checks if the current character is one of the types
private boolean match(TokenType... types) {
if (isAtEnd()) return false;
for (TokenType type : types) {
if (peek().type == type) {
advance();
return true;
}
}
return false;
}
private Token peek() {
return tokens.get(current);
}
private void advance() {
if (!isAtEnd()) current++;
}
private Token previous() {
return tokens.get(current - 1);
}
private boolean isAtEnd() {
return current >= tokens.size();
}
private ParseError error(String message) {
Explanck.error(message);
return new ParseError();
}
}