yacc文法规则解决运算符优先级 您所在的位置:网站首页 LEX专栏 yacc文法规则解决运算符优先级

yacc文法规则解决运算符优先级

2023-11-23 03:44| 来源: 网络整理| 查看: 265

优先级错误2-3*4=-4? 

把上一个博文的程序扩展成支持加减乘除的程序,需要扩充cal.y的文法规则

%{ #include %} %token PRINT NUMBER %% statement: PRINT expression { printf("\ntest yacc PRINT expression\n"); printf("result is %d", $2); } |expression { printf("\ntest yacc expression\n"); printf("%d is the result", $1); } ; expression: expression '*' NUMBER { printf("\ntest yacc expression + NUMBER\n"); $$ = $1 * $3; } |expression '/' NUMBER { printf("\ntest yacc expression + NUMBER\n"); $$ = $1 / $3; } |expression '+' NUMBER { printf("\ntest yacc expression + NUMBER\n"); $$ = $1 + $3; } |expression '-' NUMBER { printf("\ntest yacc expression + NUMBER\n"); $$ = $1 - $3; } |NUMBER { printf("\ntest yacc NUMBER\n"); $$ = $1; }

nosourcesmatoMacBook-Pro:cal nosources$ yacc -d cal.y && lex cal.l && cc -o cal yyy.c -ly -ll nosourcesmatoMacBook-Pro:cal nosources$ ./cal print 2-3*4 test lex print test lex NUMBER test yacc NUMBER test lex - test lex NUMBER test yacc expression + NUMBER test lex * test lex NUMBER test yacc expression + NUMBER test yacc PRINT expression result is -4 可见 2-3*4

输出的结果是-4,这个是因为我们的文法没有优先级,我们按照问发的匹配顺序发现确实是会的到-4的结果,怎么让程序先计算3*4呢?两种方式

隐式的指定优先级

cal.y

%{ #include %} %token PRINT NUMBER %% statement: PRINT expression { printf("\ntest yacc PRINT expression\n"); printf("result is %d", $2); } |expression { printf("\ntest yacc expression\n"); printf("%d is the result", $1); } ; expression: expression '+' mulexp { printf("\ntest yacc expression + expression\n"); $$ = $1 + $3; } |expression '-' mulexp { printf("\ntest yacc expression - expression\n"); $$ = $1 - $3; } |mulexp { printf("\ntest yacc mulexp\n"); $$ = $1; } mulexp: |NUMBER '*' NUMBER { printf("\ntest yacc NUMBER '*' NUMBER\n"); $$ = $1 * $3; } |NUMBER '/' NUMBER { printf("\ntest yacc NUMBER '/' NUMBER\n"); $$ = $1 / $3; } |NUMBER { printf("\ntest yacc NUMBER\n"); $$ = $1; } 这样做了之后,mulexp变成了更小的规则,所以会先规约这个规则,优先级也就对了

显示的指定 %{ #include %} %token PRINT NUMBER %left '+' '-' %left '*' '/' %% statement: PRINT expression { printf("\ntest yacc PRINT expression\n"); printf("result is %d", $2); } |expression { printf("\ntest yacc expression\n"); printf("%d is the result", $1); } ; expression: expression '*' expression { printf("\ntest yacc expression + expression\n"); $$ = $1 * $3; } |expression '/' expression { printf("\ntest yacc expression + expression\n"); $$ = $1 / $3; } |expression '+' expression { printf("\ntest yacc expression + expression\n"); $$ = $1 + $3; } |expression '-' expression { printf("\ntest yacc expression + expression\n"); $$ = $1 - $3; } |NUMBER { printf("\ntest yacc NUMBER\n"); $$ = $1; } %left定义了左结合的优先级,也可以用%right定义右结合优先级

什么时候使用优先规则 优先规则不可随便使用,以上例子实在表达式下,大家都很清楚是什么意思,但是通常的程序很难正确理解 有两种情况: 表达是语法,为了解决if-then-else结构中虚挂的else冲突如果可以的话,应该调整语法删除冲突



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有