From 5b0ca1ca6d83fc7cf20d46e6d165c87b90861a84 Mon Sep 17 00:00:00 2001 From: Brandon Dyck Date: Sat, 1 Jul 2023 23:30:24 -0600 Subject: [PATCH] Parse variants --- ASTPrinter.cs | 9 +++++++++ Expr.g.cs | 10 ++++++++++ Parser.cs | 23 ++++++++++++++++++++--- ast_classes.fsx | 2 ++ 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/ASTPrinter.cs b/ASTPrinter.cs index 4d25244..4ea2d81 100644 --- a/ASTPrinter.cs +++ b/ASTPrinter.cs @@ -74,4 +74,13 @@ class ASTPrinter : IVisitor { return parenthesize("list", expr.Elements); } + + public string visitVariantExpr(Variant expr) + { + if (expr.Argument == null) + { + return parenthesize("variant", new Identifier { Value = expr.Tag }); + } + return parenthesize("variant", new Identifier { Value = expr.Tag }, expr.Argument); + } } diff --git a/Expr.g.cs b/Expr.g.cs index e9ae9a7..1a6aaa4 100644 --- a/Expr.g.cs +++ b/Expr.g.cs @@ -19,6 +19,7 @@ public interface IVisitor { T visitIfExpr(If expr); T visitIdentifierExpr(Identifier expr); T visitListExpr(List expr); + T visitVariantExpr(Variant expr); T visitSelectorExpr(Selector expr); } public class Sequence : Expr @@ -91,6 +92,15 @@ public class List : Expr return visitor.visitListExpr(this); } } +public class Variant : Expr +{ + public required Name Tag { get; init; } + public required Expr? Argument { get; init; } + public override T accept(IVisitor visitor) + { + return visitor.visitVariantExpr(this); + } +} public class Selector : Expr { public required Expr Left { get; init; } diff --git a/Parser.cs b/Parser.cs index f241ad7..e16d746 100644 --- a/Parser.cs +++ b/Parser.cs @@ -304,13 +304,30 @@ class Parser private Expr? variant() { - return null; - // throw new NotImplementedException("TODO variant"); + if (!match(TokenType.Backtick)) + { + return null; + } + Name? tag = name(); + Expr? argument = null; + if (tag == null) + { + throw error(peek(), "Expect identifier after backtick."); + } + if (match(TokenType.LParen)) + { + if (!match(TokenType.RParen)) + { + argument = expression(); + consume(TokenType.RParen, "Expect ')' after variant argument."); + } + } + return new Variant { Tag = tag, Argument = argument }; } private Expr? record() { return null; - // throw new NotImplementedException("TODO record"); + // TODO record } } diff --git a/ast_classes.fsx b/ast_classes.fsx index 07a2ef5..83ba4ab 100644 --- a/ast_classes.fsx +++ b/ast_classes.fsx @@ -26,6 +26,8 @@ let types = Fields = [ { Type = "Name"; Name = "Value" } ] } { Name = "List" Fields = [ { Type = "Expr[]"; Name = "Elements" } ] } + { Name = "Variant" + Fields = [ { Type = "Name"; Name = "Tag" }; { Type = "Expr?"; Name = "Argument" } ] } { Name = "Selector" Fields = [ { Type = "Expr"; Name = "Left" }; { Type = "Name"; Name = "FieldName" } ] } ]