Как мне написать грамматику для операторов пост-инкремента / декремента в 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