How can I have an “implicit multiplication” rule with Bison?

十年热恋 提交于 2019-11-30 18:38:28

问题


I'm working on a Bison file for a mathematical expression parser. Up to now it's mostly fine, but I'm facing a problem with implicit multiplications.

You see, I'd like to support expressions like 2x sin(4x) cos(4x). It should parse like 2 * x * sin(4 * x) * cos(4 * x). Nothing too bad here, but consider the following set of rules:

expr
    : /* snip */
    | '-' expr      { /* negate expression */ }
    | expr '-' expr { /* subtract expressions */ }
    | expr expr     { /* multiply expressions */ }

Having that implicit multiplication rule creates an ambiguity with the subtraction rule: is x - log(x) the subtraction of log(x) to x or the multiplication of x by -log(x)?

I'd be ready to settle for an easy solution, like "it's a multiplication unless it's subtracting", but I don't know how to tell that to Bison.


回答1:


Having that implicit multiplication rule creates an ambiguity with the subtraction rule: is x - log(x) the subtraction of log(x) to x or the multiplication of x by -log(x)?

Or even, is it x - l * o * g * x? Or maybe just x - log * x?

So not quite a simple problem. Suppose you can tell just by looking at log that it is a function. Then you can disambiguate in your lexer, and you're left with "in case of doubt, an operator that looks like an infix operator is an infix operator". Here's a quick solution:

term   : ID
       | NUMBER
       | '(' expr ')'      { $$ = $2; }
       | FUNC '(' expr ')' { $$ = new_expr($1, 'c', $3); }
       ;

factor : term
       | term factor       { $$ = new_expr($1, '*', $2); }
       ;

prefix : factor
       | '-' factor        { $$ = new_expr(0, '-', $2); }
       ;

muldiv : prefix
       | muldiv '/' prefix { $$ = new_expr($1, '/', $3); }
       | muldiv '*' prefix { $$ = new_expr($1, '*', $3); }
       ;

expr   : muldiv
       | expr '+' muldiv { $$ = new_expr($1, '+', $3); }
       | expr '-' muldiv { $$ = new_expr($1, '-', $3); }
       ;

This particular grammar disallows --x, although it's perfectly happy with y--x, which means y-(-x). If you want to accept --x, you could change the second prefix production to '-' prefix.

Personally, I'd prefer to be able to type sin 2x and log 3n but that starts to get a bit tricky. What does sin 2x cos 2x mean? Presumably, it means (sin(2*x))*(cos(2*x)). But does log nlog n not mean log(n*log(n)) ? This can all be achieved; it just requires thinking through all the possibilities.



来源:https://stackoverflow.com/questions/12875573/how-can-i-have-an-implicit-multiplication-rule-with-bison

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!