1

我目前减少了野牛,这意味着将逗号分隔的列表与几个可选的不同规则相匹配:

arg_list
    :
    | expr_list
    | assignment_list
    | expr_list ',' assignment_list
    | varargs
    | expr_list ',' varargs
    | assignment_list ',' varargs
    | expr_list ',' assignment_list ',' varargs
    | varkwdargs
    | expr_list ',' varkwdargs
    | assignment_list ',' varkwdargs
    | expr_list ',' assignment_list ',' varkwdargs
    | varargs ',' varkwdargs
    | expr_list ',' varargs ',' varkwdargs
    | assignment_list ',' varargs ',' varkwdargs
    | expr_list ',' assignment_list ',' varargs ',' varkwdargs
    ;

如果不清楚,这意味着实现(在伪代码中):

arg_list
    :
    | expr_list [',' assignment_list] [',' varargs] [',' varkwdargs]
    | assignment_list [',' varargs] [',' varkwdargs]
    | varargs [',' varkwdargs]
    | varkwdargs
    ;

这样做的方法是实施,例如:

optional_assignment_list:
    :
    | ',' assignment_list
    ;

然而,后一个公式不是 LALR(1),因为在 Bison 看到逗号的每一步,它必须决定是转移并寻找一个 *assignment_list* 还是减少一个空的 *optional_assignment_list* 并继续前进寻找* optional_varargs *。

我正在尝试寻找是否有更好的方法来表示这一点。我已经能够通过引入 *optional_varkwdargs* 来减少备选方案的数量,但这仍然留下了 9 个备选方案来减少,我猜这比 16 个要好:

optional_varkwdargs
    :
    | ',' varkwdargs
    ;

arg_list
    :
    | expr_list optional_varkwdargs
    | assignment_list optional_varkwdargs
    | expr_list ',' assignment_list optional_varkwdargs
    | varargs optional_varkwdargs
    | expr_list ',' varargs optional_varkwdargs
    | assignment_list ',' varargs optional_varkwdargs
    | expr_list ',' assignment_list ',' varargs optional_varkwdargs
    | varkwdargs
    ;

任何想法,将不胜感激。

4

1 回答 1

3

好吧,一种可能性是拥有一个更通用的 arglist 解析器,它允许以任何顺序列出任何这些事物:

arg_list: arg_item 
          { $$ = CreateSingletonArgList($1); }
        | arg_list ',' arg_item
          { if (CheckArgListOrdering($1, $3))
                $$ = AppendArgList($1, $3);
            else
                $$ = $1; }
        ;

arg_item: expr
        | assignment
        | vararg
        | varkwarg
        ;

然后,您对 arg_list 进行解析后检查,以确保事情不会以错误的顺序出现。这样做的好处是您可以为这些情况提供更好的错误消息(“kwarg must be after vararg”或类似的),而不仅仅是通用的“语法错误”

编辑

通过规则中的上述操作,CheckArgListOrdering 函数会检查以确保 arg_item 可以跟踪现有 arg_list 中的所有内容,如果没有,则发出适当的错误消息。返回值告诉解析器是接受新的 arg_item 还是将其丢弃。Create/Append 函数只是将 arg_lists 管理为任何类型的有序集合数据结构(可能是链表、数组或其他任何合适的)。

于 2012-09-26T16:24:16.787 回答