From 3f54b73a61e2fbe29e6e33dff4bb0b6e8bbf31f1 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Wed, 22 Apr 2026 11:34:09 +0100 Subject: Parse empty struct definitions --- .../zwobble/hobgoblin/compiler/parser/Parser.java | 23 +++++++++++++++--- .../hobgoblin/compiler/parser/TokenIterator.java | 10 ++++++++ .../parser/ParserStructDefinitionTests.java | 27 ++++++++++++++++++++++ 3 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserStructDefinitionTests.java 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 4411306..e90518c 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java @@ -1,8 +1,6 @@ package org.zwobble.hobgoblin.compiler.parser; -import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedNamespaceNode; -import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedTypeLevelExpressionNode; -import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedTypeLevelReferenceNode; +import org.zwobble.hobgoblin.compiler.ast.untyped.*; import org.zwobble.hobgoblin.compiler.sources.FileFragmentSource; import org.zwobble.hobgoblin.compiler.sources.Source; import org.zwobble.hobgoblin.compiler.types.NamespaceName; @@ -30,6 +28,25 @@ public class Parser { ); } + public static UntypedNamespaceStatementNode parseNamespaceStatement( + TokenIterator tokens + ) { + var start = tokens.startPosition(); + + tokens.skip(TokenType.KEYWORD_STRUCT); + var name = tokens.next(TokenType.IDENTIFIER); + tokens.skip(TokenType.SYMBOL_BRACE_OPEN); + tokens.skip(TokenType.SYMBOL_BRACE_CLOSE); + + var end = tokens.endPosition(); + var source = createSource(start, end); + + return new UntypedStructDefinitionNode( + name.charSequence().toString(), + source + ); + } + public static UntypedTypeLevelExpressionNode parseTypeLevelExpression( TokenIterator tokens ) { diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/parser/TokenIterator.java b/src/main/java/org/zwobble/hobgoblin/compiler/parser/TokenIterator.java index cb59e79..177a87e 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/parser/TokenIterator.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/parser/TokenIterator.java @@ -30,6 +30,16 @@ class TokenIterator { } } + public void skip(TokenType tokenType) { + var token = peek(); + if (token.tokenType().equals(tokenType)) { + this.tokenIndex++; + } else { + // TODO: better expected string + throw new UnexpectedTokenError(tokenType.toString(), token); + } + } + private Token getAbsolute(int index) { if (index < this.tokens.size()) { return this.tokens.get(index); diff --git a/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserStructDefinitionTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserStructDefinitionTests.java new file mode 100644 index 0000000..8c692fd --- /dev/null +++ b/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserStructDefinitionTests.java @@ -0,0 +1,27 @@ +package org.zwobble.hobgoblin.compiler.parser; + +import org.junit.jupiter.api.Test; +import org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode; + +import static org.zwobble.hobgoblin.compiler.parser.ParserTesting.parseString; +import static org.zwobble.precisely.AssertThat.assertThat; +import static org.zwobble.precisely.Matchers.*; + +public class ParserStructDefinitionTests { + @Test + public void emptyStruct() { + var source = """ + struct Point { + }"""; + + var node = parseString( + source, + Parser::parseNamespaceStatement + ); + + assertThat(node, instanceOf( + UntypedStructDefinitionNode.class, + has("name", UntypedStructDefinitionNode::name, equalTo("Point")) + )); + } +} -- cgit v1.2.3