mirror of
https://github.com/chylex/Query.git
synced 2024-10-16 07:42:46 +02:00
72 lines
2.3 KiB
C#
72 lines
2.3 KiB
C#
using Calculator.Math;
|
|
using Calculator.Parser;
|
|
|
|
namespace Calculator;
|
|
|
|
public sealed class CalculatorExpressionVisitor : ExpressionVisitor<NumberWithUnit> {
|
|
public NumberWithUnit VisitNumber(Expression.Number number) {
|
|
return new NumberWithUnit(number.NumberToken.Value, null);
|
|
}
|
|
|
|
public NumberWithUnit VisitNumbersWithUnits(Expression.NumbersWithUnits numbersWithUnits) {
|
|
NumberWithUnit result = new Number.Rational(0);
|
|
|
|
foreach ((Token.Number number, Unit unit) in numbersWithUnits.NumberTokensWithUnits) {
|
|
result += new NumberWithUnit(number.Value, unit);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public NumberWithUnit VisitGrouping(Expression.Grouping grouping) {
|
|
return Evaluate(grouping.Expression);
|
|
}
|
|
|
|
public NumberWithUnit VisitUnary(Expression.Unary unary) {
|
|
(Token.Simple op, Expression right) = unary;
|
|
|
|
return op.Type switch {
|
|
SimpleTokenType.PLUS => +Evaluate(right),
|
|
SimpleTokenType.MINUS => -Evaluate(right),
|
|
_ => throw new CalculatorException("Unsupported unary operator: " + op.Type)
|
|
};
|
|
}
|
|
|
|
public NumberWithUnit VisitBinary(Expression.Binary binary) {
|
|
(Expression left, Token.Simple op, Expression right) = binary;
|
|
|
|
return op.Type switch {
|
|
SimpleTokenType.PLUS => Evaluate(left) + Evaluate(right),
|
|
SimpleTokenType.MINUS => Evaluate(left) - Evaluate(right),
|
|
SimpleTokenType.STAR => Evaluate(left) * Evaluate(right),
|
|
SimpleTokenType.SLASH => Evaluate(left) / Evaluate(right),
|
|
SimpleTokenType.PERCENT => Evaluate(left) % Evaluate(right),
|
|
SimpleTokenType.CARET => Evaluate(left).Pow(Evaluate(right)),
|
|
_ => throw new CalculatorException("Unsupported binary operator: " + op.Type)
|
|
};
|
|
}
|
|
|
|
public NumberWithUnit VisitUnitAssignment(Expression.UnitAssignment unitAssignment) {
|
|
(Expression left, Unit right) = unitAssignment;
|
|
|
|
NumberWithUnit number = Evaluate(left);
|
|
|
|
if (number.Unit is null) {
|
|
return number with { Unit = right };
|
|
}
|
|
else {
|
|
throw new CalculatorException("Expression already has a unit, cannot assign a new unit: " + right);
|
|
}
|
|
}
|
|
|
|
public NumberWithUnit VisitUnitConversion(Expression.UnitConversion unitConversion) {
|
|
(Expression left, Unit unit) = unitConversion;
|
|
|
|
return Evaluate(left).ConvertTo(unit);
|
|
}
|
|
|
|
private NumberWithUnit Evaluate(Expression expression) {
|
|
return expression.Accept(this);
|
|
}
|
|
}
|