diff --git a/compiler/Compiler/Generator.cs b/compiler/Compiler/Generator.cs index effdd99..5d28061 100644 --- a/compiler/Compiler/Generator.cs +++ b/compiler/Compiler/Generator.cs @@ -74,6 +74,9 @@ public sealed class Generator(List nodes) case NodeStatementIf statement: EmitStatementIf(statement); break; + case NodeStatementWhile statement: + EmitStatementWhile(statement); + break; default: throw new ArgumentOutOfRangeException(nameof(node), node, null); } @@ -147,6 +150,18 @@ public sealed class Generator(List nodes) } } + private void EmitStatementWhile(NodeStatementWhile statement) + { + var condition = EmitExpression(statement.Condition); + writer.WriteLine($"while ({condition})"); + writer.WriteLine("{"); + using (writer.Indent()) + { + EmitStatement(statement.Block); + } + writer.WriteLine("}"); + } + private string EmitExpression(NodeExpression node) { return node switch diff --git a/compiler/Compiler/Parser.cs b/compiler/Compiler/Parser.cs index 7163ce3..b43bd4c 100644 --- a/compiler/Compiler/Parser.cs +++ b/compiler/Compiler/Parser.cs @@ -92,6 +92,13 @@ public sealed class Parser(List tokens) return new NodeStatementIf(TokensFrom(startIndex), condition, thenBlock, elseBlock); } + if (TryExpectKeyword(Keyword.While)) + { + var condition = ParseExpression(); + var thenBlock = ParseStatement(); + return new NodeStatementWhile(TokensFrom(startIndex), condition, thenBlock); + } + var target = ParseExpression(); if (TryExpectSymbol(Symbol.OpenParen)) @@ -377,6 +384,12 @@ internal class NodeStatementIf(List tokens, NodeExpression condition, Nod public readonly NodeStatement? ElseBlock = elseBlock; } +internal class NodeStatementWhile(List tokens, NodeExpression condition, NodeStatement block) : NodeStatement(tokens) +{ + public readonly NodeExpression Condition = condition; + public readonly NodeStatement Block = block; +} + public abstract class NodeExpression(List tokens) : Node(tokens); public sealed class NodeExpressionIntLiteral(List tokens, TokenIntLiteral value) : NodeExpression(tokens) diff --git a/compiler/Compiler/Program.cs b/compiler/Compiler/Program.cs index a8c32c4..e90ab37 100644 --- a/compiler/Compiler/Program.cs +++ b/compiler/Compiler/Program.cs @@ -7,11 +7,14 @@ const string contents = """ if true { x = 49 - } - else { + } else { x = 3 } + while false { + x = 6 + } + do_something("test") return x } diff --git a/compiler/Compiler/Tokenizer.cs b/compiler/Compiler/Tokenizer.cs index 4b4789b..99dceb1 100644 --- a/compiler/Compiler/Tokenizer.cs +++ b/compiler/Compiler/Tokenizer.cs @@ -280,6 +280,7 @@ public sealed class Tokenizer(string contents) "let" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Let), "if" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.If), "else" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Else), + "while" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.While), "return" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Return), "true" => new TokenBoolLiteral(line, startColumn, column - startColumn, true), "false" => new TokenBoolLiteral(line, startColumn, column - startColumn, false), @@ -400,6 +401,7 @@ public enum Keyword Let, If, Else, + While, Return, }