2012-01-31 2 views
3

Для строки, содержащей математическое выражение, заданного набором функций/команд и заданного набора назначенных переменных, существуют ли инструменты, которые .NET обеспечивает для быстрой сборки парсера?Анализ математического выражения

Я хотел бы построить простой синтаксический анализатор, который анализирует выражение и разбивает его на простейшие компоненты, например:

d*(abs(a-b)+sqrt(c))

становится

  1. f = abs(a-b) и g = sqrt(c)
  2. e = f + g
  3. d*e

ответ

1

Отъезд veparser также. Вот пример кода, который показывает, как вы можете построить оценщик выражения (код анализирует выражение и напрямую вычисляет вывод). Этот образец может быть изменен для хранения дерева оценки вместо его запуска.

using System; 
using VeParser; 

public class MathEvaluator : CharParser 
{ 
    protected override Parser GetRootParser() 
    { 
     Func<double, double, double> productFunc = (value1, value2) => value1 * value2; 
     Func<double, double, double> divideFunc = (value1, value2) => value1/value2; 
     Func<double, double, double> sumFunc = (value1, value2) => value1 + value2; 
     Func<double, double, double> subtractFunc = (value1, value2) => value1 - value2; 
     Func<double, double> negativeFunc = value => -value; 
     Func<double, double> posititveFunc = value => value; 


     var dot = token('.'); 
     var op = token('('); 
     var cp = token(')'); 
     var sumOp = create(sumFunc, token('+')); 
     var subtractOp = create(subtractFunc, token('-')); 
     var positiveOp = create(posititveFunc, token('+')); 
     var negativeOp = create(negativeFunc, token('-')); 
     var productOp = create(productFunc, token('*')); 
     var divideOp = create(divideFunc, token('/')); 

     // Numbers 
     var deciamlPlaceValue = 1M; 
     var decimalDot = run(() => { deciamlPlaceValue = 1; }, dot); 
     var digit = consume((n, d) => n * 10 + char.GetNumericValue(d), keep(Digit)); 
     var decimalDigit = consume((n, d) => { deciamlPlaceValue = deciamlPlaceValue * 10; return (double)((decimal)n + ((decimal)char.GetNumericValue(d))/deciamlPlaceValue); }, keep(Digit)); 
     var number = any(
      /* float */ create(0, seq(zeroOrMore(digit), decimalDot, oneOrMore(decimalDigit))), 
      /* int */ create(0, oneOrMore(digit)) 
     ); 

     var expression = createReference(); 
     var simpleExpression = createReference(); 
     // Unary 
     var unaryOp = any(positiveOp, negativeOp); 
     var unaryExpression = update(d => d.action(d.value), 
        createNew(seq(set("action", unaryOp), set("value", expression)))); 
     // Binary 
     var binaryOp = any(sumOp, subtractOp, productOp, divideOp); 

     var binaryExpressinoTree = update(x => x.value1, createNew(
      seq(
       set("value1", simpleExpression), 
       zeroOrMore(
        update(d => { var r = base.CreateDynamicObject(); r.value1 = d.action(d.value1, d.value2); return r; }, 
         seq(
          set("action", binaryOp), 
          set("value2", simpleExpression)))) 
      ))); 


     var privilegedExpressoin = seq(op, expression, cp); 

     setReference(simpleExpression, any(privilegedExpressoin, unaryExpression, number)); 

     setReference(expression, any(binaryExpressinoTree, simpleExpression)); 

     return seq(expression, endOfFile()); 
    } 

    public static object Eval(string expression) 
    { 
     MathEvaluator me = new MathEvaluator(); 
     var result = me.Parse(expression.ToCharArray()); 
     return result; 
    } 
} 
6

Вы хотите создать парсер или просто предоставить решение?

В любом случае, ознакомьтесь с nCalc. Если вам просто нужно его решить, возьмите двоичные файлы. Если вам нужно посмотреть, как они анализируют дерево выражений, возьмите источник.

+0

Ну, я хочу создать простой синтаксический анализатор: эффективность не важна, а скорее расширяемость, что позволяет легко добавлять новые команды. Я прочитаю источник nCalc, поэтому я узнаю что-то новое. Благодаря! – enzom83

4

Я слышал хорошие вещи о генераторе парсера Grammatica. ANTLR также широко используется (особенно на Java).

Я предполагаю, что вы знаете, как определить грамматику BNF, и узнали о или построили парсеры в прошлом.

+0

Прямо сейчас мне нужно что-то более простое. Однако в ближайшие месяцы ваша ссылка может быть полезна для меня. Благодаря! – enzom83

Смежные вопросы