将我的yacc和lex文件放在一起时,yacc无法识别我的令牌为什么?

问题描述

我正在尝试将yacc,lex和语义文件放在一起,以便能够识别以下格式的输入文件


    x = 55;
    y = 45.5;
    z = - ( x + y );

我感觉好像一切都井井有条,并且在编译时没有出现任何错误,但是yacc和lex似乎什么都没识别。

这是我的lex文件


    %{
    #include "IOMngr.h"
    #include "y.tab.h"
    
    #define YY_INPUT(buf,result,max_size) \
    { int c = getNextSourceChar(); \
    result = (c == EOF) ? YY_NULL : (buf[0] = c,1); \
    }
    
    %}
    
    letter [A-Za-z]
    digit [0-9]
    
    %%
    
    ({digit}+).({digit}+)        {return FLOAT;}
    {letter}({letter}|{digit})*  {return Ident;}
    {digit}{digit}*              {return INT;}
    "+"                          {return '+';}
    "-"                          {return '-';}
    "="                          {return '=';}
    "*"                          {return '*';}
    ")"                          {return ')';}
    "("                          {return '(';}
    
    [ ]                          {}
    \t                           {}
    \r                           {}
    \n                           {}
    
    .                            {
                                   writeIndicator(getCurrentColumnNum());
                                   writeMessage("Illegal Character in lex");
                                 }
    
    %%
    
    int yywrap() {
      return 1;
    }

这是我的yacc文件


    %{
      #include "SymTab.h"
      #include "semantics.h"
      #include "IOMngr.h"
      #include <string.h>
      #include <stdio.h>
      
      extern int yylex();
      extern char *yytext;
      extern int yyleng;
      extern int yyerror(char *);
    
      extern SymTab *table;
      extern SymEntry *entry;
      
    %}
    
    
    %union {
      struct number *value;
      int integer;
      float floatnum;
      char * string;
    }
    
    %type <string> Id
    %type <value> Expr
    %type <value> Term
    %type <value> Factor
    %type <integer> INT
    %type <floatnum> FLOAT
    
    %token Ident
    %token FLOAT
    %token INT
    
    %%
    
    Prog            :  StmtSeq                 {printSymTab();};
    StmtSeq         :  Stmt StmtSeq            {};
    StmtSeq         :                          {};
    Stmt            :  Id '=' Expr ';'         {storeVar($1,$3);};
    Expr            :  Expr '+' Term           {$$ = doADD($1,$3);};
    Expr            :  Term                    {$$ = $1;};
    Term            :  Term '*' Factor         {$$ = doMULTIPLY($1,$3);};
    Term            :  Factor                  {$$ = $1;};
    Factor          :  '-' Factor              {$$ = doNEGATE($2);};
    Factor          :  '(' Expr ')'            {$$ = $2;};
    Factor          :  Id                      {$$ = getVal($1);};
    Factor          :  INT                     {$$ = getInt($1);};
    Factor          :  FLOAT                   {$$ = getFloat($1);};
    Id              :  Ident                   {$$ = strdup(yytext);};
    
    %%
    
         int yyerror(char *s) {
           printf("YYERROR STRING: %s\n",s);
           writeIndicator(getCurrentColumnNum());
           writeMessage("Illegal Character in YACC");
           return 1;
         }
       
       

这是我的语义。h:


    #include <stdlib.h>
    #include <string.h>
    
    struct number {
      int ival;
      float fval;
      char type;
    };
    
    void printSymTab();
    void storeVar(char * name,struct number *v);
    struct number *doADD(struct number * n1,struct number * n2);
    struct number *doMULTIPLY(struct number *n1,struct number *n2);
    struct number *doNEGATE(struct number *n1);
    struct number *getVal(char * name);
    struct number *getInt(int num);
    struct number *getFloat(float num);

最后是我的IOMngr.h(如果相关):

    #include <stdlib.h>
    #include <stdio.h>
    
    #define MAXLINE 1024
    
    int openFiles(char * sourceName,char * listingName);
    
    void closeFiles();
    
    char getNextSourceChar();
    
    void writeIndicator(int column);
    
    void writeMessage(char * message);
    
    int getCurrentLineNum();
    
    int getCurrentColumnNum();

问题出在yacc或lex文件中。

任何帮助将不胜感激。

解决方法

问题可能出在令牌解码和^-50的使用上。您不会在.l文件中提取INT / FLOAT / Ident令牌的值;您可以在其他位置访问yytext(在操作yytext中,我们可以在您的getInt / getFloat函数中进行假设。)

问题在于这并不安全-yytext指向最后提取的令牌,它可能是您实际想要的令牌的 之后的一个,因为bison使用了一个令牌前瞻。通常,从yacc动作(或从yacc动作调用的函数)访问yytext永远都不安全,因为您不知道要获得哪个令牌。

相反,您需要解码.l文件中的关联令牌值并将其分配给yylval:

Id : Ident {$$ = strdup(yytext);};