From 371a4e8db3aa6fdc0a6d144351e9c0169c13badf Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Wed, 22 Apr 2026 11:28:02 +0100 Subject: Parse type level references --- .../untyped/UntypedStructFieldDefinitionNode.java | 10 +++++++++ .../untyped/UntypedTypeLevelExpressionNode.java | 4 ++++ .../ast/untyped/UntypedTypeLevelReferenceNode.java | 9 ++++++++ .../zwobble/hobgoblin/compiler/parser/Parser.java | 18 ++++++++++++++++ .../hobgoblin/compiler/parser/TokenIterator.java | 11 ++++++++++ .../parser/ParserTypeLevelReferenceTests.java | 25 ++++++++++++++++++++++ 6 files changed, 77 insertions(+) create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedStructFieldDefinitionNode.java create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedTypeLevelExpressionNode.java create mode 100644 src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedTypeLevelReferenceNode.java create mode 100644 src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserTypeLevelReferenceTests.java (limited to 'src') diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedStructFieldDefinitionNode.java b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedStructFieldDefinitionNode.java new file mode 100644 index 0000000..0e21663 --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedStructFieldDefinitionNode.java @@ -0,0 +1,10 @@ +package org.zwobble.hobgoblin.compiler.ast.untyped; + +import org.zwobble.hobgoblin.compiler.sources.Source; + +public record UntypedStructFieldDefinitionNode( + String name, + UntypedTypeLevelExpressionNode type, + Source source +) implements UntypedNode { +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedTypeLevelExpressionNode.java b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedTypeLevelExpressionNode.java new file mode 100644 index 0000000..871393d --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedTypeLevelExpressionNode.java @@ -0,0 +1,4 @@ +package org.zwobble.hobgoblin.compiler.ast.untyped; + +public sealed interface UntypedTypeLevelExpressionNode extends UntypedNode permits UntypedTypeLevelReferenceNode { +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedTypeLevelReferenceNode.java b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedTypeLevelReferenceNode.java new file mode 100644 index 0000000..018655e --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedTypeLevelReferenceNode.java @@ -0,0 +1,9 @@ +package org.zwobble.hobgoblin.compiler.ast.untyped; + +import org.zwobble.hobgoblin.compiler.sources.Source; + +public record UntypedTypeLevelReferenceNode( + String name, + Source source +) implements UntypedTypeLevelExpressionNode { +} 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 704f34f..4411306 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java @@ -1,6 +1,8 @@ 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.sources.FileFragmentSource; import org.zwobble.hobgoblin.compiler.sources.Source; import org.zwobble.hobgoblin.compiler.types.NamespaceName; @@ -28,6 +30,22 @@ public class Parser { ); } + public static UntypedTypeLevelExpressionNode parseTypeLevelExpression( + TokenIterator tokens + ) { + var start = tokens.startPosition(); + + var name = tokens.next(TokenType.IDENTIFIER); + + var end = tokens.endPosition(); + var source = createSource(start, end); + + return new UntypedTypeLevelReferenceNode( + name.charSequence().toString(), + source + ); + } + private static Source createSource(SourcePosition start, SourcePosition end) { return new FileFragmentSource(start.to(end)); } 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 9e1dd9c..cb59e79 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/parser/TokenIterator.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/parser/TokenIterator.java @@ -19,6 +19,17 @@ class TokenIterator { return this.getAbsolute(this.tokenIndex); } + public Token next(TokenType tokenType) { + var token = peek(); + if (token.tokenType().equals(tokenType)) { + this.tokenIndex++; + return token; + } 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/ParserTypeLevelReferenceTests.java b/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserTypeLevelReferenceTests.java new file mode 100644 index 0000000..4f50199 --- /dev/null +++ b/src/test/java/org/zwobble/hobgoblin/compiler/parser/ParserTypeLevelReferenceTests.java @@ -0,0 +1,25 @@ +package org.zwobble.hobgoblin.compiler.parser; + +import org.junit.jupiter.api.Test; +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 ParserTypeLevelReferenceTests { + @Test + public void canParseIdentifierAsTypeLevelReference() { + var source = "Point"; + + var node = parseString( + source, + Parser::parseTypeLevelExpression + ); + + assertThat(node, instanceOf( + UntypedTypeLevelReferenceNode.class, + has("name", UntypedTypeLevelReferenceNode::name, equalTo("Point")) + )); + } +} -- cgit v1.2.3