From 107ce1646e24b0d30f7fc42e831a7e5f03daecc3 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sat, 30 Sep 2023 11:01:22 +0100 Subject: Parse when expressions --- .../ast/untyped/UntypedExpressionNode.java | 2 +- .../compiler/ast/untyped/UntypedWhenCaseNode.java | 10 ++++++ .../compiler/ast/untyped/UntypedWhenNode.java | 12 +++++++ .../java/org/shedlang/compiler/parser/Parser.java | 41 +++++++++++++++++++++- .../org/shedlang/compiler/parser/TokenType.java | 2 ++ .../org/shedlang/compiler/parser/Tokeniser.java | 2 ++ .../shedlang/compiler/typechecker/TypeChecker.java | 3 ++ 7 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/shedlang/compiler/ast/untyped/UntypedWhenCaseNode.java create mode 100644 src/main/java/org/shedlang/compiler/ast/untyped/UntypedWhenNode.java (limited to 'src/main/java') diff --git a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedExpressionNode.java b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedExpressionNode.java index b1d7ba83..107bc20b 100644 --- a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedExpressionNode.java +++ b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedExpressionNode.java @@ -1,5 +1,5 @@ package org.shedlang.compiler.ast.untyped; public sealed interface UntypedExpressionNode extends UntypedNode - permits UntypedBinaryOperationNode, UntypedBoolLiteralNode, UntypedCallNode, UntypedFieldAccessNode, UntypedIfNode, UntypedIntLiteralNode, UntypedReferenceNode, UntypedStringLiteralNode, UntypedTupleNode { + permits UntypedBinaryOperationNode, UntypedBoolLiteralNode, UntypedCallNode, UntypedFieldAccessNode, UntypedIfNode, UntypedIntLiteralNode, UntypedReferenceNode, UntypedStringLiteralNode, UntypedTupleNode, UntypedWhenNode { } diff --git a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedWhenCaseNode.java b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedWhenCaseNode.java new file mode 100644 index 00000000..7b3e95b9 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedWhenCaseNode.java @@ -0,0 +1,10 @@ +package org.shedlang.compiler.ast.untyped; + +import org.shedlang.compiler.sources.Source; + +public record UntypedWhenCaseNode( + UntypedTypeLevelExpressionNode caseType, + UntypedBlockNode body, + Source source +) implements UntypedNode { +} diff --git a/src/main/java/org/shedlang/compiler/ast/untyped/UntypedWhenNode.java b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedWhenNode.java new file mode 100644 index 00000000..e8c2d348 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/ast/untyped/UntypedWhenNode.java @@ -0,0 +1,12 @@ +package org.shedlang.compiler.ast.untyped; + +import org.shedlang.compiler.sources.Source; + +import java.util.List; + +public record UntypedWhenNode( + UntypedExpressionNode expression, + List cases, + Source source +) implements UntypedExpressionNode { +} diff --git a/src/main/java/org/shedlang/compiler/parser/Parser.java b/src/main/java/org/shedlang/compiler/parser/Parser.java index 84900688..71490933 100644 --- a/src/main/java/org/shedlang/compiler/parser/Parser.java +++ b/src/main/java/org/shedlang/compiler/parser/Parser.java @@ -540,6 +540,8 @@ public class Parser { case KEYWORD_IF -> parseIf(tokens); case KEYWORD_FALSE, KEYWORD_TRUE -> parseBoolLiteral(tokens); + + case KEYWORD_WHEN -> parseWhen(tokens); case STRING -> parseStringLiteral(tokens); @@ -812,7 +814,6 @@ public class Parser { return new UntypedTupleTypeNode(elements, source); } - private static UntypedTypeLevelReferenceNode parseTypeLevelReference(TokenIterator tokens) { var start = tokens.position(); @@ -824,6 +825,44 @@ public class Parser { return new UntypedTypeLevelReferenceNode(name, source); } + private static UntypedExpressionNode parseWhen(TokenIterator tokens) { + var start = tokens.position(); + + tokens.skip(TokenType.KEYWORD_WHEN); + + tokens.skip(TokenType.SYMBOL_PAREN_OPEN); + var expression = parseTopLevelExpression(tokens); + tokens.skip(TokenType.SYMBOL_PAREN_CLOSE); + + tokens.skip(TokenType.SYMBOL_BRACE_OPEN); + var cases = parseMany( + () -> tokens.isNext(TokenType.SYMBOL_BRACE_CLOSE), + () -> parseWhenCase(tokens), + () -> true + ); + tokens.skip(TokenType.SYMBOL_BRACE_CLOSE); + + var end = tokens.position(); + var source = start.to(end); + + return new UntypedWhenNode(expression, cases, source); + } + + private static UntypedWhenCaseNode parseWhenCase(TokenIterator tokens) { + var start = tokens.position(); + + tokens.skip(TokenType.KEYWORD_IS); + + var caseType = parseTopLevelTypeLevelExpression(tokens); + + var body = parseBlock(tokens); + + var end = tokens.position(); + var source = start.to(end); + + return new UntypedWhenCaseNode(caseType, body, source); + } + private static UntypedFunctionStatementNode parseWhile( TokenIterator tokens ) { diff --git a/src/main/java/org/shedlang/compiler/parser/TokenType.java b/src/main/java/org/shedlang/compiler/parser/TokenType.java index 9c8183dc..e2350ae2 100644 --- a/src/main/java/org/shedlang/compiler/parser/TokenType.java +++ b/src/main/java/org/shedlang/compiler/parser/TokenType.java @@ -14,12 +14,14 @@ public enum TokenType { KEYWORD_FALSE, KEYWORD_FUN, KEYWORD_IF, + KEYWORD_IS, KEYWORD_RETURN, KEYWORD_STRUCT, KEYWORD_SUMTYPE, KEYWORD_TRUE, KEYWORD_VAL, KEYWORD_VAR, + KEYWORD_WHEN, KEYWORD_WHILE, SYMBOL_BANG, diff --git a/src/main/java/org/shedlang/compiler/parser/Tokeniser.java b/src/main/java/org/shedlang/compiler/parser/Tokeniser.java index 7659d717..e7f04189 100644 --- a/src/main/java/org/shedlang/compiler/parser/Tokeniser.java +++ b/src/main/java/org/shedlang/compiler/parser/Tokeniser.java @@ -18,12 +18,14 @@ public class Tokeniser { Map.entry("false", TokenType.KEYWORD_FALSE), Map.entry("fun", TokenType.KEYWORD_FUN), Map.entry("if", TokenType.KEYWORD_IF), + Map.entry("is", TokenType.KEYWORD_IS), Map.entry("return", TokenType.KEYWORD_RETURN), Map.entry("struct", TokenType.KEYWORD_STRUCT), Map.entry("sumtype", TokenType.KEYWORD_SUMTYPE), Map.entry("true", TokenType.KEYWORD_TRUE), Map.entry("val", TokenType.KEYWORD_VAL), Map.entry("var", TokenType.KEYWORD_VAR), + Map.entry("when", TokenType.KEYWORD_WHEN), Map.entry("while", TokenType.KEYWORD_WHILE) ); diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java index 7c3741e2..c630b9dc 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java @@ -406,6 +406,9 @@ public class TypeChecker { case UntypedTupleNode untypedTuple -> typeCheckTuple(untypedTuple, context); + + case UntypedWhenNode untypedWhen -> + throw new UnsupportedOperationException(); }; } -- cgit v1.2.3