我尝试将以下内容输入到我的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);
}
}
答案 0 :(得分:1)
我看不到你的yacc语法文件有什么问题;我最好的猜测是你的扫描仪没有正确返回RETURN令牌。如果我与
一起编译您的yacc源代码<强> parser.h 强>
#define NSYMS 100
struct symtab {
char *name;
int value;
int arraysize;
char *args;
} symtab[NSYMS];
<强> scanner.l 强>
%{
#include "parser.tab.h"
extern struct symtab *symlook(char *);
extern void printTable();
%}
%option noyywrap
NUM [0-9][0-9]*
ID [_a-zA-Z][_a-zA-Z0-9]*
%%
else return ELSE;
if return IF;
int return INT;
return return RETURN;
void return VOID;
while return WHILE;
"==" return EQUAL;
"!=" return NOTEQUAL;
">=" return LTE;
"<=" return GTE;
[ \t\n] ;
{NUM} { yylval.intval = atoi(yytext); return NUM; }
{ID} { yylval.symp = symlook(yytext); return ID; }
. return *yytext;
%%
int main()
{
yyparse();
printTable();
return 0;
}
然后它接受你的示例程序就好了,没有错误,只用主符号打印出符号表
答案 1 :(得分:0)
我的yacc发出关于减少冲突的警告。我怀疑问题是它很快就无法区分函数和变量定义。