Parse function calls

This commit is contained in:
Brandon Dyck 2023-07-02 12:05:46 -06:00
parent 6f742ec577
commit 57cd5b3a9e
4 changed files with 51 additions and 2 deletions

View File

@ -130,4 +130,24 @@ class ASTPrinter : IVisitor<string>
{ {
return parenthesize("index", expr.Left, expr.Index); return parenthesize("index", expr.Left, expr.Index);
} }
public string visitCallExpr(Call expr)
{
var w = new StringWriter();
w.Write("(call ");
w.Write(print(expr.Left));
foreach (var arg in expr.Arguments)
{
if (arg == null)
{
w.Write(" _");
}
else
{
w.Write($" {print(arg)}");
}
}
w.Write(')');
return w.ToString();
}
} }

View File

@ -23,6 +23,7 @@ public interface IVisitor<T> {
T visitRecordExpr(Record expr); T visitRecordExpr(Record expr);
T visitSelectorExpr(Selector expr); T visitSelectorExpr(Selector expr);
T visitIndexerExpr(Indexer expr); T visitIndexerExpr(Indexer expr);
T visitCallExpr(Call expr);
} }
public class Sequence : Expr public class Sequence : Expr
{ {
@ -130,3 +131,12 @@ public class Indexer : Expr
return visitor.visitIndexerExpr(this); return visitor.visitIndexerExpr(this);
} }
} }
public class Call : Expr
{
public required Expr Left { get; init; }
public required Expr?[] Arguments { get; init; }
public override T accept<T>(IVisitor<T> visitor)
{
return visitor.visitCallExpr(this);
}
}

View File

@ -227,7 +227,24 @@ class Parser
if (match(TokenType.LParen)) if (match(TokenType.LParen))
{ {
throw new NotImplementedException("TODO apply"); var args = new List<Expr?>();
while (!check(TokenType.RParen))
{
if (match(TokenType.Blank))
{
args.Add(null);
}
else
{
args.Add(expression());
}
if (!match(TokenType.Comma))
{
break;
}
}
consume(TokenType.RParen, "Expect '(' after arguments.");
return new Call { Left = expr, Arguments = args.ToArray() };
} }
return expr; return expr;

View File

@ -36,7 +36,9 @@ let types =
{ Name = "Selector" { Name = "Selector"
Fields = [ { Type = "Expr"; Name = "Left" }; { Type = "Name"; Name = "FieldName" } ] } Fields = [ { Type = "Expr"; Name = "Left" }; { Type = "Name"; Name = "FieldName" } ] }
{ Name = "Indexer" { Name = "Indexer"
Fields = [ { Type = "Expr"; Name = "Left" }; { Type = "Expr"; Name = "Index" } ] } ] Fields = [ { Type = "Expr"; Name = "Left" }; { Type = "Expr"; Name = "Index" } ] }
{ Name = "Call"
Fields = [ { Type = "Expr"; Name = "Left" }; { Type = "Expr?[]"; Name = "Arguments" } ] } ]
let visitorMethod baseName t = $"visit{t.Name}{baseName}" let visitorMethod baseName t = $"visit{t.Name}{baseName}"