Как мне представить epsilon, когда я создаю правила внутри своего файла Yacc? - PullRequest
0 голосов
/ 16 апреля 2019

Я пытаюсь реализовать простой синтаксический анализатор C минус в lex / yacc. Я проверил свой код с очень простым набором правил, и это сработало. Но теперь, когда я пытаюсь добавить действительные правила, я получаю эту ошибку везде, где есть правило epsilon. error: syntax error, unexpected identifier Я посмотрел, как представлять epsilon в yacc, и каждый, где я смотрю, говорит, что я могу просто оставить правило пустым. Я даже попытался добавить комментарий в правило, потому что я тоже это видел. Но я полагаю, что проблема может быть в другом Почему это не работает для меня? Ниже мой файл .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.

1 Ответ

1 голос
/ 16 апреля 2019

У вас есть

args : /* epsilon */ | {};

Это два произведения для args, оба они пустые и одно с явным действием no-op. Это заканчивается точкой с запятой, что означает конец правил для args. Таким образом, бизон не ожидает другой правой стороны. Это ожидает правила для какого-то другого нетерминала.

То, что вы имели в виду, я полагаю, было

args : /* epsilon */
     | arglist
     ;

Обратите внимание, что нет необходимости явно добавлять пустое действие. Оставить действие целиком (как указано выше) точно так же, и, возможно, менее шумно.

Лучший стиль для бизона - использовать маркер %empty вместо комментария, потому что бизон гарантирует, что правило с %empty действительно пустое:

args : %empty
     | arglist
     ;
...