diff --git a/AST.cs b/AST.cs index 65d701d..75f47b8 100644 --- a/AST.cs +++ b/AST.cs @@ -60,4 +60,12 @@ public partial record Let { return $"Let {{ Bindings = {string.Join(", ", (IEnumerable)(this.Bindings))}, Body = {this.Body} }}"; } +} + +public partial record RecordPattern +{ + public override string ToString() + { + return $"Let {{ Bindings = {string.Join(", ", (IEnumerable)(this.Fields))}, Rest = {this.Rest} }}"; + } } \ No newline at end of file diff --git a/Parser.cs b/Parser.cs index 4a25549..f2057d3 100644 --- a/Parser.cs +++ b/Parser.cs @@ -167,7 +167,25 @@ class Parser { return null; } - throw new NotImplementedException("TODO record pattern"); + + List fields = new List(); + while (!check(TokenType.RBrace, TokenType.Pipe)) + { + var fieldName = name(); + if (fieldName == null) + { + throw error(peek(), "Expect identifier as field name."); + } + var pat = match(TokenType.Equal) ? pattern() : null; + fields.Add(new(fieldName, pat)); + if (!match(TokenType.Comma)) + { + break; + } + } + var restPattern = match(TokenType.Pipe) ? simplePattern() : null; + consume(TokenType.RBrace, "Expect '}' at end of record pattern."); + return new(fields.ToArray(), restPattern); } private VariantPattern? variantPattern() @@ -190,7 +208,7 @@ class Parser return new(tag, argument); } - private Pattern pattern() + private SimplePattern? simplePattern() { if (match(TokenType.Blank)) { @@ -203,8 +221,17 @@ class Parser return new SimplePattern(identifier); } - Pattern? p = recordPattern(); - if (p != null) + return null; + } + + private Pattern pattern() + { + Pattern? p; + if ((p = simplePattern()) != null) + { + return p; + } + if ((p = recordPattern()) != null) { return p; } @@ -212,7 +239,15 @@ class Parser { return p; } - throw error(peek(), "Expect pattern after 'let'."); + if (check(TokenType.String)) + { + throw error(peek(), "Cannot pattern-match string literals."); + } + if (check(TokenType.Number)) + { + throw error(peek(), "Cannot pattern-match numbers."); + } + throw error(peek(), "Expect pattern."); } private Expr let()