2009-11-17 40 views
1

我试着输入以下到我的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

你是否也有相应的[F] Lex文件?这会导致字符串“return”返回标记RETURN?自从我接触YACC已经有一段时间了,但认为这是必需的。除了任何转变 - 减少冲突,这是我能看到的唯一可能的问题。 – Morinar 2009-11-17 23:08:08

+0

是的,flex文件在遇到字符串“return”时返回标记RETURN。 – neuromancer 2009-11-18 10:18:34

回答

0

我YACC发出关于移减少冲突的警告。我怀疑问题在于它无法很快区分函数和变量定义。

+0

转换/减少冲突是由于悬而未决的问题,所以它无害 - 默认的转变是正确的答案 – 2010-02-21 06:35:41

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; 
} 

然后,它会将您的示例程序只是没有错误的罚款,并打印出符号表只用符号