我的语法有什么问题
我尝试将以下内容输入到我的 yacc 解析器中:
int main(void)
{
return;
}
根据 yacc 文件中的定义,它对我来说看起来有效,但在返回后我收到“语法错误”消息。这是为什么?
yacc 文件:
/* C-Minus BNF Grammar */
%{
#include "parser.h"
#include <string.h>
%}
%union
{
int intval;
struct symtab *symp;
}
%token ELSE
%token IF
%token INT
%token RETURN
%token VOID
%token WHILE
%token <symp> ID
%token <intval> NUM
%token LTE
%token GTE
%token EQUAL
%token NOTEQUAL
type <string> paramlist
%%
program : declaration_list ;
declaration_list : declaration_list declaration | declaration ;
declaration : var_declaration
| fun_declaration
| '$' { printTable();};
var_declaration : type_specifier ID ';' {$2->value = 0; $2->arraysize = 0;};
| type_specifier ID '[' NUM ']' ';' {$2->arraysize = $4;printf("Array size is %d", $2->arraysize);} ;
type_specifier : INT | VOID ;
fun_declaration : type_specifier ID '(' params ')' compound_stmt {printf("function declaration\n"); $2->args = 'a'; printf("Parameters: \n", $2->args); } ;
params : param_list | VOID ;
param_list : param_list ',' param
| param ;
param : type_specifier ID | type_specifier ID '[' ']' ;
compound_stmt : '{' local_declarations statement_list '}' {printf("exiting scope\n"); } ;
local_declarations : local_declarations var_declaration
| /* empty */ ;
statement_list : statement_list statement
| /* empty */ ;
statement : expression_stmt
| compound_stmt
| selection_stmt
| iteration_stmt
| return_stmt ;
expression_stmt : expression ';'
| ';' ;
selection_stmt : IF '(' expression ')' statement
| IF '(' expression ')' statement ELSE statement ;
iteration_stmt : WHILE '(' expression ')' statement ;
return_stmt : RETURN ';' | RETURN expression ';' ;
expression : var '=' expression | simple_expression ;
var : ID | ID '[' expression ']' ;
simple_expression : additive_expression relop additive_expression
| additive_expression ;
relop : LTE | '<' | '>' | GTE | EQUAL | NOTEQUAL ;
additive_expression : additive_expression addop term | term ;
addop : '+' | '-' ;
term : term mulop factor | factor ;
mulop : '*' | '/' ;
factor : '(' expression ')' | var | call | NUM ;
call : ID '(' args ')' ;
args : arg_list | /* empty */ ;
arg_list : arg_list ',' expression | expression ;
%%
/* look up a symbol table entry, add if not present */
struct symtab *symlook(char *s) {
printf("Putting %s into the symbol table\n", s);
//char *p;
struct symtab *sp;
for(sp = symtab; sp < &symtab[NSYMS]; sp++) {
/* is it already here? */
if(sp->name && !strcmp(sp->name, s))
{
yyerror("already in symbol table\n");
exit(1);
return sp;
}
if(!sp->name) { /* is it free */
sp->name = strdup(s);
return sp;
}
/* otherwise continue to next */
}
yyerror("Too many symbols");
exit(1); /* cannot continue */
} /* symlook */
yyerror(char *s)
{
printf( "yyerror: %s\n", s);
}
printTable()
{
printf("Print out the symbol table:\n\n");
struct symtab *sp;
for(sp = symtab; sp < &symtab[NSYMS]; sp++)
{
printf("name: %s\t"
"args: %s\t"
"value %d\t"
"arraysize %d\n",
sp->name,
sp->args,
sp->value,
sp->arraysize);
}
}
I try to input the following into my yacc parser:
int main(void)
{
return;
}
It looks valid to me according to what's defined in the yacc file, but I get a "syntax error" message after the return. Why is that?
The yacc file:
/* C-Minus BNF Grammar */
%{
#include "parser.h"
#include <string.h>
%}
%union
{
int intval;
struct symtab *symp;
}
%token ELSE
%token IF
%token INT
%token RETURN
%token VOID
%token WHILE
%token <symp> ID
%token <intval> NUM
%token LTE
%token GTE
%token EQUAL
%token NOTEQUAL
type <string> paramlist
%%
program : declaration_list ;
declaration_list : declaration_list declaration | declaration ;
declaration : var_declaration
| fun_declaration
| '
{ printTable();};
var_declaration : type_specifier ID ';' {$2->value = 0; $2->arraysize = 0;};
| type_specifier ID '[' NUM ']' ';' {$2->arraysize = $4;printf("Array size is %d", $2->arraysize);} ;
type_specifier : INT | VOID ;
fun_declaration : type_specifier ID '(' params ')' compound_stmt {printf("function declaration\n"); $2->args = 'a'; printf("Parameters: \n", $2->args); } ;
params : param_list | VOID ;
param_list : param_list ',' param
| param ;
param : type_specifier ID | type_specifier ID '[' ']' ;
compound_stmt : '{' local_declarations statement_list '}' {printf("exiting scope\n"); } ;
local_declarations : local_declarations var_declaration
| /* empty */ ;
statement_list : statement_list statement
| /* empty */ ;
statement : expression_stmt
| compound_stmt
| selection_stmt
| iteration_stmt
| return_stmt ;
expression_stmt : expression ';'
| ';' ;
selection_stmt : IF '(' expression ')' statement
| IF '(' expression ')' statement ELSE statement ;
iteration_stmt : WHILE '(' expression ')' statement ;
return_stmt : RETURN ';' | RETURN expression ';' ;
expression : var '=' expression | simple_expression ;
var : ID | ID '[' expression ']' ;
simple_expression : additive_expression relop additive_expression
| additive_expression ;
relop : LTE | '<' | '>' | GTE | EQUAL | NOTEQUAL ;
additive_expression : additive_expression addop term | term ;
addop : '+' | '-' ;
term : term mulop factor | factor ;
mulop : '*' | '/' ;
factor : '(' expression ')' | var | call | NUM ;
call : ID '(' args ')' ;
args : arg_list | /* empty */ ;
arg_list : arg_list ',' expression | expression ;
%%
/* look up a symbol table entry, add if not present */
struct symtab *symlook(char *s) {
printf("Putting %s into the symbol table\n", s);
//char *p;
struct symtab *sp;
for(sp = symtab; sp < &symtab[NSYMS]; sp++) {
/* is it already here? */
if(sp->name && !strcmp(sp->name, s))
{
yyerror("already in symbol table\n");
exit(1);
return sp;
}
if(!sp->name) { /* is it free */
sp->name = strdup(s);
return sp;
}
/* otherwise continue to next */
}
yyerror("Too many symbols");
exit(1); /* cannot continue */
} /* symlook */
yyerror(char *s)
{
printf( "yyerror: %s\n", s);
}
printTable()
{
printf("Print out the symbol table:\n\n");
struct symtab *sp;
for(sp = symtab; sp < &symtab[NSYMS]; sp++)
{
printf("name: %s\t"
"args: %s\t"
"value %d\t"
"arraysize %d\n",
sp->name,
sp->args,
sp->value,
sp->arraysize);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我看不出你的 yacc 语法文件有什么问题;我最好的猜测是您的扫描仪没有正确返回 RETURN 令牌。如果我将您的 yacc 源代码与
parser.h
scanner.l
一起编译,那么它会很好地接受您的示例程序,没有错误,并仅打印出符号表 <强>主要符号
I can't see anything wrong with your yacc grammar file; my best guess is that your scanner isn't returning the RETURN token properly. If I compile your yacc source along with
parser.h
scanner.l
Then it accepts your example program just fine with no errors, and prints out the symbol table with just the main symbol
我的 yacc 发出有关移位减少冲突的警告。我怀疑问题在于它无法尽快区分函数和变量定义。
My yacc issues a warning about a shift-reduce conflict. I suspect the problem is that it's unable to differentiate between function and variable definition soon enough.