Yacc 打印一个与指定的不同的联合变量
Yacc prints a different union variable than the one specified
我正在尝试在 flex/yacc 中实现一个也支持实数的计算器(我还没有实现)。但是出于某种原因,我的代码没有打印表达式的值,而是只打印了表达式的类型,即 1 表示整数。这是 flex 文件
%{
#include <stdio.h>
#include "y.tab.h"
int c;
%}
%%
" " ;
[a-z] {
c = yytext[0];
yylval.a = c - 'a';
return(LETTER);
}
[0-9] {
c = yytext[0];
yylval.a = c - '0';
return(DIGIT);
}
[^a-z0-9\b] {
c = yytext[0];
return(c);
}
%%
这是 yacc 文件
%{
#include <stdio.h>
#include <math.h>
int iregs[26];
double dregs[26];
char type[26];
int base = 10;
void yyerror(char*);
int yywrap();
int yyparse();
int yylex();
%}
%start list
%union
{
int a;
double b;
char type; /* 0 for double , 1 for integer */
}
%token DIGIT LETTER
%left '|'
%left '&'
%left '+' '-'
%left '*' '/' '%'
%left UMINUS /*supplies precedence for unary minus */
%% /* beginning of rules section */
list: /*empty */
|
list stat '\n'
|
list error '\n'
{
yyerrok;
}
;
stat: expr
{
if(.type) {
printf("%d\n",.a);
}
else {
printf("%f\n",.b);
}
}
|
LETTER '=' expr
{
if(.type) {
iregs[.a] = .a;
type[.a] = 1;
}
else {
dregs[.a] = .b;
type[.a] = 0;
}
}
;
expr: '(' expr ')'
{
$$ = ;
}
|
expr '*' expr
{
if(.type && .type) { /* both integers */
$$.a = .a * .a;
$$.type = 1;
}
else if (!.type && !.type) { /* both doubles */
$$.b = .b * .b;
$$.type = 0;
}
else if (.type && !.type) { /* first integer second double */
$$.b = .a * .b;
$$.type = 0;
}
else { /* first double second integer */
$$.b = .b * .a;
$$.type = 0;
}
}
|
expr '/' expr
{
if(.type && .type) { /* both integers */
$$.a = .a / .a;
$$.type = 1;
}
else if (!.type && !.type) { /* both doubles */
$$.b = .b / .b;
$$.type = 0;
}
else if (.type && !.type) { /* first integer second double */
$$.b = .a / .b;
$$.type = 0;
}
else { /* first double second integer */
$$.b = .b / .a;
$$.type = 0;
}
}
|
expr '%' expr
{
if(.type && .type) { /* both integers */
$$.a = .a % .a;
$$.type = 1;
}
else { /* at least one double */
yyerror("% is applied to integers only");
}
}
|
expr '+' expr
{
if(.type && .type) { /* both integers */
$$.a = .a + .a;
$$.type = 1;
}
else if (!.type && !.type) { /* both doubles */
$$.b = .b + .b;
$$.type = 0;
}
else if (.type && !.type) { /* first integer second double */
$$.b = .a + .b;
$$.type = 0;
}
else { /* first double second integer */
$$.b = .b + .a;
$$.type = 0;
}
}
|
expr '-' expr
{
if(.type && .type) { /* both integers */
$$.a = .a - .a;
$$.type = 1;
}
else if (!.type && !.type) { /* both doubles */
$$.b = .b - .b;
$$.type = 0;
}
else if (.type && !.type) { /* first integer second double */
$$.b = .a - .b;
$$.type = 0;
}
else { /* first double second integer */
$$.b = .b - .a;
$$.type = 0;
}
}
|
expr '&' expr
{
if(.type && .type) { /* both integers */
$$.a = .a & .a;
$$.type = 1;
}
else { /* at least one double */
yyerror("& is applied to integers only");
}
}
|
expr '|' expr
{
if(.type && .type) { /* both integers */
$$.a = .a | .a;
$$.type = 1;
}
else { /* at least one double */
yyerror("| is applied to integers only");
}
}
|
'-' expr %prec UMINUS
{
if(.type) {
$$.a = -.a;
$$.type = 1;
}
else {
$$.b = -.b;
$$.type = 0;
}
}
|
LETTER
{
if(type[.a]) {
$$.a = iregs[.a];
$$.type = 1;
}
else {
$$.b = dregs[.a];
$$.type = 0;
}
}
|
integer
{
$$.a = .a;
$$.type = 1;
}
;
integer: DIGIT
{
$$.a = .a;
}
|
integer DIGIT
{
$$.a = base * .a + .a;
}
;
%%
int main()
{
return(yyparse());
}
void yyerror(s)
char *s;
{
fprintf(stderr, "%s\n",s);
}
int yywrap()
{
return(1);
}
因为我在我的测试文件中使用整数,所以无论我使用什么表达式,这段代码只打印 1,我不知道为什么。
每个标记和语法规则只能使用联合中的一个值,而不是整个联合作为一个结构。
我正在尝试在 flex/yacc 中实现一个也支持实数的计算器(我还没有实现)。但是出于某种原因,我的代码没有打印表达式的值,而是只打印了表达式的类型,即 1 表示整数。这是 flex 文件
%{
#include <stdio.h>
#include "y.tab.h"
int c;
%}
%%
" " ;
[a-z] {
c = yytext[0];
yylval.a = c - 'a';
return(LETTER);
}
[0-9] {
c = yytext[0];
yylval.a = c - '0';
return(DIGIT);
}
[^a-z0-9\b] {
c = yytext[0];
return(c);
}
%%
这是 yacc 文件
%{
#include <stdio.h>
#include <math.h>
int iregs[26];
double dregs[26];
char type[26];
int base = 10;
void yyerror(char*);
int yywrap();
int yyparse();
int yylex();
%}
%start list
%union
{
int a;
double b;
char type; /* 0 for double , 1 for integer */
}
%token DIGIT LETTER
%left '|'
%left '&'
%left '+' '-'
%left '*' '/' '%'
%left UMINUS /*supplies precedence for unary minus */
%% /* beginning of rules section */
list: /*empty */
|
list stat '\n'
|
list error '\n'
{
yyerrok;
}
;
stat: expr
{
if(.type) {
printf("%d\n",.a);
}
else {
printf("%f\n",.b);
}
}
|
LETTER '=' expr
{
if(.type) {
iregs[.a] = .a;
type[.a] = 1;
}
else {
dregs[.a] = .b;
type[.a] = 0;
}
}
;
expr: '(' expr ')'
{
$$ = ;
}
|
expr '*' expr
{
if(.type && .type) { /* both integers */
$$.a = .a * .a;
$$.type = 1;
}
else if (!.type && !.type) { /* both doubles */
$$.b = .b * .b;
$$.type = 0;
}
else if (.type && !.type) { /* first integer second double */
$$.b = .a * .b;
$$.type = 0;
}
else { /* first double second integer */
$$.b = .b * .a;
$$.type = 0;
}
}
|
expr '/' expr
{
if(.type && .type) { /* both integers */
$$.a = .a / .a;
$$.type = 1;
}
else if (!.type && !.type) { /* both doubles */
$$.b = .b / .b;
$$.type = 0;
}
else if (.type && !.type) { /* first integer second double */
$$.b = .a / .b;
$$.type = 0;
}
else { /* first double second integer */
$$.b = .b / .a;
$$.type = 0;
}
}
|
expr '%' expr
{
if(.type && .type) { /* both integers */
$$.a = .a % .a;
$$.type = 1;
}
else { /* at least one double */
yyerror("% is applied to integers only");
}
}
|
expr '+' expr
{
if(.type && .type) { /* both integers */
$$.a = .a + .a;
$$.type = 1;
}
else if (!.type && !.type) { /* both doubles */
$$.b = .b + .b;
$$.type = 0;
}
else if (.type && !.type) { /* first integer second double */
$$.b = .a + .b;
$$.type = 0;
}
else { /* first double second integer */
$$.b = .b + .a;
$$.type = 0;
}
}
|
expr '-' expr
{
if(.type && .type) { /* both integers */
$$.a = .a - .a;
$$.type = 1;
}
else if (!.type && !.type) { /* both doubles */
$$.b = .b - .b;
$$.type = 0;
}
else if (.type && !.type) { /* first integer second double */
$$.b = .a - .b;
$$.type = 0;
}
else { /* first double second integer */
$$.b = .b - .a;
$$.type = 0;
}
}
|
expr '&' expr
{
if(.type && .type) { /* both integers */
$$.a = .a & .a;
$$.type = 1;
}
else { /* at least one double */
yyerror("& is applied to integers only");
}
}
|
expr '|' expr
{
if(.type && .type) { /* both integers */
$$.a = .a | .a;
$$.type = 1;
}
else { /* at least one double */
yyerror("| is applied to integers only");
}
}
|
'-' expr %prec UMINUS
{
if(.type) {
$$.a = -.a;
$$.type = 1;
}
else {
$$.b = -.b;
$$.type = 0;
}
}
|
LETTER
{
if(type[.a]) {
$$.a = iregs[.a];
$$.type = 1;
}
else {
$$.b = dregs[.a];
$$.type = 0;
}
}
|
integer
{
$$.a = .a;
$$.type = 1;
}
;
integer: DIGIT
{
$$.a = .a;
}
|
integer DIGIT
{
$$.a = base * .a + .a;
}
;
%%
int main()
{
return(yyparse());
}
void yyerror(s)
char *s;
{
fprintf(stderr, "%s\n",s);
}
int yywrap()
{
return(1);
}
因为我在我的测试文件中使用整数,所以无论我使用什么表达式,这段代码只打印 1,我不知道为什么。
每个标记和语法规则只能使用联合中的一个值,而不是整个联合作为一个结构。