我的语法有什么问题

发布于 2024-08-12 00:15:07 字数 3656 浏览 2 评论 0原文

我尝试将以下内容输入到我的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风流物 2024-08-19 00:15:07

我看不出你的 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;
}

一起编译,那么它会很好地接受您的示例程序,没有错误,并仅打印出符号表 <强>主要符号

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

时光无声 2024-08-19 00:15:07

我的 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文