diff options
| author | 2024-08-24 03:54:25 +0800 | |
|---|---|---|
| committer | 2024-08-24 03:54:25 +0800 | |
| commit | 16a20ee8b08df919e93ea1b878013f9a2ad709fa (patch) | |
| tree | 80d59e93c566ddba1e2116e8d64222b8036b216e /parser/src/main/java | |
| parent | Add tuples. (diff) | |
| download | orang-16a20ee8b08df919e93ea1b878013f9a2ad709fa.tar.gz orang-16a20ee8b08df919e93ea1b878013f9a2ad709fa.tar.xz orang-16a20ee8b08df919e93ea1b878013f9a2ad709fa.zip | |
Added fancier tuple argument specs.
Made ArgSpec use visitor pattern to avoid problems the best way.
Merged empty tuple and non-empty tuple classes.
Diffstat (limited to 'parser/src/main/java')
| -rw-r--r-- | parser/src/main/java/lv/enes/orang/parser/Parser.java | 59 |
1 files changed, 44 insertions, 15 deletions
diff --git a/parser/src/main/java/lv/enes/orang/parser/Parser.java b/parser/src/main/java/lv/enes/orang/parser/Parser.java index 0ff1f78..06183a3 100644 --- a/parser/src/main/java/lv/enes/orang/parser/Parser.java +++ b/parser/src/main/java/lv/enes/orang/parser/Parser.java | |||
| @@ -131,23 +131,51 @@ public class Parser { | |||
| 131 | 131 | ||
| 132 | private List<ArgSpec> parseArgSpecs() throws ParserException { | 132 | private List<ArgSpec> parseArgSpecs() throws ParserException { |
| 133 | var argSpecs = new ArrayList<ArgSpec>(); | 133 | var argSpecs = new ArrayList<ArgSpec>(); |
| 134 | while (true) { | 134 | while (couldStartArgSpec(input.peek().type())) { |
| 135 | if (input.peek().type() == Token.Type.IDENTIFIER) { | 135 | argSpecs.add(parseArgSpec()); |
| 136 | argSpecs.add(ArgSpec.named(input.next().literal())); | ||
| 137 | } else if (input.peek().type() == Token.Type.PAREN_LEFT) { | ||
| 138 | consumeToken(Token.Type.PAREN_LEFT); | ||
| 139 | consumeToken(Token.Type.PAREN_RIGHT); | ||
| 140 | argSpecs.add(ArgSpec.nothing()); | ||
| 141 | } else if (input.peek().type() == Token.Type.UNDERSCORE) { | ||
| 142 | consumeToken(Token.Type.UNDERSCORE); | ||
| 143 | argSpecs.add(ArgSpec.ignored()); | ||
| 144 | } else { | ||
| 145 | break; | ||
| 146 | } | ||
| 147 | } | 136 | } |
| 137 | argSpecs.trimToSize(); | ||
| 148 | return Collections.unmodifiableList(argSpecs); | 138 | return Collections.unmodifiableList(argSpecs); |
| 149 | } | 139 | } |
| 150 | 140 | ||
| 141 | private boolean couldStartArgSpec(Token.Type type) { | ||
| 142 | return switch (type) { | ||
| 143 | case IDENTIFIER, PAREN_LEFT, UNDERSCORE -> true; | ||
| 144 | default -> false; | ||
| 145 | }; | ||
| 146 | } | ||
| 147 | |||
| 148 | private ArgSpec parseArgSpec() throws ParserException { | ||
| 149 | var token = input.next(); | ||
| 150 | return switch (token.type()) { | ||
| 151 | case IDENTIFIER -> new ArgSpecNamed(token.literal()); | ||
| 152 | case PAREN_LEFT -> { | ||
| 153 | if (maybeConsumeToken(Token.Type.PAREN_RIGHT)) { | ||
| 154 | yield new ArgSpecTuple(List.of()); | ||
| 155 | } | ||
| 156 | var argspec = parseArgSpec(); | ||
| 157 | if (maybeConsumeToken(Token.Type.COMMA)) { | ||
| 158 | yield parseArgSpecTuple(argspec); | ||
| 159 | } | ||
| 160 | consumeToken(Token.Type.PAREN_RIGHT); | ||
| 161 | yield argspec; | ||
| 162 | } | ||
| 163 | case UNDERSCORE -> ArgSpecIgnored.INSTANCE; | ||
| 164 | default -> throw new ParserException(STR."Unexpected token when parsing argspecs: \{token}"); | ||
| 165 | }; | ||
| 166 | } | ||
| 167 | |||
| 168 | private ArgSpec parseArgSpecTuple(ArgSpec first) throws ParserException { | ||
| 169 | var specs = new ArrayList<ArgSpec>(); | ||
| 170 | specs.add(first); | ||
| 171 | do { | ||
| 172 | specs.add(parseArgSpec()); | ||
| 173 | maybeConsumeToken(Token.Type.COMMA); | ||
| 174 | } while (!maybeConsumeToken(Token.Type.PAREN_RIGHT)); | ||
| 175 | specs.trimToSize(); | ||
| 176 | return new ArgSpecTuple(specs); | ||
| 177 | } | ||
| 178 | |||
| 151 | private Expression parseBinaryExpression() throws ParserException { | 179 | private Expression parseBinaryExpression() throws ParserException { |
| 152 | var lhs = parseCallExpression(); | 180 | var lhs = parseCallExpression(); |
| 153 | if (isNotBinaryOp(input.peek())) { | 181 | if (isNotBinaryOp(input.peek())) { |
| @@ -283,7 +311,7 @@ public class Parser { | |||
| 283 | case PAREN_LEFT -> { | 311 | case PAREN_LEFT -> { |
| 284 | consumeToken(Token.Type.PAREN_LEFT); | 312 | consumeToken(Token.Type.PAREN_LEFT); |
| 285 | if (maybeConsumeToken(Token.Type.PAREN_RIGHT)) { | 313 | if (maybeConsumeToken(Token.Type.PAREN_RIGHT)) { |
| 286 | yield EmptyTupleLiteral.INSTANCE; | 314 | yield new TupleExpression(List.of()); |
| 287 | } | 315 | } |
| 288 | var expr = parseExpression(); | 316 | var expr = parseExpression(); |
| 289 | if (maybeConsumeToken(Token.Type.COMMA)) { | 317 | if (maybeConsumeToken(Token.Type.COMMA)) { |
| @@ -346,7 +374,8 @@ public class Parser { | |||
| 346 | exprs.add(parseExpression()); | 374 | exprs.add(parseExpression()); |
| 347 | maybeConsumeToken(Token.Type.COMMA); | 375 | maybeConsumeToken(Token.Type.COMMA); |
| 348 | } while (!maybeConsumeToken(Token.Type.PAREN_RIGHT)); | 376 | } while (!maybeConsumeToken(Token.Type.PAREN_RIGHT)); |
| 349 | return new TupleExpression(new NonEmptyList<>(exprs)); | 377 | exprs.trimToSize(); |
| 378 | return new TupleExpression(exprs); | ||
| 350 | } | 379 | } |
| 351 | 380 | ||
| 352 | private Expression parseUnaryExpression() throws ParserException { | 381 | private Expression parseUnaryExpression() throws ParserException { |