Parse if-expressions
This commit is contained in:
parent
1264aca7f3
commit
ba5283694e
@ -43,4 +43,9 @@ class ASTPrinter : IVisitor<string>
|
||||
{
|
||||
return parenthesize(expr.Op.lexeme, expr.Right);
|
||||
}
|
||||
|
||||
public string visitIfExpr(If expr)
|
||||
{
|
||||
return parenthesize("if", expr.Condition, expr.Then, expr.Else);
|
||||
}
|
||||
}
|
||||
|
11
Expr.g.cs
11
Expr.g.cs
@ -14,6 +14,7 @@ public interface IVisitor<T> {
|
||||
T visitGroupingExpr(Grouping expr);
|
||||
T visitLiteralExpr(Literal expr);
|
||||
T visitUnaryExpr(Unary expr);
|
||||
T visitIfExpr(If expr);
|
||||
}
|
||||
public class Binary : Expr
|
||||
{
|
||||
@ -50,3 +51,13 @@ public class Unary : Expr
|
||||
return visitor.visitUnaryExpr(this);
|
||||
}
|
||||
}
|
||||
public class If : Expr
|
||||
{
|
||||
public required Expr Condition { get; init; }
|
||||
public required Expr Then { get; init; }
|
||||
public required Expr Else { get; init; }
|
||||
public override T accept<T>(IVisitor<T> visitor)
|
||||
{
|
||||
return visitor.visitIfExpr(this);
|
||||
}
|
||||
}
|
||||
|
16
Parser.cs
16
Parser.cs
@ -143,6 +143,7 @@ class Parser
|
||||
private Expr sum() => binaryLeft(product, TokenType.Minus, TokenType.Plus);
|
||||
|
||||
private Expr product() => binaryLeft(unary, TokenType.Slash, TokenType.Asterisk);
|
||||
|
||||
private Expr unary()
|
||||
{
|
||||
if (match(TokenType.Bang, TokenType.Minus))
|
||||
@ -151,6 +152,21 @@ class Parser
|
||||
Expr right = unary();
|
||||
return new Unary { Op = op, Right = right };
|
||||
}
|
||||
return ifExpr();
|
||||
}
|
||||
|
||||
private Expr ifExpr()
|
||||
{
|
||||
if (match(TokenType.If))
|
||||
{
|
||||
Expr condition = expression();
|
||||
consume(TokenType.Then, "Expect 'then' after condition.");
|
||||
Expr thenCase = expression();
|
||||
consume(TokenType.Else, "Expect 'else' after 'then' case.");
|
||||
Expr elseCase = expression();
|
||||
return new If { Condition = condition, Then = thenCase, Else = elseCase };
|
||||
}
|
||||
|
||||
return primary();
|
||||
}
|
||||
|
||||
|
@ -107,6 +107,7 @@ public enum TokenType
|
||||
PipeLeft,
|
||||
ComposeRight,
|
||||
ComposeLeft,
|
||||
If, Then, Else,
|
||||
When,
|
||||
Is,
|
||||
Let,
|
||||
@ -136,6 +137,9 @@ class Scanner
|
||||
private static readonly Dictionary<String, TokenType> keywords = new Dictionary<string, TokenType>()
|
||||
{
|
||||
{"def", TokenType.Def},
|
||||
{"if", TokenType.If},
|
||||
{"then", TokenType.Then},
|
||||
{"else", TokenType.Else},
|
||||
{"when", TokenType.When},
|
||||
{"is", TokenType.Is},
|
||||
{"let", TokenType.Let},
|
||||
|
@ -14,7 +14,12 @@ let types =
|
||||
[ { Type = "System.Object"
|
||||
Name = "Value" } ] }
|
||||
{ Name = "Unary"
|
||||
Fields = [ { Type = "Token"; Name = "Op" }; { Type = "Expr"; Name = "Right" } ] } ]
|
||||
Fields = [ { Type = "Token"; Name = "Op" }; { Type = "Expr"; Name = "Right" } ] }
|
||||
{ Name = "If"
|
||||
Fields =
|
||||
[ { Type = "Expr"; Name = "Condition" }
|
||||
{ Type = "Expr"; Name = "Then" }
|
||||
{ Type = "Expr"; Name = "Else" } ] } ]
|
||||
|
||||
let visitorMethod baseName t = $"visit{t.Name}{baseName}"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user