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

14
AST.cs
View File

@ -40,8 +40,6 @@ public partial record Literal
} }
} }
public record Binding(Pattern Pattern, Expr Value);
public partial record SimplePattern public partial record SimplePattern
{ {
public override string ToString() 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 partial record Let
{ {
public override string ToString() public override string ToString()
@ -68,4 +76,4 @@ public partial record RecordPattern
{ {
return $"Let {{ Bindings = {string.Join(", ", (IEnumerable<object?>)(this.Fields))}, Rest = {this.Rest} }}"; return $"Let {{ Bindings = {string.Join(", ", (IEnumerable<object?>)(this.Fields))}, Rest = {this.Rest} }}";
} }
} }

View File

@ -248,20 +248,53 @@ class Parser
return ifExpr(); return ifExpr();
} }
// TODO Add function bindings.
List<Binding> bindings = new List<Binding>(); List<Binding> bindings = new List<Binding>();
Pattern p = pattern(); bindings.Add(parseBinding());
consume(TokenType.Equal, "Expect '=' after pattern.");
bindings.Add(new(p, expression()));
while (match(TokenType.And)) while (match(TokenType.And))
{ {
p = pattern(); bindings.Add(parseBinding());
consume(TokenType.Equal, "Expect '=' after pattern.");
bindings.Add(new(p, expression()));
} }
consume(TokenType.In, "Expect 'in' after let-bindings."); consume(TokenType.In, "Expect 'in' after let-bindings.");
Expr body = expression(); Expr body = expression();
return new Let(bindings.ToArray(), body); 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() private Expr ifExpr()
@ -300,7 +333,7 @@ class Parser
Pattern pat = pattern(); Pattern pat = pattern();
consume(TokenType.DoubleArrow, "Expect '=>' after pattern."); consume(TokenType.DoubleArrow, "Expect '=>' after pattern.");
Expr value = expression(); Expr value = expression();
return new(pat, value); return new VarBinding(pat, value);
} }
} }
@ -357,7 +390,7 @@ class Parser
break; break;
} }
} }
consume(TokenType.RParen, "Expect '(' after arguments."); consume(TokenType.RParen, "Expect ')' after arguments.");
return new Call(expr, args.ToArray()); return new Call(expr, args.ToArray());
} }