summaryrefslogtreecommitdiff
path: root/parser/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--parser/src/main/java/lv/enes/orang/parser/Parser.java (renamed from orang/src/main/java/lv/enes/orang/Parser.java)129
-rw-r--r--parser/src/main/java/lv/enes/orang/parser/ParserException.java (renamed from orang/src/main/java/lv/enes/orang/ParserException.java)2
-rw-r--r--parser/src/main/java/module-info.java8
3 files changed, 95 insertions, 44 deletions
diff --git a/orang/src/main/java/lv/enes/orang/Parser.java b/parser/src/main/java/lv/enes/orang/parser/Parser.java
index 77abe24..6c86e85 100644
--- a/orang/src/main/java/lv/enes/orang/Parser.java
+++ b/parser/src/main/java/lv/enes/orang/parser/Parser.java
@@ -1,9 +1,12 @@
1package lv.enes.orang; 1package lv.enes.orang.parser;
2 2
3import lv.enes.orang.ast.*; 3import lv.enes.orang.ast.*;
4import lv.enes.orang.ast.IfElseExpression; 4import lv.enes.orang.ast.IfElseExpression;
5import lv.enes.orang.ast.Statement; 5import lv.enes.orang.ast.Statement;
6import lv.enes.orang.lexer.Lexer;
7import lv.enes.orang.lexer.Token;
6import lv.enes.orang.utils.NonEmptyList; 8import lv.enes.orang.utils.NonEmptyList;
9import lv.enes.orang.utils.PeekableStream;
7 10
8import java.io.InputStream; 11import java.io.InputStream;
9import java.io.Reader; 12import java.io.Reader;
@@ -49,13 +52,53 @@ public class Parser {
49 52
50 public Program parseProgram() throws ParserException { 53 public Program parseProgram() throws ParserException {
51 var statements = new ArrayList<Statement>(); 54 var statements = new ArrayList<Statement>();
52 while (!maybeConsumeToken(TokenType.EOF)) { 55 while (!maybeConsumeToken(Token.Type.EOF)) {
53 statements.add(parseStatement()); 56 statements.add(parseStatement());
54 maybeConsumeToken(TokenType.SEMICOLON); 57 maybeConsumeToken(Token.Type.SEMICOLON);
55 } 58 }
56 return new Program(Collections.unmodifiableList(statements)); 59 return new Program(Collections.unmodifiableList(statements));
57 } 60 }
58 61
62 private static boolean isBinaryOp(Token token) {
63 return switch (token.type()) {
64 case ASTERISK, SLASH, PLUS, MINUS, QUESTION_EQUAL, SLASH_EQUAL, GREATER, GREATER_EQUAL, LESS, LESS_EQUAL
65 -> true;
66 default -> false;
67 };
68 }
69
70 private static BinaryExpression.Operator toBinaryOp(Token token) {
71 return switch (token.type()) {
72 case ASTERISK -> BinaryExpression.Operator.MULTIPLY;
73 case SLASH -> BinaryExpression.Operator.DIVIDE;
74 case PLUS -> BinaryExpression.Operator.ADD;
75 case MINUS -> BinaryExpression.Operator.SUBTRACT;
76 case QUESTION_EQUAL -> BinaryExpression.Operator.EQUALS;
77 case SLASH_EQUAL -> BinaryExpression.Operator.NOT_EQUALS;
78 case GREATER -> BinaryExpression.Operator.GT;
79 case GREATER_EQUAL -> BinaryExpression.Operator.GTE;
80 case LESS -> BinaryExpression.Operator.LT;
81 case LESS_EQUAL -> BinaryExpression.Operator.LTE;
82 default -> throw new IllegalStateException(STR."Token \{token.type()} is not a binary operator");
83 };
84 }
85
86 public static boolean isUnaryOp(Token token) {
87 return switch (token.type()) {
88 case PLUS, MINUS, BANG -> true;
89 default -> false;
90 };
91 }
92
93 public static UnaryExpression.Operator toUnaryOp(Token token) {
94 return switch (token.type()) {
95 case PLUS -> UnaryExpression.Operator.PLUS;
96 case MINUS -> UnaryExpression.Operator.NEGATE;
97 case BANG -> UnaryExpression.Operator.NOT;
98 default -> throw new IllegalStateException(STR."Token \{token.type()} is not a unary operator");
99 };
100 }
101
59 private Token consume(Predicate<Token> pred, String msg) throws ParserException { 102 private Token consume(Predicate<Token> pred, String msg) throws ParserException {
60 var tok = input.next(); 103 var tok = input.next();
61 if (!pred.test(tok)) { 104 if (!pred.test(tok)) {
@@ -64,11 +107,11 @@ public class Parser {
64 return tok; 107 return tok;
65 } 108 }
66 109
67 private Token consumeToken(TokenType type) throws ParserException { 110 private Token consumeToken(Token.Type type) throws ParserException {
68 return consume(tok -> tok.type() == type, STR."Expected \{type}"); 111 return consume(tok -> tok.type() == type, STR."Expected \{type}");
69 } 112 }
70 113
71 private boolean maybeConsumeToken(TokenType type) { 114 private boolean maybeConsumeToken(Token.Type type) {
72 if (input.peek().type() == type) { 115 if (input.peek().type() == type) {
73 input.next(); 116 input.next();
74 return true; 117 return true;
@@ -77,16 +120,16 @@ public class Parser {
77 } 120 }
78 121
79 private ArrayExpression parseArray() throws ParserException { 122 private ArrayExpression parseArray() throws ParserException {
80 consumeToken(TokenType.BRACKET_LEFT); 123 consumeToken(Token.Type.BRACKET_LEFT);
81 if (maybeConsumeToken(TokenType.BRACKET_RIGHT)) { 124 if (maybeConsumeToken(Token.Type.BRACKET_RIGHT)) {
82 return new ArrayExpression(List.of()); 125 return new ArrayExpression(List.of());
83 } 126 }
84 127
85 var items = new ArrayList<Expression>(); 128 var items = new ArrayList<Expression>();
86 do { 129 do {
87 items.add(parseExpression()); 130 items.add(parseExpression());
88 } while (maybeConsumeToken(TokenType.COMMA)); 131 } while (maybeConsumeToken(Token.Type.COMMA));
89 consumeToken(TokenType.BRACKET_RIGHT); 132 consumeToken(Token.Type.BRACKET_RIGHT);
90 133
91 return new ArrayExpression(Collections.unmodifiableList(items)); 134 return new ArrayExpression(Collections.unmodifiableList(items));
92 } 135 }
@@ -94,11 +137,11 @@ public class Parser {
94 private List<ArgSpec> parseArgSpecs() throws ParserException { 137 private List<ArgSpec> parseArgSpecs() throws ParserException {
95 var argSpecs = new ArrayList<ArgSpec>(); 138 var argSpecs = new ArrayList<ArgSpec>();
96 while (true) { 139 while (true) {
97 if (input.peek().type() == TokenType.IDENTIFIER) { 140 if (input.peek().type() == Token.Type.IDENTIFIER) {
98 argSpecs.add(ArgSpec.named(input.next().literal())); 141 argSpecs.add(ArgSpec.named(input.next().literal()));
99 } else if (input.peek().type() == TokenType.PAREN_LEFT) { 142 } else if (input.peek().type() == Token.Type.PAREN_LEFT) {
100 consumeToken(TokenType.PAREN_LEFT); 143 consumeToken(Token.Type.PAREN_LEFT);
101 consumeToken(TokenType.PAREN_RIGHT); 144 consumeToken(Token.Type.PAREN_RIGHT);
102 argSpecs.add(ArgSpec.nothing()); 145 argSpecs.add(ArgSpec.nothing());
103 } else { 146 } else {
104 break; 147 break;
@@ -109,20 +152,20 @@ public class Parser {
109 152
110 private Expression parseBinaryExpression() throws ParserException { 153 private Expression parseBinaryExpression() throws ParserException {
111 var lhs = parseCallExpression(); 154 var lhs = parseCallExpression();
112 if (!input.peek().type().isBinaryOp()) { 155 if (!isBinaryOp(input.peek())) {
113 return lhs; 156 return lhs;
114 } 157 }
115 158
116 return parseBinaryExpressionRhs(lhs, input.next().type().toBinaryOp()); 159 return parseBinaryExpressionRhs(lhs, toBinaryOp(input.next()));
117 } 160 }
118 161
119 private Expression parseBinaryExpressionRhs(Expression lhs, BinaryExpression.Operator op) throws ParserException { 162 private Expression parseBinaryExpressionRhs(Expression lhs, BinaryExpression.Operator op) throws ParserException {
120 var rhs = parseCallExpression(); 163 var rhs = parseCallExpression();
121 if (!input.peek().type().isBinaryOp()) { 164 if (!isBinaryOp(input.peek())) {
122 return new BinaryExpression(op, lhs, rhs); 165 return new BinaryExpression(op, lhs, rhs);
123 } 166 }
124 167
125 var op2 = input.next().type().toBinaryOp(); 168 var op2 = toBinaryOp(input.next());
126 if (op2.bindsStrongerThan(op)) { 169 if (op2.bindsStrongerThan(op)) {
127 return new BinaryExpression(op, lhs, parseBinaryExpressionRhs(rhs, op2)); 170 return new BinaryExpression(op, lhs, parseBinaryExpressionRhs(rhs, op2));
128 } else { 171 } else {
@@ -131,8 +174,8 @@ public class Parser {
131 } 174 }
132 175
133 private BooleanLiteral parseBoolean() throws ParserException { 176 private BooleanLiteral parseBoolean() throws ParserException {
134 var t = consume(tok -> tok.type() == TokenType.FALSE || tok.type() == TokenType.TRUE, "Expected TRUE or FALSE"); 177 var t = consume(tok -> tok.type() == Token.Type.FALSE || tok.type() == Token.Type.TRUE, "Expected TRUE or FALSE");
135 return new BooleanLiteral(t.type() == TokenType.TRUE); 178 return new BooleanLiteral(t.type() == Token.Type.TRUE);
136 } 179 }
137 180
138 private Expression parseCallExpression() throws ParserException { 181 private Expression parseCallExpression() throws ParserException {
@@ -145,9 +188,9 @@ public class Parser {
145 } 188 }
146 189
147 private Definition parseDefinition() throws ParserException { 190 private Definition parseDefinition() throws ParserException {
148 consumeToken(TokenType.DEF); 191 consumeToken(Token.Type.DEF);
149 var defSpec = parseDefSpec(); 192 var defSpec = parseDefSpec();
150 consumeToken(TokenType.EQUAL); 193 consumeToken(Token.Type.EQUAL);
151 var value = parseExpression(); 194 var value = parseExpression();
152 if (defSpec.args().isEmpty()) { 195 if (defSpec.args().isEmpty()) {
153 return new Definition(defSpec.name(), value); 196 return new Definition(defSpec.name(), value);
@@ -157,59 +200,59 @@ public class Parser {
157 } 200 }
158 201
159 private DefSpec parseDefSpec() throws ParserException { 202 private DefSpec parseDefSpec() throws ParserException {
160 var name = consumeToken(TokenType.IDENTIFIER).literal(); 203 var name = consumeToken(Token.Type.IDENTIFIER).literal();
161 var argSpecs = parseArgSpecs(); 204 var argSpecs = parseArgSpecs();
162 return new DefSpec(name, argSpecs); 205 return new DefSpec(name, argSpecs);
163 } 206 }
164 207
165 private DoExpression parseDoExpression() throws ParserException { 208 private DoExpression parseDoExpression() throws ParserException {
166 consumeToken(TokenType.DO); 209 consumeToken(Token.Type.DO);
167 var exprs = new ArrayList<Expression>(); 210 var exprs = new ArrayList<Expression>();
168 do { 211 do {
169 exprs.add(parseExpression()); 212 exprs.add(parseExpression());
170 } while (maybeConsumeToken(TokenType.SEMICOLON)); 213 } while (maybeConsumeToken(Token.Type.SEMICOLON));
171 consumeToken(TokenType.END); 214 consumeToken(Token.Type.END);
172 return new DoExpression(Collections.unmodifiableList(exprs)); 215 return new DoExpression(Collections.unmodifiableList(exprs));
173 } 216 }
174 217
175 private Expression parseExpression() throws ParserException { 218 private Expression parseExpression() throws ParserException {
176 if (input.peek().type().isUnaryOp()) { 219 if (isUnaryOp(input.peek())) {
177 return parseUnaryExpression(); 220 return parseUnaryExpression();
178 } 221 }
179 return parseBinaryExpression(); 222 return parseBinaryExpression();
180 } 223 }
181 224
182 private FnExpression parseFnExpression() throws ParserException { 225 private FnExpression parseFnExpression() throws ParserException {
183 consumeToken(TokenType.FN); 226 consumeToken(Token.Type.FN);
184 var argSpecs = parseArgSpecs(); 227 var argSpecs = parseArgSpecs();
185 if (argSpecs.isEmpty()) { 228 if (argSpecs.isEmpty()) {
186 throw new ParserException("Function definition with no arguments"); 229 throw new ParserException("Function definition with no arguments");
187 } 230 }
188 var body = maybeConsumeToken(TokenType.MINUS_GREATER) ? parseExpression() : parseDoExpression(); 231 var body = maybeConsumeToken(Token.Type.MINUS_GREATER) ? parseExpression() : parseDoExpression();
189 return new FnExpression(new NonEmptyList<>(argSpecs), body); 232 return new FnExpression(new NonEmptyList<>(argSpecs), body);
190 } 233 }
191 234
192 private IfElseExpression parseIfElseExpression() throws ParserException { 235 private IfElseExpression parseIfElseExpression() throws ParserException {
193 consumeToken(TokenType.IF); 236 consumeToken(Token.Type.IF);
194 var cond = parseExpression(); 237 var cond = parseExpression();
195 consumeToken(TokenType.THEN); 238 consumeToken(Token.Type.THEN);
196 var trueBranch = parseExpression(); 239 var trueBranch = parseExpression();
197 consumeToken(TokenType.ELSE); 240 consumeToken(Token.Type.ELSE);
198 var falseBranch = parseExpression(); 241 var falseBranch = parseExpression();
199 return new IfElseExpression(cond, trueBranch, falseBranch); 242 return new IfElseExpression(cond, trueBranch, falseBranch);
200 } 243 }
201 244
202 private IntLiteral parseInteger() throws ParserException { 245 private IntLiteral parseInteger() throws ParserException {
203 var tok = consumeToken(TokenType.INTEGER); 246 var tok = consumeToken(Token.Type.INTEGER);
204 return new IntLiteral(Integer.parseInt(tok.literal())); 247 return new IntLiteral(Integer.parseInt(tok.literal()));
205 } 248 }
206 249
207 private LetInExpression parseLetInExpression() throws ParserException { 250 private LetInExpression parseLetInExpression() throws ParserException {
208 consumeToken(TokenType.LET); 251 consumeToken(Token.Type.LET);
209 var bindings = new ArrayList<LetInExpression.Binding>(); 252 var bindings = new ArrayList<LetInExpression.Binding>();
210 do { 253 do {
211 var defSpec = parseDefSpec(); 254 var defSpec = parseDefSpec();
212 consumeToken(TokenType.EQUAL); 255 consumeToken(Token.Type.EQUAL);
213 var value = parseExpression(); 256 var value = parseExpression();
214 if (defSpec.args().isEmpty()) { 257 if (defSpec.args().isEmpty()) {
215 bindings.add(new LetInExpression.Binding(defSpec.name(), value)); 258 bindings.add(new LetInExpression.Binding(defSpec.name(), value));
@@ -217,8 +260,8 @@ public class Parser {
217 var fn = new FnExpression(new NonEmptyList<>(defSpec.args()), value); 260 var fn = new FnExpression(new NonEmptyList<>(defSpec.args()), value);
218 bindings.add(new LetInExpression.Binding(defSpec.name(), fn)); 261 bindings.add(new LetInExpression.Binding(defSpec.name(), fn));
219 } 262 }
220 } while (maybeConsumeToken(TokenType.AND)); 263 } while (maybeConsumeToken(Token.Type.AND));
221 consumeToken(TokenType.IN); 264 consumeToken(Token.Type.IN);
222 var body = parseExpression(); 265 var body = parseExpression();
223 return new LetInExpression(Collections.unmodifiableList(bindings), body); 266 return new LetInExpression(Collections.unmodifiableList(bindings), body);
224 } 267 }
@@ -226,12 +269,12 @@ public class Parser {
226 private Expression parseSimpleExpression() throws ParserException { 269 private Expression parseSimpleExpression() throws ParserException {
227 return switch (input.peek().type()) { 270 return switch (input.peek().type()) {
228 case PAREN_LEFT -> { 271 case PAREN_LEFT -> {
229 consumeToken(TokenType.PAREN_LEFT); 272 consumeToken(Token.Type.PAREN_LEFT);
230 if (maybeConsumeToken(TokenType.PAREN_RIGHT)) { 273 if (maybeConsumeToken(Token.Type.PAREN_RIGHT)) {
231 yield VoidExpression.INSTANCE; 274 yield VoidExpression.INSTANCE;
232 } 275 }
233 var expr = parseExpression(); 276 var expr = parseExpression();
234 consumeToken(TokenType.PAREN_RIGHT); 277 consumeToken(Token.Type.PAREN_RIGHT);
235 yield expr; 278 yield expr;
236 } 279 }
237 case TRUE, FALSE -> parseBoolean(); 280 case TRUE, FALSE -> parseBoolean();
@@ -247,7 +290,7 @@ public class Parser {
247 }; 290 };
248 } 291 }
249 292
250 private boolean couldStartSimpleExpression(TokenType type) { 293 private boolean couldStartSimpleExpression(Token.Type type) {
251 return switch (type) { 294 return switch (type) {
252 case PAREN_LEFT, TRUE, FALSE, INTEGER, IDENTIFIER, STRING, BRACKET_LEFT, IF, LET, FN, DO -> true; 295 case PAREN_LEFT, TRUE, FALSE, INTEGER, IDENTIFIER, STRING, BRACKET_LEFT, IF, LET, FN, DO -> true;
253 default -> false; 296 default -> false;
@@ -255,7 +298,7 @@ public class Parser {
255 } 298 }
256 299
257 private Statement parseStatement() throws ParserException { 300 private Statement parseStatement() throws ParserException {
258 if (input.peek().type() == TokenType.DEF) { 301 if (input.peek().type() == Token.Type.DEF) {
259 return parseDefinition(); 302 return parseDefinition();
260 } else { 303 } else {
261 return new ExpressionStatement(parseExpression()); 304 return new ExpressionStatement(parseExpression());
@@ -286,8 +329,8 @@ public class Parser {
286 } 329 }
287 330
288 private Expression parseUnaryExpression() throws ParserException { 331 private Expression parseUnaryExpression() throws ParserException {
289 if (input.peek().type().isUnaryOp()) { 332 if (isUnaryOp(input.peek())) {
290 var op = input.next().type().toUnaryOp(); 333 var op = toUnaryOp(input.next());
291 return new UnaryExpression(op, parseUnaryExpression()); 334 return new UnaryExpression(op, parseUnaryExpression());
292 } else { 335 } else {
293 return parseSimpleExpression(); 336 return parseSimpleExpression();
diff --git a/orang/src/main/java/lv/enes/orang/ParserException.java b/parser/src/main/java/lv/enes/orang/parser/ParserException.java
index bd65e7a..632ce15 100644
--- a/orang/src/main/java/lv/enes/orang/ParserException.java
+++ b/parser/src/main/java/lv/enes/orang/parser/ParserException.java
@@ -1,4 +1,4 @@
1package lv.enes.orang; 1package lv.enes.orang.parser;
2 2
3import lv.enes.orang.core.OrangException; 3import lv.enes.orang.core.OrangException;
4 4
diff --git a/parser/src/main/java/module-info.java b/parser/src/main/java/module-info.java
new file mode 100644
index 0000000..43c2dc5
--- /dev/null
+++ b/parser/src/main/java/module-info.java
@@ -0,0 +1,8 @@
1module lv.enes.orang.parser {
2 exports lv.enes.orang.parser;
3
4 requires lv.enes.orang.ast;
5 requires lv.enes.orang.core;
6 requires lv.enes.orang.lexer;
7 requires lv.enes.orang.utils;
8} \ No newline at end of file