From 84a888738a32ed13081b35fda0d11f3d2d79de30 Mon Sep 17 00:00:00 2001 From: Brandon Dyck Date: Wed, 28 Jun 2023 17:18:31 -0600 Subject: [PATCH] Parse sequencing expressions --- ASTPrinter.cs | 5 +++++ Expr.g.cs | 10 ++++++++++ Parser.cs | 8 +++++++- Program.cs | 2 ++ ast_classes.fsx | 4 +++- grammar.txt | 22 +++++++++++----------- 6 files changed, 38 insertions(+), 13 deletions(-) diff --git a/ASTPrinter.cs b/ASTPrinter.cs index a331171..9017e36 100644 --- a/ASTPrinter.cs +++ b/ASTPrinter.cs @@ -48,4 +48,9 @@ class ASTPrinter : IVisitor { return parenthesize("if", expr.Condition, expr.Then, expr.Else); } + + public string visitSequenceExpr(Sequence expr) + { + return parenthesize("seq", expr.Left, expr.Right); + } } diff --git a/Expr.g.cs b/Expr.g.cs index 1e0937d..d743ae9 100644 --- a/Expr.g.cs +++ b/Expr.g.cs @@ -10,12 +10,22 @@ public abstract class Expr { public abstract T accept(IVisitor visitor); } public interface IVisitor { + T visitSequenceExpr(Sequence expr); T visitBinaryExpr(Binary expr); T visitGroupingExpr(Grouping expr); T visitLiteralExpr(Literal expr); T visitUnaryExpr(Unary expr); T visitIfExpr(If expr); } +public class Sequence : Expr +{ + public required Expr Left { get; init; } + public required Expr Right { get; init; } + public override T accept(IVisitor visitor) + { + return visitor.visitSequenceExpr(this); + } +} public class Binary : Expr { public required Expr Left { get; init; } diff --git a/Parser.cs b/Parser.cs index e0efae7..c9f0098 100644 --- a/Parser.cs +++ b/Parser.cs @@ -121,7 +121,13 @@ class Parser private Expr expression() { - return equality(); + var expr = equality(); + while (match(TokenType.Semicolon)) + { + var right = equality(); + expr = new Sequence { Left = expr, Right = right }; + } + return expr; } private Expr equality() diff --git a/Program.cs b/Program.cs index efbc2dd..2e01266 100644 --- a/Program.cs +++ b/Program.cs @@ -94,6 +94,7 @@ public enum TokenType Backtick, At, Comma, + Semicolon, Period, Equal, Plus, Minus, Asterisk, Slash, @@ -284,6 +285,7 @@ class Scanner case '`': addToken(TokenType.Backtick); break; case '@': addToken(TokenType.At); break; case ',': addToken(TokenType.Comma); break; + case ';': addToken(TokenType.Semicolon); break; case '.': addToken(TokenType.Period); break; case '*': addToken(TokenType.Asterisk); break; case '/': addToken(TokenType.Slash); break; diff --git a/ast_classes.fsx b/ast_classes.fsx index 35ec3ed..5ecb21a 100644 --- a/ast_classes.fsx +++ b/ast_classes.fsx @@ -2,7 +2,9 @@ type Field = { Type: string; Name: string } type Type = { Name: string; Fields: list } let types = - [ { Name = "Binary" + [ { Name = "Sequence" + Fields = [ { Type = "Expr"; Name = "Left" }; { Type = "Expr"; Name = "Right" } ] } + { Name = "Binary" Fields = [ { Type = "Expr"; Name = "Left" } { Type = "Token"; Name = "Op" } diff --git a/grammar.txt b/grammar.txt index ac1dce0..f26d7a9 100644 --- a/grammar.txt +++ b/grammar.txt @@ -1,20 +1,16 @@ expression -> - | literal -// | identifier -// | sequence + | sequence +// | apply | unary | binary // | let -// | when - | if - | variant - | record - | list + | compound + | control | field | index - | grouping ; +// | identifier + | primary -literal -> NUMBER | STRING ; identifier -> IDENTIFIER | "@" STRING ; grouping -> "(" expression ")" ; unary -> ( "-" | "!" ) expression ; @@ -24,11 +20,15 @@ operator -> | "+" | "-" | "*" | "/" // | "|>" | "<|" | ">>" | "<<" | "++" ; +control -> + | if +// | when if -> "if" expression "then" expression "else" expression ; +compound -> variant | record | list ; variant -> "`" identifier ( "(" ( expression ( "," expression)* )? ")" )? ; record -> "{" ( identifier "=" expression ( "," identifier "=" expression )* )? "}" ; list -> "[" ( expression ( "," expression )* )? "]" ; field -> expression "." identifier ; index -> expression "[" expression "]" ; -grouping -> "(" expression ")" ; +primary -> NUMBER | STRING | "(" expression ")" ;