当我在Yacc文件中制定规则时,如何表示epsilon?

问题描述 投票:0回答:1

我试图在lex / yacc中实现一个简单的C减去解析器。我用一组非常简单的规则测试了我的代码并且它有效。但是现在,当我尝试添加实际规则时,我会在每个有ε规则的地方收到此错误。 error: syntax error, unexpected identifier我已经查找了如何在yacc中表示epsilon以及我看到的每个地方都说我可以将规则留空。我甚至试过在规则中发表评论,因为我也看到了这一点。但是,我想这个问题可能存在于其他地方。为什么这对我不起作用?下面是我的.y文件,第一个错误说明了这个(意外的标识符):

   arglist {};
        ^^^^^^^
void yyerror (char *s);
#include <stdio.h>
#include <stdlib.h>
int yylex();
extern int yytext[];
extern FILE *yyin;
%}
%start program
%token LTE GTE BEQUALS NOTEQUALS BEGCOMMENT ENDCOMMENT COMMENT GREATER LESS COMMA PLUS SUB MULT DIV EQUAL LP RP LB RB LC RC SEMICOLON INT FLOAT VOID IF WHILE RETURN ELSE ID NUM INVALID
%%
program : declarationlist { printf("\nACCEPT\n"); };

declarationlist : declaration declarationlistPrime {};

declaration : typespecifier ID DDD {};

DDD : vardeclarationPrime {};
    | LP params RP compoundstmt {};
vardeclaration : typespecifier ID vardeclarationPrime {};
typespecifier : INT {};
    | VOID {};
    | FLOAT {};
params : paramlist {};
    | VOID {};
paramlist : param paramlistPrime {};
param : INT ID paramPrime  {};
    | VOID ID paramPrime {};
    | FLOAT ID paramPrime {};
compoundstmt : LC localdeclarations statementlist RC {};
localdeclarations : localdeclarationsPrime {};
statementlist : statementlistPrime {};
statement : expressionstmt {};
    | LC localdeclarations statementlist RC {}; 
    | selectionstmt {};
    | iterationstmt {};
    | returnstmt {};
expressionstmt : expression SEMICOLON {};
    | SEMICOLON {};
selectionstmt : IF LP expression RP statement selectionstmtPrime {};

iterationstmt : WHILE LP expression RP statement {};

returnstmt : RETURN returnstmtPrime {};

expression : ID FFF {};
    | LP expression RP termPrime SSS {};
    | NUM termPrime SSS {};

FFF : LP args RP termPrime SSS {};
    | varPrime XXX {};

XXX : EQUAL expression arglistPrime {};
    | termPrime additiveexpressionPrime SSS {};

var : ID varPrime {};

SSS : additiveexpressionPrime arglistPrime {};
    | relop additiveexpression arglistPrime {};

relop : LTE {};
    | LESS {};
    | GREATER {};
    | GTE {};
    | BEQUALS {};
    | NOTEQUALS {};

additiveexpression : term additiveexpressionPrime {};

addop : ADD {};
    | SUB {};

term : factor termPrime {};

mulop : MULT {};
    | DIV {};

factor : LP expression RP {};
    | ID factorXYZ {};
    | NUM {};

factorXYZ : varPrime {};
    | LP args RP {};

args : /* epsilon */ | {};
    arglist {};

arglist : ID CS {};
    | LP expression RP termPrime FID {};
    | NUM termPrime FID {};

CS : varPrime EEE {};
    | LP args RP termPrime FID {};

EEE : EQUAL expression arglistPrime {};
    | termPrime FID {};

FID : relop additiveexpression arglistPrime {};
    | additiveexpressionPrime arglistPrime {};

vardeclarationPrime : SEMICOLON {};
    | LB NUM RB SEMICOLON {};

paramPrime : /* epsilon */ | {};
    LB RB {};

selectionstmtPrime : | 
    ELSE statement {};

returnstmtPrime : SEMICOLON {};
    | ID CCC {};
    | NUM termPrime BBB {};
    | LP expression RP termPrime BBB {};

AAA : EQUAL expression SEMICOLON {};
    | termPrime BBB {};

BBB : relop additiveexpression SEMICOLON {};
    | additiveexpressionPrime SEMICOLON {};

CCC : varPrime AAA {};
    | LP args RP termPrime BBB {};

varPrime :  | {};
    LB expression RB {};

declarationlistPrime : | {};
    declaration declarationlistPrime {};

paramlistPrime : | {};
    COMMA param paramlistPrime {};

localdeclarationsPrime : | {};
    vardeclaration localdeclarationsPrime {};

statementlistPrime : | {};
    statement statementlistPrime {};

additiveexpressionPrime : | {};
    addop term additiveexpressionPrime {};

termPrime : | {};
    mulop factor termPrime {};

arglistPrime : | {};
    COMMA expression arglistPrime {};


%%
int main(int argc, char *argv[])
{
   yyin = fopen(argv[1], "r");
   if (!yyin)
   {
      printf("no file\n");
      exit(0);
   }
   yyparse();
}
void yyerror(char *s)
{
   printf("\nREJECT\n");
//   printf("error from yyerror\n");
   exit(0);
}
int yywrap()
{
  // printf("in yywarp\n");
   exit(0);
}```

Please help, I have tried everything I can think of.
yacc lex
1个回答
1
投票

你有

args : /* epsilon */ | {};

这是args的两个作品,两个都是空的,一个有明确的无操作动作。这是以分号结束的,意味着args规则的终结。因此,野牛不期待另一个右手边。它期待一些不同的非终端规则。

我想,你的意思是

args : /* epsilon */
     | arglist
     ;

请注意,无需显式添加空操作完全退出操作(如上所述)完全相同,并且可以说噪音较小。

使用bison更好的风格是使用%empty标记而不是注释,因为bison将确保%empty的规则确实是空的:

args : %empty
     | arglist
     ;
© www.soinside.com 2019 - 2024. All rights reserved.