From 1422d647cddb577fafc19ee97e33a394aefc560b Mon Sep 17 00:00:00 2001 From: Elias Haugsbakk Date: Sun, 20 Sep 2026 03:12:03 +0200 Subject: add rules to semantics analyzer --- .../eliashaugsbakk/kompilator/parsing/Parser.java | 64 ++++++++++------------ .../no/eliashaugsbakk/kompilator/parsing/Type.java | 18 +++++- .../parsing/node/expression/FunctionCall.java | 9 +++ .../parsing/node/expression/Identifier.java | 2 +- .../parsing/node/statement/Assignment.java | 2 +- .../node/statement/IdentifierDeclaration.java | 6 +- 6 files changed, 59 insertions(+), 42 deletions(-) (limited to 'src/main/java/no/eliashaugsbakk/kompilator/parsing') diff --git a/src/main/java/no/eliashaugsbakk/kompilator/parsing/Parser.java b/src/main/java/no/eliashaugsbakk/kompilator/parsing/Parser.java index 356a6d7..f959daf 100644 --- a/src/main/java/no/eliashaugsbakk/kompilator/parsing/Parser.java +++ b/src/main/java/no/eliashaugsbakk/kompilator/parsing/Parser.java @@ -108,9 +108,11 @@ public class Parser { private Statement parseKeyword() throws ParserException { Token token = tokens.get(current); if (token.value().contentEquals("set")) { - return parseIdentifierStatement(); + current++; // consume "set" + return parseDeclaration(false); } else if (token.value().contentEquals("mut")) { - return parseIdentifierStatement(); + current++; // consume "mut" + return parseDeclaration(true); } else if (token.value().contentEquals("skriv")) { return parseExpressionStatement(); } else { @@ -130,60 +132,50 @@ public class Parser { return new ExpressionStatement(expression); } - - private Statement parseIdentifierStatement() throws ParserException { - // this is either: - // - declaration of a new variable with an associated value - // - declaration of a new variable without an associated value - // - reassigning an existing variable - - /* - mut x: string?; IDENTIFIER, COLON, TYPE, SEMICOLON - set x: string = "string"; IDENTIFIER, COLON, TYPE, ASSIGN, STRING, SEMICOLON - x = "string"; IDENTIFIER, ASSIGN, STRING, SEMICOLON - */ - - boolean mutable = false; - - if (tokens.get(current).value().contentEquals("mut")) { - mutable = true; - current++; - } else if (tokens.get(current).value().contentEquals("set")) { - current++; - } - String identifier = tokens.get(current).value(); - current++; + current++; // consume identifier Token next = tokens.get(current); - if (next.type() == COLON) { - // x: string = "hello"; - return parseDeclaration(identifier, mutable); - } else if (next.type() == ASSIGN) { - // x = "hello"; + if (next.type() == ASSIGN) { return parseAssignment(identifier); + } else if (next.type() == LPAREN) { + // Future expansion: standalone function calls like `doSomething();` + current--; // rewind to identifier + Expression expr = parseFunctionCall(); + expectSemicolon(); + return new ExpressionStatement(expr); } else { - throw new ParserException(next.line(), next.column(), "Expected : or = after: " + identifier); + throw new ParserException(next.line(), next.column(), "Unexpected token after identifier: " + next.value()); } } - private Statement parseDeclaration(String identifier, boolean mutable) throws ParserException { - // x: type; - current++; // skip colon + private Statement parseDeclaration(boolean isMutable) throws ParserException { + Token nameToken = tokens.get(current); + if (nameToken.type() != IDENTIFIER) { + throw new ParserException(nameToken.line(), nameToken.column(), + "Expected identifier after declaration keyword, got: " + nameToken.value()); + } + String identifier = nameToken.value(); + current++; // consume identifier + + if (tokens.get(current).type() != COLON) { + throw new ParserException(tokens.get(current).line(), tokens.get(current).column(), + "Expected : after identifier in declaration"); + } + current++; // skip : Type type = parseType(); Expression initializer = null; - // x: type = "hello"; if (tokens.get(current).type() == ASSIGN) { current++; // skip = initializer = parseExpression(); } expectSemicolon(); - return new IdentifierDeclaration(identifier, type, initializer, mutable); + return new IdentifierDeclaration(identifier, type, initializer, isMutable); } private Statement parseAssignment(String identifier) throws ParserException { diff --git a/src/main/java/no/eliashaugsbakk/kompilator/parsing/Type.java b/src/main/java/no/eliashaugsbakk/kompilator/parsing/Type.java index d707696..6b1007c 100644 --- a/src/main/java/no/eliashaugsbakk/kompilator/parsing/Type.java +++ b/src/main/java/no/eliashaugsbakk/kompilator/parsing/Type.java @@ -1,12 +1,28 @@ package no.eliashaugsbakk.kompilator.parsing; +import java.util.Objects; + public class Type { - final String type; + public final String type; public final boolean nullable; public Type(String type, boolean nullable) { this.type = type; this.nullable = nullable; } + + @Override + public boolean equals(Object o) { + if (o instanceof Type t) { + return this.type.equals(t.type) && this.nullable == t.nullable; + } else { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hash(type, nullable); + } } diff --git a/src/main/java/no/eliashaugsbakk/kompilator/parsing/node/expression/FunctionCall.java b/src/main/java/no/eliashaugsbakk/kompilator/parsing/node/expression/FunctionCall.java index 3c46ec4..2537d9c 100644 --- a/src/main/java/no/eliashaugsbakk/kompilator/parsing/node/expression/FunctionCall.java +++ b/src/main/java/no/eliashaugsbakk/kompilator/parsing/node/expression/FunctionCall.java @@ -1,6 +1,7 @@ package no.eliashaugsbakk.kompilator.parsing.node.expression; import java.util.List; +import no.eliashaugsbakk.kompilator.parsing.Type; /** * Represents a function call statement (e.g., print("Hello, world")). @@ -13,4 +14,12 @@ public class FunctionCall extends Expression { this.functionName = functionName; this.arguments = arguments; } + + public Type getReturnType() { + if (functionName.equals("skriv")) { + return new Type("void", false); + } + // TODO: Look up return type in function table when you add more functions + return null; + } } diff --git a/src/main/java/no/eliashaugsbakk/kompilator/parsing/node/expression/Identifier.java b/src/main/java/no/eliashaugsbakk/kompilator/parsing/node/expression/Identifier.java index c1f475f..91607f8 100644 --- a/src/main/java/no/eliashaugsbakk/kompilator/parsing/node/expression/Identifier.java +++ b/src/main/java/no/eliashaugsbakk/kompilator/parsing/node/expression/Identifier.java @@ -4,7 +4,7 @@ package no.eliashaugsbakk.kompilator.parsing.node.expression; * Resolves to a variable's value */ public class Identifier extends Expression { - final String name; + public final String name; public Identifier(String name) { this.name = name; diff --git a/src/main/java/no/eliashaugsbakk/kompilator/parsing/node/statement/Assignment.java b/src/main/java/no/eliashaugsbakk/kompilator/parsing/node/statement/Assignment.java index bca16df..01d207d 100644 --- a/src/main/java/no/eliashaugsbakk/kompilator/parsing/node/statement/Assignment.java +++ b/src/main/java/no/eliashaugsbakk/kompilator/parsing/node/statement/Assignment.java @@ -4,7 +4,7 @@ import no.eliashaugsbakk.kompilator.parsing.node.expression.Expression; public class Assignment extends Statement { public final String identifier; - final Expression expression; + public final Expression expression; public Assignment(String identifier, Expression expression) { this.identifier = identifier; diff --git a/src/main/java/no/eliashaugsbakk/kompilator/parsing/node/statement/IdentifierDeclaration.java b/src/main/java/no/eliashaugsbakk/kompilator/parsing/node/statement/IdentifierDeclaration.java index d3c5474..69b0f1b 100644 --- a/src/main/java/no/eliashaugsbakk/kompilator/parsing/node/statement/IdentifierDeclaration.java +++ b/src/main/java/no/eliashaugsbakk/kompilator/parsing/node/statement/IdentifierDeclaration.java @@ -12,14 +12,14 @@ public class IdentifierDeclaration extends Statement { // identifier initialization: my_var: type [4]; // may be null: my_var: type?; - public final Expression expression; // may be null: x: int?; + public final Expression initializer; // may be null: x: int?; public final boolean mutable; - public IdentifierDeclaration(String identifier, Type type, Expression expression, boolean mutable) { + public IdentifierDeclaration(String identifier, Type type, Expression initializer, boolean mutable) { this.identifier = identifier; this.type = type; - this.expression = expression; + this.initializer = initializer; this.mutable = mutable; } } -- cgit v1.2.3