Parse variants

This commit is contained in:
Brandon Dyck 2023-07-01 23:30:24 -06:00
parent 8de88c0ce3
commit 5b0ca1ca6d
4 changed files with 41 additions and 3 deletions

View File

@ -74,4 +74,13 @@ class ASTPrinter : IVisitor<string>
{ {
return parenthesize("list", expr.Elements); 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);
}
} }

View File

@ -19,6 +19,7 @@ public interface IVisitor<T> {
T visitIfExpr(If expr); T visitIfExpr(If expr);
T visitIdentifierExpr(Identifier expr); T visitIdentifierExpr(Identifier expr);
T visitListExpr(List expr); T visitListExpr(List expr);
T visitVariantExpr(Variant expr);
T visitSelectorExpr(Selector expr); T visitSelectorExpr(Selector expr);
} }
public class Sequence : Expr public class Sequence : Expr
@ -91,6 +92,15 @@ public class List : Expr
return visitor.visitListExpr(this); return visitor.visitListExpr(this);
} }
} }
public class Variant : Expr
{
public required Name Tag { get; init; }
public required Expr? Argument { get; init; }
public override T accept<T>(IVisitor<T> visitor)
{
return visitor.visitVariantExpr(this);
}
}
public class Selector : Expr public class Selector : Expr
{ {
public required Expr Left { get; init; } public required Expr Left { get; init; }

View File

@ -304,13 +304,30 @@ class Parser
private Expr? variant() private Expr? variant()
{ {
return null; if (!match(TokenType.Backtick))
// throw new NotImplementedException("TODO variant"); {
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() private Expr? record()
{ {
return null; return null;
// throw new NotImplementedException("TODO record"); // TODO record
} }
} }

View File

@ -26,6 +26,8 @@ let types =
Fields = [ { Type = "Name"; Name = "Value" } ] } Fields = [ { Type = "Name"; Name = "Value" } ] }
{ Name = "List" { Name = "List"
Fields = [ { Type = "Expr[]"; Name = "Elements" } ] } Fields = [ { Type = "Expr[]"; Name = "Elements" } ] }
{ Name = "Variant"
Fields = [ { Type = "Name"; Name = "Tag" }; { Type = "Expr?"; Name = "Argument" } ] }
{ Name = "Selector" { Name = "Selector"
Fields = [ { Type = "Expr"; Name = "Left" }; { Type = "Name"; Name = "FieldName" } ] } ] Fields = [ { Type = "Expr"; Name = "Left" }; { Type = "Name"; Name = "FieldName" } ] } ]