yacc文法规则解决运算符优先级 | 您所在的位置:网站首页 › LEX专栏 › yacc文法规则解决运算符优先级 |
优先级错误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 实验室设备网 版权所有 |