【问题标题】:failed to parse number by yacc and lexyacc 和 lex 解析数字失败
【发布时间】:2014-05-17 10:20:57
【问题描述】:

我已经完成了我的 lex 文件并开始学习 yacc 但我对我的部分 lex 代码有一些疑问:

%{
#include "y.tab.h"
int num_lines = 1;
int comment_mode=0;
int stack =0;
%}
digit ([0-9])
integer ({digit}+)
float_num ({digit}+\.{digit}+)
%%
{integer} {  //deal with integer 
                printf("#%d: NUM:",num_lines); ECHO;printf("\n");
                yylval.Integer = atoi(yytext);
                return INT;
               }
{float_num} {// deal with float
                 printf("#%d: NUM:",num_lines);ECHO;printf("\n");
                 yylval.Float = atof(yytext);
                 return FLOAT;
                 }
\n         { ++num_lines; }
.          if(strcmp(yytext," "))ECHO;
%%
int yywrap() {
return 1;
}

每次我得到一个整数或浮点数时,我都会返回令牌并将其保存到 yylval 这是我在 parser.y 中的代码:

%{
#include <stdio.h>
#define YYDEBUG 1  
void yyerror (char const *s) {
fprintf (stderr, "%s\n", s);
}
%}
%union{
int Integer;
float Float;
}
%token <int>INT;
%token <float>FLOAT;
%%
statement :
         INT  {printf("int yacc\n");}
      | FLOAT {printf("float yacc\n");}
      |
      ;
%%
int main(int argc, char** argv)
{
yyparse();
return 0;
}

由
编译 byacc –d parser.y

lex lex.l

gcc lex.yy.c y.tab.c –ll

因为我只是想尝试一些容易上手的东西,所以我想看看我是否可以解析 首先只有 int 和 float 数字,我在输入后将它们打印在 .l 和 .y 文件中 integer 或 float.int 开头 i 输入的第一个随机数,例如 123 ,然后我的程序打印:

1:数字:123

在 yylex() 和

"int yacc\n"

在 parser.y 中
但是如果我输入第二个 else 数字,它会显示语法错误并且程序关闭 我不知道问题出在哪里。 有什么解决办法吗?

【问题讨论】:

    标签: yacc lex


    【解决方案1】:

    您的语法只接受单个标记,INT 或 FLOAT。所以它只会接受一个数字,这就是它在读取第二个数字时会产生语法错误的原因;它正在等待文件结束。

    解决办法是改变语法,让它接受任意数量的“语句”:

    program: /* EMPTY */
           | program statement
           ;
    

    两个音符:

    1) 您的词法分析器中不需要(昂贵的)strcmp。只需这样做:

    " "    /* Do nothing */;
    .      { return yytext[0]; }
    

    最好将未知字符返回到解析器,如果该字符不对应于任何标记类型(如在您的简单语法中),则会产生语法错误,而不是将字符回显到stdout,这将证明令人困惑。有些人更愿意在词法分析器中为无效输入生成错误消息,但是当您开发语法时,我认为只传递字符更容易,因为这可以让您在不重新生成词法分析器的情况下将运算符添加到解析器。

    2) 当您在bison 中指定%types 时,您使用联合中的标记名,而不是C 类型。一些(但不是全部)版本的 bison 可以让你摆脱使用 C 类型,如果它是一个简单类型,但你不能指望它;它不是 posix 标准,如果您使用较旧或较新版本的野牛,它可能会损坏。 (例如,它不适用于 bison 3.0。)所以你应该写,例如:

    %union{
      int Integer;
      float Float;
    }
    %token <Integer>INT;
    %token <Float>FLOAT;
    

    【讨论】:

    • 感谢回复,请问为什么程序后面的第一行需要为空?我试试如果没有空会导致一些错误
    • @user3552111:有两条规则:program: ; 和 program: program statement ;。第一个说program 可能是空字符串,第二个说program 可能是program,后跟statement。通常使用注释/* EMPTY */ 使空规则更加可见。如果您不允许 program 为空,您将永远无法在第二条规则中结束递归,这可能是错误消息所说的。
    猜你喜欢
    • 1970-01-01
    • 2016-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-09
    相关资源
    最近更新 更多