Parse if-expressions
This commit is contained in:
		@@ -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}"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user