Parse function bindings

This commit is contained in:
Brandon Dyck 2023-07-05 10:18:27 -06:00
parent 4fe56dbdbc
commit eed952d154
2 changed files with 53 additions and 12 deletions

12
AST.cs
View File

@ -40,8 +40,6 @@ public partial record Literal
}
}
public record Binding(Pattern Pattern, Expr Value);
public partial record SimplePattern
{
public override string ToString()
@ -54,6 +52,16 @@ public partial record SimplePattern
}
}
public abstract record Binding(Expr Value);
public record VarBinding(Pattern Pattern, Expr Value) : Binding(Value);
public record FuncBinding(Name Name, SimplePattern[] Params, Expr Value) : Binding(Value)
{
public override string ToString()
{
return $"FuncBinding {{ Name = {Name}, Params = {string.Join(", ", (IEnumerable<object?>)(this.Params))}, Value = {this.Value} }}";
}
}
public partial record Let
{
public override string ToString()

View File

@ -248,20 +248,53 @@ class Parser
return ifExpr();
}
// TODO Add function bindings.
List<Binding> bindings = new List<Binding>();
Pattern p = pattern();
consume(TokenType.Equal, "Expect '=' after pattern.");
bindings.Add(new(p, expression()));
bindings.Add(parseBinding());
while (match(TokenType.And))
{
p = pattern();
consume(TokenType.Equal, "Expect '=' after pattern.");
bindings.Add(new(p, expression()));
bindings.Add(parseBinding());
}
consume(TokenType.In, "Expect 'in' after let-bindings.");
Expr body = expression();
return new Let(bindings.ToArray(), body);
Binding parseBinding()
{
Pattern p = pattern();
switch (p)
{
case (SimplePattern(var funcName)) when funcName != null && match(TokenType.LParen):
List<SimplePattern> funcParams = new List<SimplePattern>();
while (!check(TokenType.RParen))
{
Name? paramName;
if (match(TokenType.Blank))
{
funcParams.Add(new(null));
}
else if ((paramName = name()) != null)
{
funcParams.Add(new(paramName));
}
else
{
throw error(peek(), "Expect identifier or '_' as function parameter.");
}
if (!match(TokenType.Comma))
{
break;
}
}
consume(TokenType.RParen, "Expect ')' at end of parameters.");
consume(TokenType.Equal, "Expect '=' after parameters.");
return new FuncBinding(funcName, funcParams.ToArray(), expression());
default:
consume(TokenType.Equal, "Expect '=' after pattern.");
return new VarBinding(p, expression());
}
}
}
private Expr ifExpr()
@ -300,7 +333,7 @@ class Parser
Pattern pat = pattern();
consume(TokenType.DoubleArrow, "Expect '=>' after pattern.");
Expr value = expression();
return new(pat, value);
return new VarBinding(pat, value);
}
}
@ -357,7 +390,7 @@ class Parser
break;
}
}
consume(TokenType.RParen, "Expect '(' after arguments.");
consume(TokenType.RParen, "Expect ')' after arguments.");
return new Call(expr, args.ToArray());
}