Parse list literals

This commit is contained in:
Brandon Dyck 2023-07-01 23:13:24 -06:00
parent 6ab36fc489
commit 8de88c0ce3
4 changed files with 54 additions and 5 deletions

View File

@ -69,4 +69,9 @@ class ASTPrinter : IVisitor<string>
{ {
return parenthesize(".", expr.Left, new Identifier { Value = expr.FieldName }); return parenthesize(".", expr.Left, new Identifier { Value = expr.FieldName });
} }
public string visitListExpr(List expr)
{
return parenthesize("list", expr.Elements);
}
} }

View File

@ -4,6 +4,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
using System; using System;
namespace Finn.AST; namespace Finn.AST;
public abstract class Expr { public abstract class Expr {
@ -17,6 +18,7 @@ public interface IVisitor<T> {
T visitUnaryExpr(Unary expr); T visitUnaryExpr(Unary expr);
T visitIfExpr(If expr); T visitIfExpr(If expr);
T visitIdentifierExpr(Identifier expr); T visitIdentifierExpr(Identifier expr);
T visitListExpr(List expr);
T visitSelectorExpr(Selector expr); T visitSelectorExpr(Selector expr);
} }
public class Sequence : Expr public class Sequence : Expr
@ -81,6 +83,14 @@ public class Identifier : Expr
return visitor.visitIdentifierExpr(this); return visitor.visitIdentifierExpr(this);
} }
} }
public class List : Expr
{
public required Expr[] Elements { get; init; }
public override T accept<T>(IVisitor<T> visitor)
{
return visitor.visitListExpr(this);
}
}
public class Selector : Expr public class Selector : Expr
{ {
public required Expr Left { get; init; } public required Expr Left { get; init; }

View File

@ -246,9 +246,9 @@ class Parser
if (match(TokenType.LParen)) if (match(TokenType.LParen))
{ {
Expr expr = expression(); Expr groupedExpr = expression();
consume(TokenType.RParen, "Expect ')' after expression."); consume(TokenType.RParen, "Expect ')' after expression.");
return new Grouping { Expression = expr }; return new Grouping { Expression = groupedExpr };
} }
Expr? expr; Expr? expr;
@ -270,16 +270,47 @@ class Parser
private Expr? list() private Expr? list()
{ {
throw new NotImplementedException("TODO list"); if (!match(TokenType.LBracket))
{
return null;
}
List<Expr> elements = new List<Expr>();
if (!match(TokenType.RBracket))
{
elements.Add(expression());
while (!match(TokenType.RBracket))
{
if (match(TokenType.Comma))
{
if (match(TokenType.RBracket))
{
break;
}
else
{
elements.Add(expression());
}
}
else
{
throw error(previous(), "Expect comma between list elements.");
}
}
}
return new Finn.AST.List { Elements = elements.ToArray() };
} }
private Expr? variant() private Expr? variant()
{ {
throw new NotImplementedException("TODO variant"); return null;
// throw new NotImplementedException("TODO variant");
} }
private Expr? record() private Expr? record()
{ {
throw new NotImplementedException("TODO record"); return null;
// throw new NotImplementedException("TODO record");
} }
} }

View File

@ -24,6 +24,8 @@ let types =
{ Type = "Expr"; Name = "Else" } ] } { Type = "Expr"; Name = "Else" } ] }
{ Name = "Identifier" { Name = "Identifier"
Fields = [ { Type = "Name"; Name = "Value" } ] } Fields = [ { Type = "Name"; Name = "Value" } ] }
{ Name = "List"
Fields = [ { Type = "Expr[]"; Name = "Elements" } ] }
{ Name = "Selector" { Name = "Selector"
Fields = [ { Type = "Expr"; Name = "Left" }; { Type = "Name"; Name = "FieldName" } ] } ] Fields = [ { Type = "Expr"; Name = "Left" }; { Type = "Name"; Name = "FieldName" } ] } ]
@ -64,6 +66,7 @@ let renderAST outputDir baseName types =
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
using System; using System;
namespace Finn.AST; namespace Finn.AST;
public abstract class {baseName} {{ public abstract class {baseName} {{