summaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2026-06-14 11:05:12 +0100
committerMichael Williamson <mike@zwobble.org>2026-06-14 11:05:12 +0100
commit8f4049e29116e1f80a2ab8d740ca1f4519a64aa2 (patch)
treee835b0a4cd3724802e3b72c47522236c9b932385 /src/main
parent95f9dc1f12d14acad47472bb20f03f0e90a98fac (diff)
Parse imports
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java61
1 files changed, 60 insertions, 1 deletions
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 dc35fa0..2a51257 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java
@@ -32,6 +32,12 @@ public class Parser {
) {
var start = tokens.startPosition();
+ var imports = parseMany(
+ () -> !tokens.isNext(TokenType.KEYWORD_IMPORT),
+ () -> parseImport(tokens),
+ () -> true
+ );
+
var body = parseMany(
() -> tokens.isNext(TokenType.END),
() -> parseNamespaceStatement(tokens),
@@ -43,12 +49,32 @@ public class Parser {
return new UntypedNamespaceNode(
namespaceName,
- List.of(),
+ imports,
body,
source
);
}
+ private static UntypedImportNode parseImport(TokenIterator tokens) {
+ tokens.skip(TokenType.KEYWORD_IMPORT);
+ tokens.skip(TokenType.SYMBOL_BRACE_OPEN);
+
+ var importedNames = parseMany(
+ () -> tokens.isNext(TokenType.SYMBOL_BRACE_CLOSE),
+ () -> parseIdentifier(tokens),
+ () -> tokens.trySkip(TokenType.SYMBOL_COMMA)
+ );
+
+ tokens.skip(TokenType.SYMBOL_BRACE_CLOSE);
+ tokens.skip(TokenType.KEYWORD_FROM);
+
+ var namespaceName = parseRelativeNamespaceName(tokens);
+
+ tokens.skip(TokenType.SYMBOL_SEMICOLON);
+
+ return new UntypedImportNode(importedNames, namespaceName);
+ }
+
static UntypedNamespaceStatementNode parseNamespaceStatement(
TokenIterator tokens
) {
@@ -281,6 +307,39 @@ public class Parser {
return new NamespaceName(namespaceParts);
}
+ private static NamespaceName parseRelativeNamespaceName(TokenIterator tokens) {
+ var isSibling = tokens.trySkip(TokenType.SYMBOL_DOT);
+
+ List<String> parentParts;
+ if (isSibling) {
+ tokens.skip(TokenType.SYMBOL_FORWARD_SLASH);
+ parentParts = List.of(".");
+ } else if (tokens.isNext(TokenType.SYMBOL_DOT_DOT)) {
+ parentParts = new ArrayList<>();
+ while (tokens.trySkip(TokenType.SYMBOL_DOT_DOT)) {
+ parentParts.add("..");
+ tokens.skip(TokenType.SYMBOL_FORWARD_SLASH);
+ }
+ } else {
+ parentParts = List.of(parseIdentifier(tokens));
+ }
+
+ var childParts = parseMany(
+ () -> !tokens.isNext(TokenType.IDENTIFIER),
+ () -> {
+ tokens.trySkip(TokenType.SYMBOL_FORWARD_SLASH);
+ return parseIdentifier(tokens);
+ },
+ () -> true
+ );
+
+ var namespaceParts = new ArrayList<String>();
+ namespaceParts.addAll(parentParts);
+ namespaceParts.addAll(childParts);
+
+ return new NamespaceName(namespaceParts);
+ }
+
private static String parseIdentifier(TokenIterator tokens) {
return tokens.next(TokenType.IDENTIFIER).charSequence().toString();
}