我是使用野牛的新手,我试图修改使用野牛输入文件的解释器。我总是收到类型冲突警告。我认为这是因为表达式和case_statement没有值,但我不确定如何修复它。
这是警告。
parser.y:97.9-59: warning: type clash on default action: <value> != <> [-Wother]
97 | IF expression THEN statement_ ELSE statement_ ENDIF |
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
parser.y:98.9-30: warning: type clash on default action: <value> != <> [-Wother]
98 | case_statement ENDCASE ;
这就是问题所在的代码
%union
{
CharPtr iden;
Operators oper;
int value;
}
%token <iden> IDENTIFIER
%token <value> INT_LITERAL REAL_LITERAL BOOL_LITERAL
%token <oper> ADDOP MULOP RELOP REMOP EXPOP
%token ANDOP
%token BEGIN_ BOOLEAN END ENDREDUCE FUNCTION INTEGER IS REDUCE RETURNS
%token ARROW OROP NOTOP CASE ELSE ENDCASE ENDIF IF REAL
%token OTHERS THEN WHEN
%type <value> body statement_ statement reductions expression relation term factor primary
power conjunction
%type <oper> operator
%%
statement_:
statement ';' |
error ';' {$$ = 0;} ;
statement:
expression |
REDUCE operator reductions ENDREDUCE {$$ = $3;} |
IF expression THEN statement_ ELSE statement_ ENDIF |
case_statement ENDCASE ;
case:
WHEN INT_LITERAL ARROW statement_;
cases:
case cases_others;
case_statement:
CASE expression IS cases OTHERS ARROW statement_ ';' |
error ';' ;
cases_others:
case cases_others |
;
您已经声明statement
具有类型<value>
,这意味着statement
的每个替代产品必须将$$
设置为类型<value>
的东西。
语法中的大多数备选项没有关联的操作,因此Bison插入默认操作$$ = $1;
。为此,$$
(即statement
)的类型必须与该替代方案中的$1
的类型相同。这是Bison可以检查的东西,因为它知道所有语法符号的类型,所以它会检查,以便能够在默认操作明显不正确时警告您。
在statement
的情况下,您有四个产品。statement: expression
不是问题,因为expression
被声明为<value>
类型。statement: reduce
也不是问题,因为它具有$$ = $3;
的动作。(Bison不会对显式操作进行类型检查,因为它几乎必须是C编译器才能确定用C编写的操作是否类型安全。但是如果它确实检查了,这个也可以,因为$3
是reductions
,reductions
也被声明为<value>
类型。
但是,其他两个选择确实存在问题。两者都没有显式的操作,而且在这两种情况下,$1
都是一个没有声明类型的语法符号(关键字IF
当然不应该有值,而非终结符case-statement
可能应该有值,因为您将需要它来赋值给statement
)。$$ = $1;
将把statement
的语义值设置为未分配的值,这显然是不正确的。因此有了警告。
要静音警告,给这两个选项一个操作。如上所述,Bison不会检查显式操作是否正确输入。但是,要正确解决这个问题,您需要弄清楚在这两种情况下给$$
的值。
注意这只是一个警告,而不是一个错误。Bison无法判断你没有在背后赋值,也无法判断C是否在两种不同类型之间进行隐式转换。因此,在某些情况下,$$ = $1;
实际上是可以的,即使$$
和$1
具有不同(或没有)声明的类型。但是大多数情况下,默认操作中的类型不匹配表明存在错误,并且警告是合理的。