Syntax 什么';我的语法有问题

Syntax 什么';我的语法有问题,syntax,grammar,yacc,Syntax,Grammar,Yacc,我尝试将以下内容输入到我的yacc解析器中: int main(void) { return; } 根据yacc文件中定义的内容,它对我来说是有效的,但在返回后我会收到一条“syntax error”消息。为什么呢 yacc文件: /* C-Minus BNF Grammar */ %{ #include "parser.h" #include <string.h> %} %union { int intval; struct symtab *symp; } %

我尝试将以下内容输入到我的yacc解析器中:

int main(void)
{
return;
}
根据yacc文件中定义的内容,它对我来说是有效的,但在返回后我会收到一条“syntax error”消息。为什么呢

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


}
/*C-减BNF语法*/
%{
#包括“parser.h”
#包括
%}
%联合
{
int intval;
结构符号表*符号;
}
%其他代币
%代币如果
%标记整数
%代币返还
%代币无效
%代币
%令牌ID
%令牌数
%令牌LTE
%令牌GTE
%象征平等
%代币
类型参数列表
%%
程序:申报单;
申报单:申报单申报单申报单;
声明:var_声明
|《欢乐宣言》
|'$'{printTable();};
var_声明:类型_说明符ID';'{$2->value=0;$2->arraysize=0;};
|类型_说明符ID“['NUM']”;'{$2->arraysize=$4;printf(“数组大小为%d”,$2->arraysize);};
类型|说明符:INT | VOID;
fun_声明:类型_说明符ID'('params')'复合_stmt{printf(“函数声明”);$2->args='a';printf(“参数:\n',$2->args);};
参数:参数列表|无效;
参数列表:参数列表“,”参数
|param;
param:type_说明符ID | type_说明符ID'[''];
复合语句:“{”局部声明语句{u列表“}{printf(“exiting scope\n”);};
局部声明:局部声明变量声明
|/*空*/;
语句列表:语句列表语句
|/*空*/;
语句:表达式
|复合材料
|选择
|迭代法
|返回测试;
表达式:表达式“;”
| ';' ;
选择stmt:IF'('expression')语句
|IF'('表达式')'语句ELSE语句;
迭代:WHILE'('expression')'语句;
return_stmt:return';'|返回表达式“;”;
表达式:var'='表达式|简单|表达式;
变量:ID | ID'['表达式']';
简单表达式:加法表达式重新加载加法表达式
|加性_表达;
重播:LTE |‘| GTE | EQUAL | NOTEQUAL;
加法表达式:加法表达式addop term | term;
addop:“+”|“-”;
术语:术语mulop因子|因子;
mulop:“*”|“/”;
因子:“(“表达式”)”| var | call | NUM;
调用:ID'('args');
args:arg_list |/*空*/;
arg_列表:arg_列表','表达式|表达式;
%%
/*查找符号表条目,如果不存在,则添加*/
结构symtab*symlook(字符*s){
printf(“将%s放入符号表\n”,s);
//char*p;
结构符号表*sp;
对于(sp=symtab;sp<&symtab[NSYMS];sp++){
/*已经到了吗*/
如果(sp->name&&!strcmp(sp->name,s))
{
yyerror(“已在符号表中\n”);
出口(1);
返回sp;
}
如果(!sp->name){/*它是免费的吗*/
sp->name=strdup;
返回sp;
}
/*否则继续下一步*/
}
yyerror(“符号太多”);
退出(1);/*无法继续*/
}/*符号外观*/
yyerror(字符*s)
{
printf(“YY错误:%s\n”,s);
}
printTable()
{
printf(“打印出符号表:\n\n”);
结构符号表*sp;
对于(sp=symtab;sp<&symtab[NSYMS];sp++)
{
printf(“名称:%s\t”
“参数:%s\t”
“值%d\t”
“阵列化%d\n”,
sp->name,
sp->args,
sp->value,
sp->arraysize);
}
}

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

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

我看不出您的yacc语法文件有任何错误;我最好的猜测是您的扫描仪没有正确返回返回令牌。如果我编译你的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;
}
%{
#包括“parser.tab.h”
外部结构symtab*symlook(char*);
extern void printTable();
%}
%选项No yywrap
数字[0-9][0-9]*
ID[_a-zA-Z][_a-zA-Z0-9]*
%%
否则返回其他;
如果返回如果;
int返回int;
返回;
无效返回无效;
当返回时;
“=”返回相等;
“!=”返回NOTEQUAL;
“>=”返回LTE;

“我看不出你的yacc语法文件有什么问题;我最好的猜测是你的扫描程序没有正确返回返回令牌。如果我编译你的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;
}
%{
#包括“parser.tab.h”
外部结构symtab*symlook(char*);
extern void printTable();
%}
%选项No yywrap
数字[0-9][0-9]*
ID[_a-zA-Z][_a-zA-Z0-9]*
%%
否则返回其他;
如果返回如果;
int返回int;
返回;
无效返回无效;
当返回时;
“=”返回相等;
"!=“返回NOTEQUAL;
“>=”返回LTE;

“您是否也有相应的[F]Lex文件?这会导致字符串“return”返回令牌return吗?我已经有一段时间没有接触YACC了,但我认为这是必需的。除非有任何shift-reduce冲突,这是我能看到的唯一可能的问题。是的,flex文件在遇到字符串“RETURN”时返回令牌返回。您是否也有相应的[F]Lex文件?这会导致字符串“return”返回令牌return吗?我已经有一段时间没有接触YACC了,但我认为这是必需的。除非存在任何shift-reduce冲突,否则这是我所能看到的唯一可能的问题。是的,flex文件在遇到字符串“RETURN”时返回令牌返回。shift/reduce冲突是由于悬空else问题造成的,所以它是无害的——默认的shift是正确的答案shift/reduce冲突是由悬而未决的else问题引起的,所以它是无害的