【问题标题】:How do I write a Grammar for post-increment/decrement operators in YACC?如何为 YACC 中的后自增/自减运算符编写语法?
【发布时间】:2014-04-27 22:21:56
【问题描述】:
%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 语法。我试图让一元减号工作。 x——例如。

但是当我尝试在我的测试文件上运行它时

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;

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 () {
}

【问题讨论】:

  • 你为什么在你的问题中包含'c'标签?
  • 'x--' 不是一元减号。 '-x' 是一元减号。 'x--' 是一个后减量。是否从解析器调用 yyerror()?还是您自己从词法分析器中调用它? '非法字符'这个词暗示了后者,在这种情况下,只有你才能知道你为什么叫它。
  • @MahonriMoriancumer 在 y 文件中插入的代码是用 C 或 C++ 编写的。我不明白为什么他不应该将其标记为 C。
  • 您的语法看起来是正确的,但它期望标记 UM 对应于 --。你的词法分析器给你什么令牌?显示您的 .l 文件,或您用于词法分析器的任何文件。
  • 我要检查的第一件事是你的词法分析器是否真的返回 UM 而不是 '-' '-'。

标签: c yacc unary-operator


【解决方案1】:

问题在于对术语的误解。根据您的语法,一元减号表示仅在主要之前的减号。

Primary         :   '-'Primary 

您的语法的正确测试代码如下所示。它应该可以正确编译。

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

运算符“--”称为减量,不会出现在您的语法中。如果您需要编译减量运算符,则必须将其添加到您的语法中。

【讨论】:

    【解决方案2】:

    yacc 对调试语法的支持有限。在这种情况下通常有帮助的一件事是定义 YYDEBUG 预处理器符号并将 yydebug 全局设置为非零。这将导致所有扫描和移动的标记转储到标准输出,并在解析时减少规则,这会有所帮助。

    添加:

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

    到你的主函数(或者可能使用命令行开关来设置yydebug),并用-DYYDEBUG编译你的所有源文件

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-15
      • 1970-01-01
      • 2011-02-14
      • 1970-01-01
      • 2011-01-23
      相关资源
      最近更新 更多