Irony
Пример калькулятора на Irony.
using System;
using System.Collections.Generic;
using Irony.Parsing;
namespace Irony.SampleApp
{
[Language("Expression Grammar", "1.0", "A simple arithmetic expression grammar.")]
public class ExpressionGrammar : Grammar
{
public ExpressionGrammar() : base(false)
{
//
var number = new NumberLiteral("Number");
//
var Expr = new NonTerminal("Expr");
var Term = new NonTerminal("Term");
var BinExpr = new NonTerminal("BinExpr");
var ParExpr = new NonTerminal("ParExpr");
var UnExpr = new NonTerminal("UnExpr");
var BinOp = new NonTerminal("BinOp", "operator");
//
Expr.Rule = Term | UnExpr | BinExpr;
Term.Rule = number | ParExpr ;
ParExpr.Rule = "(" + Expr + ")";
UnExpr.Rule = ToTerm("-") + Term;
BinExpr.Rule = Expr + BinOp + Expr;
BinOp.Rule = ToTerm("+") | "-" | "*" | "/" | "^";
this.Root = Expr;
//
RegisterOperators(1, "+", "-");
RegisterOperators(2, "*", "/");
RegisterOperators(3, Associativity.Right, "^");
MarkPunctuation("(", ")");
MarkTransient(Term, Expr, BinOp, ParExpr);
}
}
internal sealed class Evaluator
{
public double PerformEvaluate(ParseTreeNode node)
{
switch (node.Term.Name)
{
case "BinExpr":
{
double left = PerformEvaluate(node.ChildNodes[0]);
double right = PerformEvaluate(node.ChildNodes[2]);
switch (node.ChildNodes[1].Term.Name)
{
case "+": return left + right;
case "-": return left - right;
case "*": return left * right;
case "/": return left / right;
case "^": return Math.Pow(left, right);
}
}
break;
case "UnExpr":
{
double left = PerformEvaluate(node.ChildNodes[1]);
return -left;
}
case "Number":
return Convert.ToDouble(node.Token.Text);
}
throw new InvalidOperationException("Unrecognizable term " + node.Term.Name);
}
}
public class Program
{
public static void Main(string[] args)
{
Grammar grammar = new ExpressionGrammar();
Parser parser = new Parser(grammar);
ParseTree parseTree = parser.Parse("2 * -(5 + 1)+4^3");
var evaluator = new Evaluator();
Console.WriteLine("Result={0}",evaluator.PerformEvaluate(parseTree.Root));
}
}
}