View previous topic :: View next topic |
Author |
Message |
davidl
Joined: 17 Aug 2006 Posts: 27
|
Posted: Tue Nov 21, 2006 9:35 am Post subject: how can i make the grammar call from left to right |
|
|
.import("enki.BaseParser");
.import("std.conv");
.import("calc");
.define("String","digit","true","Digit");
Expr = float num
::= AddExpression:num;
AddExpression = float add(num1,num2,opr)
::=
(MulExpression:num1|AddExpression:num1)[ ("+":opr | "-":opr) AddExpression:num2]
;
MulExpression = float mul(num1,num2,opr)
::= number:num1 [("*":opr | "/":opr) MulExpression:num2]
;
number = float toFloat(num1)
::= {digit}:num1;
the grammar would call from right to left
like parse
2+3+4+5
it would call 4+5 then 9+3 then 12+2
it would be alright when plus
consider
2+3-4-5
it would call 4-5 =-1 then 3-(-1) = 4 2+4=6 which is incorrect
and also
2/3*4
it would 3*4 =12 2/12 = 0.1833 but it shouldn't |
|
Back to top |
|
|
pragma
Joined: 28 May 2004 Posts: 607 Location: Washington, DC
|
Posted: Tue Nov 21, 2006 12:32 pm Post subject: Re: how can i make the grammar call from left to right |
|
|
David, you might want to try a grammar that looks a little more like this:
Code: |
Expr ::= Add;
Add ::= Mul [('+' | '-') Add)];
Mul ::= Atom [('*' | '/') Mul];
Atom ::= number | '(' Expr ')';
|
_________________ -- !Eric.t.Anderton at gmail |
|
Back to top |
|
|
davidl
Joined: 17 Aug 2006 Posts: 27
|
Posted: Tue Nov 21, 2006 7:29 pm Post subject: |
|
|
i guess u didn't get my point.
the grammar actually recognize the following sequence
3-4-5 to
3 - Addexpr
and Addexpr= 4-5
and i call add(4,5,'-') which return -1
then call add(3,-1,'-') which return 4
the grammar eval the expr from right to left, if i introduce a stack it's painful
in all it actually add () to the rightest expr, so 3-4-5 actually executed as
(3-(4-5)) , and (3/4/5) would be recognized as (3/(4/5)) |
|
Back to top |
|
|
pragma
Joined: 28 May 2004 Posts: 607 Location: Washington, DC
|
Posted: Wed Nov 22, 2006 10:29 am Post subject: |
|
|
My apologies. You're right about having to add a stack: for something like this, it should be a piece of cake.
I see what I did wrong in my suggestion. Take a look at the calculator grammar here: http://www.nongnu.org/bnf/
Code: | input ::= ws expr ws eoi;
expr ::= ws powterm [{ws '^' ws powterm}];
powterm ::= ws factor [{ws ('*'|'/') ws factor}];
factor ::= ws term [{ws ('+'|'-') ws term}];
term ::= '(' ws expr ws ')' | '-' ws expr | number;
number ::= {dgt} ['.' {dgt}] [('e'|'E') ['-'] {dgt}];
dgt ::= '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9';
ws ::= [{' '|'\t'|'\n'|'\r'}]; |
This should do the trick. From here you can try expanding the grammar into a tree, or just use arrays to store the terms for evaluation:
Code: | expr = float expr(float[] terms)
::= ws powterm:~terms {ws '^' ws powterm:~terms}; |
_________________ -- !Eric.t.Anderton at gmail |
|
Back to top |
|
|
|