2012-01-31 3 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

관련 문제