对没有终端的规则使用yacc优先级,只使用非终端

时间:2014-04-23 21:33:51

标签: bison yacc

可能有人帮助我,我有这个规则:

e   : T_NUM                                            { $$ = mk_int($1);}
| T_POP e[l]                                       { $$ = mk_app(mk_op(POP),$l);}
| T_NEXT e[l]                                      { $$ = mk_app(mk_op(NEXT),$l);}
| "{" e[x] "," e[y] "}"                            { $$ = mk_point($x,$y);}
| e T_PLUS e                                       { $$ = mk_app(mk_app(mk_op(PLUS),$1),$3);}
| e T_MINUS e                                      { $$ = mk_app(mk_app(mk_op(MINUS),$1),$3);}
| e T_DIV e                                        { $$ = mk_app(mk_app(mk_op(DIV),$1),$3);}
| e T_MULT e                                       { $$ = mk_app(mk_app(mk_op(MULT),$1),$3);}
| e T_LEQ e                                        { $$ = mk_app(mk_app(mk_op(LEQ),$1),$3) ;}
| e T_LE e                                         { $$ = mk_app(mk_app(mk_op(LE),$1),$3) ;}
| e T_GEQ e                                        { $$ = mk_app(mk_app(mk_op(GEQ),$1),$3) ;}
| e T_GE e                                         { $$ = mk_app(mk_app(mk_op(GE),$1),$3) ;}
| e T_OR e                                         { $$ = mk_app(mk_app(mk_op(OR),$1),$3) ;}
| e T_AND e                                        { $$ = mk_app(mk_app(mk_op(AND),$1),$3) ;}
| T_ID                                             { $$ = mk_id($1);}/*Reconnaissance d'identificateurs et de variables*/
| e T_EQ e                                         { $$ = mk_app(mk_app(mk_op(EQ),$1),$3) ;}
| T_NOT e[expr]                                    { $$ = mk_app(mk_op(NOT),$expr) ;}
| T_FUN T_ID[var] arg_list[expr]                   { $$ = mk_fun($var,$expr);env = push_rec_env($var,$$,env);} /*Définition de fonctions*/
| T_LET T_ID[x] T_EQUAL e[arg] T_IN e[exp]         { $$ = mk_app(mk_fun($x,$exp),$arg); env = push_rec_env($x,$$,env);}/*Fonction IN*/
| e[exp] T_WHERE T_ID[x] T_EQUAL e[arg]            { $$ = mk_app(mk_fun($x,$exp),$arg); env = push_rec_env($x,$$,env);}/*Fonction WHERE*/
| T_IF e[cond] T_THEN e[then_br] T_ELSE e[else_br] { $$ = mk_cond($cond, $then_br, $else_br) ;}
| '[' list[l] ']'                                  { $$ = $l;}/*OP sur Listes*/
| e[exp] T_PUSH e[l]                               { $$ = mk_app(mk_app(mk_op(PUSH),$exp),$l);} 
| '(' f_arg[fun] e[arg] ')'                        { $$ = mk_app($fun,$arg);}/*Exécution de fonctions à plusieurs variables*/
| '(' e ')'                                        { $$ = $2;}/*Ignorer les parentheses inutiles*/
;

我的问题是在'('f_arg [fun] e [arg]')'我想删除语法周围的'()'但这会产生大量冲突,所以如果有人可以帮我一把如何在没有括号的情况下更改此语法 有关f_arg的信息:

f_arg :e                                                            {$$ = $1;}
  |f_arg[fun] e[arg]                                            {$$ = mk_app($fun,$arg);}
  ;

感谢所有

可以在

找到完整的代码

https://github.com/WillianPaiva/project_AS

抱歉我的英文

2 个答案:

答案 0 :(得分:1)

好吧,我没有尝试编译和测试它。但是,在删除'(')'时,您似乎正在创建一个包含规则的循环。您说e->f_arg然后f_arg->e。显然这会产生冲突。

如果您将| '(' f_arg[fun] e[arg] ')'替换为| e[arg] f_arg[fun],并将f_arg :e替换为f_arg :(空规则)。然后,您需要重新配置语法的所有操作,即每个规则前面的代码。

如果我的建议不起作用,您必须找到一种方法来删除ef_arg之间的循环

答案 1 :(得分:1)

问题在于,对于所有二进制中缀和前缀oparators,未经修饰的函数应用程序是不明确的 - 如果a b + c之类的输入被解析为(a b) + ca (b + c)?由于功能应用程序中没有任何令牌,因此正常的yacc / bison优先级规则在没有额外帮助的情况下无法使用。

假设你想给函数应用程序赋予最高优先级(正常情况,我相信),你可以通过一些额外的工作来完成这项工作。

将以下优先规则添加到列表末尾(最高优先级):

%left FUNCTION_APPLICATION T_NUM T_ID '{' '('

制定你的职能规则:

| e[fun] e[arg] %prec FUNCTION_APPLICATION { $$ = mk_app($fun,$arg); }

取决于语法中的其他内容,您可能需要在优先级规则中添加更多标记和/或稍微重新排列。特别是,FIRST(e)中的每个标记都需要一个优先级,如果它对函数应用程序的优先级与其它用途的优先级不同,那么事情就不会起作用(因为每个标记只能有一个优先级)。只要函数应用程序的优先级高于其他所有函数,事情就应该是可解析的。