为野牛中的非终端分配多种类型
Assigning multiple types to non-terminals in bison
我正在尝试为非终端号码分配多种数据类型,并在谷歌搜索时发现:在yacc中为非终端分配多种数据类型。但是,此语法似乎对我不起作用,因为在运行它时,我收到以下错误:
new11.y:53.54-55: $3 of `initialization' has no declared type
new11.y:57.81-82: $5 of `increment' has no declared type
new11.y:70.33-34: $4 of `ifelse' has no declared type
这是我的代码:
%union{
int ival;
float fval;
char *sval;
}
// define the terminal symbol token types
%token <ival> INTEGER
%token <fval> FLOAT
%token <sval> BLOCK
%token <sval> GOTO
%token PRINT IF ELSE RETURN
%token LESSTHAN LESSTHANEQUALTO GREATERTHAN GREATERTHANEQUALTO EQUALTO
%token ADD SUB MUL DIV
%token <sval> IDENTIFIER
%type <sval> comparison
%%
//grammar which bison will parse
start:
block statements { ; }
| start block statements { ; }
;
block:
BLOCK { cout<<"Block : "<<$1<<endl; }
;
number:
INTEGER { $<ival>$=$1 }
| FLOAT { $<fval>$=$1 }
;
initialization:
IDENTIFIER EQUALTO number { cout<<$1<<" = "<<$3<<endl; }
;
increment:
IDENTIFIER EQUALTO IDENTIFIER ADD number { cout <<$1<<" = "<<$3<<" + "<<$5<<endl; }
;
goto:
GOTO { cout<<"GOTO : "<<$1<<endl; }
;
printing:
PRINT { cout<<"printf(...)"<<endl; }
;
ifelse:
IF IDENTIFIER comparison number GOTO ELSE GOTO
{ cout <<"if "<<$2<<$3<<$4<<", "<<$5<<",else, "<<$7<<endl; }
;
comparison:
LESSTHAN { $$="<"; }
| LESSTHANEQUALTO { $$="<=" }
| GREATERTHAN { $$=">" }
| GREATERTHANEQUALTO { $$=">=" }
;
statement:
initialization
| printing
| goto
| increment
| ifelse
| RETURN
;
statements:
statements statement
| statement
;
%%
main() {
// open a file handle to a particular file:
FILE *myfile = fopen("test.cfg", "r");
// make sure it is valid:
if (!myfile) {
cout << "I can't open a.snazzle.file!" << endl;
return -1;
}
// set flex to read from it instead of defaulting to STDIN:
yyin = myfile;
// parse through the input until there is no more:
do {
yyparse();
} while (!feof(yyin));
}
void yyerror(const char *s) {
cout << "EEK, parse error! Message: " << s << endl;
// might as well halt now:
exit(-1);
}
我哪里出错了?我没有正确使用语法吗?
错误消息相当清晰。您的非终initialization
有number
$3
,number
需要%type
声明。 increment
的$5
和ifelse
的$4
也是number
,所以是同一个问题三次。
您可能需要创建一个可区分的联合来表示整数或浮点数,并在%union
中使用该联合:
struct Number
{
enum { INTEGER, FLOAT } type;
union
{
float fval;
int ival;
};
};
然后:
%union
{
char *sval;
Number nval;
};
此语法在 Bison 中编译 — 在C++级别可能有代码工作要做。 如果匿名联合不在C++中,请在 struct Number
中添加联合的名称。 您的分词器需要同时设置type
和ival
或fval
字段struct Number
。 你不能用C++写出简单的main()
;您必须在它前面加上 int
.
%{
struct Number
{
enum { INTEGER, FLOAT } type;
union
{
float fval;
int ival;
};
};
%}
%union
{
Number nval;
char *sval;
}
// define the terminal symbol token types
%token <nval> INTEGER
%token <nval> FLOAT
%token <sval> BLOCK
%token <sval> GOTO
%token PRINT IF ELSE RETURN
%token LESSTHAN LESSTHANEQUALTO GREATERTHAN GREATERTHANEQUALTO EQUALTO
%token ADD SUB MUL DIV
%token <sval> IDENTIFIER
%type <sval> comparison
%type <nval> number
%%
//grammar which bison will parse
start:
block statements { ; }
| start block statements { ; }
;
block:
BLOCK { cout<<"Block : "<<$1<<endl; }
;
number:
INTEGER { $$=$1 }
| FLOAT { $$=$1 }
;
initialization:
IDENTIFIER EQUALTO number { cout<<$1<<" = "<<$3<<endl; }
;
increment:
IDENTIFIER EQUALTO IDENTIFIER ADD number { cout <<$1<<" = "<<$3<<" + "<<$5<<endl; }
;
goto:
GOTO { cout<<"GOTO : "<<$1<<endl; }
;
printing:
PRINT { cout<<"printf(...)"<<endl; }
;
ifelse:
IF IDENTIFIER comparison number GOTO ELSE GOTO
{ cout <<"if "<<$2<<$3<<$4<<", "<<$5<<",else, "<<$7<<endl; }
;
comparison:
LESSTHAN { $$="<"; }
| LESSTHANEQUALTO { $$="<=" }
| GREATERTHAN { $$=">" }
| GREATERTHANEQUALTO { $$=">=" }
;
statement:
initialization
| printing
| goto
| increment
| ifelse
| RETURN
;
statements:
statements statement
| statement
;
%%
int main() {
// open a file handle to a particular file:
FILE *myfile = fopen("test.cfg", "r");
// make sure it is valid:
if (!myfile) {
cout << "I can't open a.snazzle.file!" << endl;
return -1;
}
// set flex to read from it instead of defaulting to STDIN:
yyin = myfile;
// parse through the input until there is no more:
do {
yyparse();
} while (!feof(yyin));
}
void yyerror(const char *s) {
cout << "EEK, parse error! Message: " << s << endl;
// might as well halt now:
exit(-1);
}
相关文章:
- 将数组的地址分配给变量并删除
- vector.resize()中的分配错误
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- Win32编译器选项和内存分配
- 函数中堆分配的效果与缺少堆分配的情况
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 获取字符串的长度并将其分配给数组
- 将地址分配给本地指针后,公共对象的变量将消失
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 有没有一种方法可以使用placement new将堆叠对象分配给分配的内存
- 我在二维向量中是否正确分配了内存
- 正在尝试重载二进制搜索树分配运算符
- GlobalAlloc而不是其他分配方法
- 自定义先决条件对移动分配运算符有效吗
- 我可以重新分配/覆盖std::字符串吗
- 在c++中使用动态分配的问题
- 当一个新对象被分配到它的地址时,对象是否必须被销毁
- 为什么我可以使用比分配的内存更多的内存
- 使用RAII在给定次数的迭代后重新分配资源