有没有办法减少这种减少的替代品数量,同时保持LALR(1)?

时间:2012-09-26 14:56:08

标签: bison yacc lalr

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

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 *,我已经能够减少备选方案的数量,但是仍然有九种替代方案可以减少,我想这比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
    ;

任何想法都会受到赞赏。

1 个答案:

答案 0 :(得分: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必须在vararg之后”或某些此类情况),而不仅仅是通用的“语法错误”

修改

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