Skip to content

Commit

Permalink
Use INumer<T> for the parser
Browse files Browse the repository at this point in the history
  • Loading branch information
ewdlop committed Sep 26, 2023
1 parent e32153e commit f04f0db
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 35 deletions.
9 changes: 6 additions & 3 deletions ConsoleApp8/BinOp.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
namespace ConsoleApp8;
using System.Numerics;

public record BinOp(AST Left, Token Op, AST Right) : AST
namespace ConsoleApp8;

public record BinOp<T>(AST<T> Left, Token Op, AST<T> Right) : AST<T>
where T: INumber<T>
{
public override T Accept<T>(IASTVisitor<T> visitor)
public override T Accept(IASTVisitor<T> visitor)
{
return visitor.VisitBinOp(this);
}
Expand Down
13 changes: 8 additions & 5 deletions ConsoleApp8/Evaluator.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
namespace ConsoleApp8;
using System.Globalization;
using System.Numerics;

public class Evaluator : IASTVisitor<double>
namespace ConsoleApp8;

public class Evaluator<T> : IASTVisitor<T> where T : INumber<T>
{
public double VisitBinOp(BinOp binOp)
public T VisitBinOp(BinOp<T> binOp)
{
if (binOp.Op.Type == TokenType.Plus)
return binOp.Left.Accept(this) + binOp.Right.Accept(this);
Expand All @@ -16,8 +19,8 @@ public double VisitBinOp(BinOp binOp)
throw new Exception($"Unknown operator: {binOp.Op.Type}");
}

public double VisitNum(Num num)
public T VisitNum(Num<T> num)
{
return double.Parse(num.Value.Value ?? string.Empty);
return T.TryParse(num.Value.Value ?? string.Empty, CultureInfo.CurrentCulture.NumberFormat,out T? result) ? result : T.Zero;
}
}
14 changes: 8 additions & 6 deletions ConsoleApp8/IASTVisitor.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
namespace ConsoleApp8;
using System.Numerics;

public interface IASTVisitor<T>
namespace ConsoleApp8;

public interface IASTVisitor<T> where T : INumber<T>
{
T VisitBinOp(BinOp binOp);
T VisitNum(Num num);
T VisitBinOp(BinOp<T> binOp);
T VisitNum(Num<T> num);
}

public abstract record AST
public abstract record AST<T> where T : INumber<T>
{
public abstract T Accept<T>(IASTVisitor<T> visitor);
public abstract T Accept(IASTVisitor<T> visitor);
}
8 changes: 5 additions & 3 deletions ConsoleApp8/Num.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
namespace ConsoleApp8;
using System.Numerics;

public record Num(Token Value) : AST
namespace ConsoleApp8;

public record Num<T>(Token Value) : AST<T> where T : INumber<T>
{
public override T Accept<T>(IASTVisitor<T> visitor)
public override T Accept(IASTVisitor<T> visitor)
{
return visitor.VisitNum(this);
}
Expand Down
31 changes: 16 additions & 15 deletions ConsoleApp8/Parser.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
namespace ConsoleApp8;
using System.Numerics;

public class Parser(Lexer lexer)
namespace ConsoleApp8;

public class Parser<T>(Lexer lexer) where T : INumber<T>
{
private Token currentToken = lexer.GetNextToken();
public Token CurrentToken => currentToken;
// Corresponds to EXPRESSION -> TERM '+' EXPRESSION | TERM
public AST Expression()
public AST<T> Expression()
{
var node = Term();
AST<T> node = Term();

while (CurrentToken.Type == TokenType.Plus || CurrentToken.Type == TokenType.Minus)
{
var token = CurrentToken;
Token token = CurrentToken;
if (token.Type == TokenType.Plus)
{
Eat(TokenType.Plus);
Expand All @@ -21,15 +22,15 @@ public AST Expression()
Eat(TokenType.Minus);
}

node = new BinOp(node, token, Term());
node = new BinOp<T>(node, token, Term());
}

return node;
}

public AST Term()
public AST<T> Term()
{
var node = Factor();
AST<T> node = Factor();

while (CurrentToken.Type == TokenType.Times || CurrentToken.Type == TokenType.Div)
{
Expand All @@ -43,33 +44,33 @@ public AST Term()
Eat(TokenType.Div);
}

node = new BinOp(node, token, Factor());
node = new BinOp<T>(node, token, Factor());
}

return node;
}

public AST Factor()
public AST<T> Factor()
{
var token = CurrentToken;
Token token = CurrentToken;

if (token.Type == TokenType.Number)
{
Eat(TokenType.Number);
return new Num(token);
return new Num<T>(token);
}
else if (token.Type == TokenType.LeftParenthesis)
{
Eat(TokenType.LeftParenthesis);
var node = Expression();
AST<T> node = Expression();
Eat(TokenType.RightParenthesis);
return node;
}

throw new Exception("Syntax Error");
}

public AST Parse()
public AST<T> Parse()
{
return Expression();
}
Expand Down
6 changes: 3 additions & 3 deletions ConsoleApp8/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

string input = "(3+5)*2";
Lexer lexer = new Lexer(input);
Parser parser = new Parser(lexer);
AST tree = parser.Parse();
Parser<double> parser = new Parser<double>(lexer);
AST<double> tree = parser.Parse();

Evaluator evaluator = new Evaluator();
Evaluator<double> evaluator = new Evaluator<double>();
double result = tree.Accept(evaluator);
Console.WriteLine(result); // Outputs: 16

0 comments on commit f04f0db

Please sign in to comment.