summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedSumDefinitionNode.java2
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedSumVariantDefinitionNode.java9
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java53
-rw-r--r--src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserSumDefinitionTests.java82
4 files changed, 144 insertions, 2 deletions
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedSumDefinitionNode.java b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedSumDefinitionNode.java
index 7969806..66acc08 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedSumDefinitionNode.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedSumDefinitionNode.java
@@ -6,7 +6,7 @@ import java.util.List;
public record UntypedSumDefinitionNode(
String name,
- List<UntypedTypeLevelExpressionNode> variants,
+ List<UntypedSumVariantDefinitionNode> variants,
Source source
) implements UntypedNamespaceStatementNode {
}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedSumVariantDefinitionNode.java b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedSumVariantDefinitionNode.java
new file mode 100644
index 0000000..91a9f0d
--- /dev/null
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedSumVariantDefinitionNode.java
@@ -0,0 +1,9 @@
+package org.zwobble.hobgoblin.compiler.ast.untyped;
+
+import org.zwobble.hobgoblin.compiler.sources.Source;
+
+public record UntypedSumVariantDefinitionNode(
+ UntypedTypeLevelExpressionNode type,
+ Source source
+) implements UntypedNode {
+}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java b/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java
index fbf38bb..4cd35f8 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java
@@ -49,7 +49,13 @@ public class Parser {
static UntypedNamespaceStatementNode parseNamespaceStatement(
TokenIterator tokens
) {
- return parseStructDefinition(tokens);
+ if (tokens.isNext(TokenType.KEYWORD_STRUCT)) {
+ return parseStructDefinition(tokens);
+ } else if (tokens.isNext(TokenType.KEYWORD_SUM)) {
+ return parseSumDefinition(tokens);
+ } else {
+ throw new UnsupportedOperationException("TODO");
+ }
}
private static UntypedStructDefinitionNode parseStructDefinition(
@@ -100,6 +106,51 @@ public class Parser {
);
}
+ private static UntypedSumDefinitionNode parseSumDefinition(
+ TokenIterator tokens
+ ) {
+ var start = tokens.startPosition();
+
+ tokens.skip(TokenType.KEYWORD_SUM);
+ var name = tokens.next(TokenType.IDENTIFIER);
+ tokens.skip(TokenType.SYMBOL_BRACE_OPEN);
+
+ var variants = parseMany(
+ () -> tokens.isNext(TokenType.SYMBOL_BRACE_CLOSE),
+ () -> parseSumVariantDefinition(tokens),
+ () -> true
+ );
+
+ tokens.skip(TokenType.SYMBOL_BRACE_CLOSE);
+
+ var end = tokens.endPosition();
+ var source = createSource(start, end);
+
+ return new UntypedSumDefinitionNode(
+ name.charSequence().toString(),
+ variants,
+ source
+ );
+ }
+
+ private static UntypedSumVariantDefinitionNode parseSumVariantDefinition(
+ TokenIterator tokens
+ ) {
+ var start = tokens.startPosition();
+
+ tokens.skip(TokenType.KEYWORD_VARIANT);
+ var type = parseTypeLevelExpression(tokens);
+ tokens.skip(TokenType.SYMBOL_SEMICOLON);
+
+ var end = tokens.endPosition();
+ var source = createSource(start, end);
+
+ return new UntypedSumVariantDefinitionNode(
+ type,
+ source
+ );
+ }
+
static UntypedTypeLevelExpressionNode parseTypeLevelExpression(
TokenIterator tokens
) {
diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserSumDefinitionTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserSumDefinitionTests.java
new file mode 100644
index 0000000..825511e
--- /dev/null
+++ b/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserSumDefinitionTests.java
@@ -0,0 +1,82 @@
+package org.zwobble.hobgoblin.compiler.parser;
+
+import org.junit.jupiter.api.Test;
+import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedSumDefinitionNode;
+import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedSumVariantDefinitionNode;
+import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedTypeLevelReferenceNode;
+
+import static org.zwobble.hobgoblin.compiler.parser.ParserTesting.parseString;
+import static org.zwobble.precisely.AssertThat.assertThat;
+import static org.zwobble.precisely.Matchers.*;
+
+public class ParserSumDefinitionTests {
+ @Test
+ public void nameIsParsed() {
+ var source = """
+ sum Shape {
+ }""";
+
+ var node = parseString(
+ source,
+ Parser::parseNamespaceStatement
+ );
+
+ assertThat(node, instanceOf(
+ UntypedSumDefinitionNode.class,
+ has("name", UntypedSumDefinitionNode::name, equalTo("Shape"))
+ ));
+ }
+
+ @Test
+ public void emptySumHasNoVariants() {
+ var source = """
+ sum Shape {
+ }""";
+
+ var node = parseString(
+ source,
+ Parser::parseNamespaceStatement
+ );
+
+ assertThat(node, instanceOf(
+ UntypedSumDefinitionNode.class,
+ has("variants", UntypedSumDefinitionNode::variants, isSequence())
+ ));
+ }
+
+ @Test
+ public void sumWithVariants() {
+ var source = """
+ sum Shape {
+ variant Rectangle;
+ variant Triangle;
+ }""";
+
+ var node = parseString(
+ source,
+ Parser::parseNamespaceStatement
+ );
+
+ assertThat(node, instanceOf(
+ UntypedSumDefinitionNode.class,
+ has("variants", UntypedSumDefinitionNode::variants, isSequence(
+ has(
+ "type",
+ UntypedSumVariantDefinitionNode::type,
+ instanceOf(
+ UntypedTypeLevelReferenceNode.class,
+ has("name", UntypedTypeLevelReferenceNode::name, equalTo("Rectangle"))
+ )
+ ),
+ has(
+ "type",
+ UntypedSumVariantDefinitionNode::type,
+ instanceOf(
+ UntypedTypeLevelReferenceNode.class,
+ has("name", UntypedTypeLevelReferenceNode::name, equalTo("Triangle"))
+ )
+ )
+ ))
+ ));
+ }
+}