Math-Parser

Timon Gehr via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun May 4 15:32:46 PDT 2014


On 05/04/2014 04:56 PM, Tim Holzschuh via Digitalmars-d-learn wrote:
> Am 03.05.2014 21:47, schrieb Timon Gehr via Digitalmars-d-learn:
>> On 05/03/2014 08:20 PM, Tim Holzschuh via Digitalmars-d-learn wrote:
>>>
>>>> Let me know if you also want hints on how to get the logic right.
>>> Would be very nice!
>>> While 2*2 works, 2+2 throws an Error because the number-method gets an
>>> END-Token instead of a Number-Token (although I'm not sure why).
>>>
>>> Thank you,
>>> Tim
>>
>> Get rid of 'revert' and implement the parser in terms of range
>> primitives. (The first thing you do in the while loops should be a
>> popFront().)
>
> Thank you very much, everything is working now!
>
> I have just a few questions left:
>
> The operator-precedence of the mathematical expressions is implemented
> through calling different functions that will parse in the 'mathematical
> way'.
>
> I think for more complex 'interpreters' this would be very inconvenient.
> So.. how is precedence of operators/keywords and so on handled for more
> complex parser? (Or better: What is a way to do it, I think there are
> many ways..)
> ...

http://en.wikipedia.org/wiki/Operator-precedence_parser

> Does anybody have some improvement-suggestions about the code?

Maybe, brevity?
This is roughly how I'd have written the expression evaluator:

double parse(string s){
     int prec(char op){return op=='+'||op=='-'?0:op=='*'||op=='/'?1:-1;}
     double run(char op,double a,double b){
         return op=='+'?a+b:op=='-'?a-b:op=='*'?a*b:a/b;
     }
     double expression()(int l=0){
         auto r=primary();
         while(s.length){
             auto op=s[0],p=prec(op);
             if(l>p) return r;
             s=s[1..$];
             r=run(op,r,expression(p+1));
         }
         return r;
     }
     double primary(){
         if(s[0]=='('){
             s=s[1..$];
             auto r=expression();
             if(s[0]!=')') throw new Exception("unbalanced parentheses");
             s=s[1..$];
             return r;
         }
         auto i=cast(size_t)0,r=0.0;
         for(;i<s.length&&'0'<=s[i]&&s[i]<='9';i++) r=r*10+s[i]-'0';
         if(!i) throw new Exception("expected number");
         s=s[i..$];
         return r;
     }
     auto r=expression();
     if(s.length) throw new Exception("end expected");
     return r;
}

> For example:
> I'm not sure whether the Token-struct is very elegant implemented..
>
> Would in this case a Token-class with a NumberToken subclass be more
> appropriate?

Not really. (You don't want to allocate a class object for every token 
read.)

> Or maybe a union or something other..
>
> Code: https://github.com/tholzschuh/math-parser/
>
> So thanks again!
> (and sorry for the bad english)
>
> Tim



More information about the Digitalmars-d-learn mailing list