What's wrong with my grammar
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
%toke开发者_JS百科n <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 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
#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;
}
Then it accepts your example program just fine with no errors, and prints out the symbol table with just the main symbol
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.
精彩评论