Bison-根据语法预期处理expr

Bison-根据语法预期处理expr,bison,yacc,Bison,Yacc,我正在开发一种使用常量、变量和数组的语法。数组可以类似于name[]或类似于name。 每个语句都使用expr或数组之类的参数。 在解析时,变量和不带[]的数组名之间没有区别 语句可以有多种语法,如: APPSOME expr APPSOME array, expr APPSOME1 expr APPSOME1 array expr APPSOME2 expr, expr APPSOME2 array expr, expr 但如果我在应用程序中使用语句APPSOME variable,Bis

我正在开发一种使用常量、变量和数组的语法。数组可以类似于name[]或类似于name。 每个语句都使用expr或数组之类的参数。 在解析时,变量和不带[]的数组名之间没有区别

语句可以有多种语法,如:

APPSOME expr
APPSOME array, expr
APPSOME1 expr
APPSOME1 array expr
APPSOME2 expr, expr
APPSOME2 array expr, expr
但如果我在应用程序中使用语句APPSOME variable,Bison将变量还原为args_变量,然后再转换为args_数组,即使只有一个参数。 我希望该程序检测到此语句只有一个参数,并使用第一个语法APPSOME expr。只有当语句有两个参数时,如APPSOME数组,expr,我想使用第二种语法APPSOME数组,expr

我该怎么做?请记住,数组在中间规则中有一些操作可以将数组放到应用程序堆栈中。 那么,我如何强制Bison根据语法预期将变量作为变量/数组来处理呢

编辑


这种语法有几个问题

APPSOME1实际上没有问题,它采用expr或数组expr。只要看到逗号,就可以清楚地选择哪个选项,但请参见下面关于括号的内容。但是,APPSOME2不起作用:

APPSOME2: expr ',' expr
        | array ',' expr ',' expr
在这里,在遇到第二个逗号之前是不可能消除歧义的,而第二个逗号可能与解析器需要在第一个逗号之前做出决定的点之间存在任意距离

另一个复杂的问题是两者之间产生的歧义

args_variable
    : APPVARIABLE
    | '(' args_variable ')'
expr: args_variable
    | '(' expr ')'
当解析器看到时,它无法知道最后一个结果是否适用,因为这取决于a是否在括号表达式后面

就我个人而言,我会通过不允许数组参数被插入括号来解决这个问题,但是你也可以通过引入一个插入括号的参数non-terminal来解决这个问题,它允许将决策推迟到最后一个右括号之后。那就意味着如果你有

APPSOME1 (((ARRAYNAME))), expr
您可以避免在ARRAYNAME上执行必要的操作,直到遇到最后一个右括号,看起来应该是这样

但是对于APPSOME2问题没有这样简单的解决方法

通常,我建议使用GLR解析器来解决这样的问题。因为语法实际上并不含糊不清,就我所见,GLR算法应该能够处理这样一个事实:对于任何k,语法都不是LRk。但是你需要仔细考虑解析器动作的处理;在bison构建的GLR解析器中,在解析器知道需要哪些操作之前,操作不会被处理,这意味着在读取更多的令牌之前,操作可能不会被执行。通常情况下,这并不重要,但如果您要将符号表信息反馈回词法扫描仪,这将不起作用

当然,总是有可能更改语法,以使arraynames的使用不那么模棱两可。例如,您可以使用如下语法:

APPSOME expr
APPSOME array, expr
APPSOME1 expr
APPSOME1 array expr
APPSOME2 expr, expr
APPSOME2 array expr, expr

其中数组引用根本不使用逗号。这对您的用户来说可能有点微妙,但也可能使代码更容易阅读,因为它提供了一个视觉提示,说明命令名后面的第一件事是否要用作数组。

您必须显示更多语法,因为我在这里看到的似乎没有显示您所询问的行为。顺便说一下,单元规则末尾的操作不是中间规则操作,尽管其行为类似。我添加了一个最小的代码。谢谢,这很清楚。