diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-09-30 10:28:05 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-09-30 10:28:05 +0100 |
| commit | fa6b2a24aad096824790501550623a7c3c2418c1 (patch) | |
| tree | 126d85c6f62130ce53fb3d950ac94398e2139c84 /src/main/java | |
| parent | 5c64771c085d2064c79bcd212f513f5a211146eb (diff) | |
Parse sum types
Diffstat (limited to 'src/main/java')
4 files changed, 58 insertions, 1 deletions
diff --git a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedSumTypeDefinitionNode.java b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedSumTypeDefinitionNode.java index 3a49f46e..681c4506 100644 --- a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedSumTypeDefinitionNode.java +++ b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedSumTypeDefinitionNode.java @@ -2,9 +2,11 @@ package org.shedlang.compiler.ast.untyped; import org.shedlang.compiler.sources.Source; +import java.util.List; + public record UntypedSumTypeDefinitionNode( String name, - UntypedTypeLevelExpressionNode variants, + List<UntypedTypeLevelExpressionNode> variants, Source source ) implements UntypedNamespaceStatementNode { } diff --git a/src/main/java/org/shedlang/compiler/parser/Parser.java b/src/main/java/org/shedlang/compiler/parser/Parser.java index e3c78d07..84900688 100644 --- a/src/main/java/org/shedlang/compiler/parser/Parser.java +++ b/src/main/java/org/shedlang/compiler/parser/Parser.java @@ -429,6 +429,13 @@ public class Parser { return new UntypedIntLiteralNode(value, source); } + /** + * Parse zero, one, or many instances of {@code T} using {@code parseOne}. + * Each instance is expected to be separated by tokens consumed by + * {@code parseSeparator}. Parsing stops either if {@code parseSeparator} + * returns false, or if {@code stop} returns false. Trailing separators + * are permitted. + */ private static <T> List<T> parseMany( BooleanSupplier stop, Supplier<T> parseOne, @@ -447,6 +454,27 @@ public class Parser { return values; } + /** + * Parse one or more instances of {@code T} using {@code parseOne}. Each + * instance is expected to be separated by tokens consumed by + * {@code parseSeparator}. Parsing stops if {@code parseSeparator} returns + * false. Trailing separators are not permitted. + */ + private static <T> List<T> parseOneOrMoreNoTrailingSeparator( + Supplier<T> parseOne, + BooleanSupplier parseSeparator + ) { + var values = new ArrayList<T>(); + + while (true) { + var value = parseOne.get(); + values.add(value); + if (!parseSeparator.getAsBoolean()) { + return values; + } + } + } + static UntypedNamespaceStatementNode parseNamespaceStatement(TokenIterator<TokenType> tokens) { return switch (tokens.peek().tokenType()) { case KEYWORD_FUN -> @@ -455,6 +483,9 @@ public class Parser { case KEYWORD_STRUCT -> parseStructDefinition(tokens); + case KEYWORD_SUMTYPE -> + parseSumTypeDefinition(tokens); + case KEYWORD_VAL -> parseAssign(tokens); @@ -603,6 +634,28 @@ public class Parser { return parseExpression(tokens, Optional.of(parentPrecedence)); } + private static UntypedNamespaceStatementNode parseSumTypeDefinition(TokenIterator<TokenType> tokens) { + var start = tokens.position(); + + tokens.skip(TokenType.KEYWORD_SUMTYPE); + + var name = tokens.nextValue(TokenType.IDENTIFIER); + + tokens.skip(TokenType.SYMBOL_EQUALS); + + var variants = parseOneOrMoreNoTrailingSeparator( + () -> parseTopLevelTypeLevelExpression(tokens), + () -> tokens.trySkip(TokenType.SYMBOL_BAR) + ); + + tokens.skip(TokenType.SYMBOL_SEMICOLON); + + var end = tokens.position(); + var source = start.to(end); + + return new UntypedSumTypeDefinitionNode(name, variants, source); + } + static UntypedExpressionNode parseTopLevelExpression(TokenIterator<TokenType> tokens) { return parseExpression(tokens, Optional.empty()); } diff --git a/src/main/java/org/shedlang/compiler/parser/TokenType.java b/src/main/java/org/shedlang/compiler/parser/TokenType.java index ec4fd332..9c8183dc 100644 --- a/src/main/java/org/shedlang/compiler/parser/TokenType.java +++ b/src/main/java/org/shedlang/compiler/parser/TokenType.java @@ -24,6 +24,7 @@ public enum TokenType { SYMBOL_BANG, SYMBOL_BANG_EQUALS, + SYMBOL_BAR, SYMBOL_BRACE_OPEN, SYMBOL_BRACE_CLOSE, SYMBOL_COLON, diff --git a/src/main/java/org/shedlang/compiler/parser/Tokeniser.java b/src/main/java/org/shedlang/compiler/parser/Tokeniser.java index f33e4d53..7659d717 100644 --- a/src/main/java/org/shedlang/compiler/parser/Tokeniser.java +++ b/src/main/java/org/shedlang/compiler/parser/Tokeniser.java @@ -43,6 +43,7 @@ public class Tokeniser { RegexTokeniser.rule(TokenType.SYMBOL_HASH_PAREN_OPEN, "#\\("), RegexTokeniser.rule(TokenType.SYMBOL_BANG, "!"), + RegexTokeniser.rule(TokenType.SYMBOL_BAR, "\\|"), RegexTokeniser.rule(TokenType.SYMBOL_BRACE_OPEN, "\\{"), RegexTokeniser.rule(TokenType.SYMBOL_BRACE_CLOSE, "\\}"), RegexTokeniser.rule(TokenType.SYMBOL_COLON, ":"), |
