Как мне написать грамматику для операторов пост-инкремента / декремента в YACC?

%type <string> Id
%type <ExprRes> Factor
%type <ExprRes> Term
%type <ExprRes> Expr
%type <InstrSeq> StmtSeq
%type <InstrSeq> Stmt
%type <BExprRes> BExpr
%type <ExprRes> Primary

%token Ident        
%token IntLit   
%token Int
%token Write
%token IF
%token EQ
%token GTE
%token LTE
%token UM
%token UP   

%%

Prog            :   Declarations StmtSeq                                {Finish($2); } ;
Declarations    :   Dec Declarations                                    { };
Declarations    :                                                       { };
Dec             :   Int Ident {EnterName(table, yytext, &entry); }';'   { };
StmtSeq         :   Stmt StmtSeq                                        { $$ = AppendSeq($1, $2); } ;
StmtSeq         :                                                       { $$ = NULL;} ;
Stmt            :   Write Expr ';'                                      { $$ = doPrint($2); };
Stmt            :   Id '=' Expr ';'                                     { $$ = doAssign($1, $3);} ;
Stmt            :   IF '(' BExpr ')' '{' StmtSeq '}'                    { $$ = doIf($3, $6);};
BExpr           :   Expr EQ Expr                                        { $$ = doBExpr($1, $3);};
Expr            :   Expr '+' Term                                       { $$ = doAdd($1, $3); } ;
Expr            :   Expr '-' Term                                       { $$ = doMinus($1, $3); };
Expr            :   Term                                                { $$ = $1; } ;
Term            :   Term '*' Factor                                     { $$ = doMult($1, $3); } ;
Term            :   Term '/' Factor                                     { $$ = doDiv($1, $3); } ;
Term            :   Factor                                              { $$ = $1; } ;
Factor          :   Primary                                             { $$ = $1;};
Primary         :   '-'Primary                                              { $$ = doUnaryMinus($1);};

Primary         :   IntLit                                              { $$ = doIntLit(yytext); };
Primary         :   Ident                                               { $$ = doRval(yytext); };
Id              :   Ident                                               { $$ = strdup(yytext);}

это моя грамматика yacc. я пытаюсь заставить унарный минус работать. х-- например.

Однако, когда я пытаюсь запустить его на моем тестовом файле

int num1;    
int num2;  
int num3;   
int num4;

num3 = 100;    
num4 = 200;   
num3 = num4 / num3;  
num1 = 1;   
num1 = num3-num1;  
num1--;

print num3;   
print num4;   
print num1;

Я получаю ошибку в строке num1--;

yyerror невероятно расплывчат в любых деталях, которые я могу найти об этом. Я могу только найти, что это вызвано, когда это сталкивается с ошибкой в ​​вводе. Я не знаю, происходит ли эта ошибка из-за моего неправильного понимания того, как я должен писать свою грамматику, или как. У меня есть программа, которая указывает на недопустимый символ и говорит, что проблема исходит от первого символа "-" в строке. Я хотел бы получить какие-либо идеи о том, где искать мой ответ или если вы видите ошибку.

это мой файл lex:

%{
#include "yaccExample.h"
#include "y.tab.h"

#define YY_INPUT(buf,result,max_size) \
    { int c = GetSourceChar(); \
          result = (c == EOF) ? YY_NULL : (buf[0] = c, 1); \
        }

%}


letter [A-Za-z]
digit [0-9]

%%
if                              {return IF;}
int                             {return Int;}
print                           {return Write;}
{letter}({letter}|{digit})*     {return Ident;}
{digit}{digit}*                 {return IntLit;}
\=\=                            {return EQ;}
\-\-                            {return UM;}
\+\+                            {return UP;}
\>\=                            {return GTE;}
\<\=                            {return LTE;}
\=                              {return '=';}
\+                              {return '+';}
\*                              {return '*';}
\;                              {return ';';}
\{                              {return '{';}
\}                              {return '}';}
\(                              {return '(';}
\)                              {return ')';}

[ ]                             {}
\t                              {}
\r                              {}
\n                              {}

.               {WriteIndicator(GetCurrentColumn());
                   WriteMessage("Illegal Character in lex");}

%%


yywrap () {
}

2 ответа

Решение

Проблема заключается в неправильном понимании терминологии. Унарный минус означает только знак минуса, предшествующий первичному, согласно вашей грамматике.

Primary         :   '-'Primary 

Правильный код теста для вашей грамматики выглядит следующим образом. Должен правильно скомпилироваться.

num1 = -99;  
num1 = -num3;
num1 = -(num3-num1);  

Оператор '-' называется декрементом и не появляется в вашей грамматике. Если вам нужно скомпилировать оператор декремента, вам нужно будет добавить его к вашей грамматике.

yacc имеет ограниченную поддержку для отладки вашей грамматики. Одна вещь, которая часто помогает в таких случаях, это определение YYDEBUG Символ препроцессора и настройка yydebug глобальный ненулевой. Это приведет к выводу на стандартный вывод всех отсканированных и сдвинутых токенов и уменьшению правил во время анализа, что может помочь.

Добавлять:

#ifdef YYDEBUG
    extern int yydebug;
    yydebug = 1;
#endif

к вашей основной функции (или, возможно, используйте переключатель командной строки, чтобы установить yydebug), и скомпилируйте все ваши исходные файлы с -DYYDEBUG

Другие вопросы по тегам