首页 文章

无法通过yacc和lex解析数字

提问于
浏览
0

我已经完成了我的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 number,我输入一个整数或一个float.int开始后我在.l和.y文件中打印它们我输入fisrt随机数,例如123,然后我的程序打印:

1:NUM:123

在yylex()和

“int yacc \ n”

在parser.y中
但如果我输入第二个其他数字,它显示语法错误和程序关闭我不知道问题出在哪里 . 有什么解决方案吗?

1 回答

  • 1

    您的语法只接受一个令牌, INTFLOAT . 所以它只接受一个数字,这就是它在读取第二个数字时产生语法错误的原因;它期待一个文件结束 .

    解决方案是更改语法,以便它接受任意数量的“语句”:

    program: /* EMPTY */
           | program statement
           ;
    

    两个说明:

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

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

    它's better to return the unknown character to the parser, which will produce a syntax error if the character doesn' t对应于任何令牌类型(如在您的简单语法中),而不是仅仅将字符回显到 stdout ,这将令人困惑 . 有些人更喜欢在词法分析器中为无效输入生成错误消息,但是在开发语法时我认为通过字符更容易,因为这样可以在不重新生成词法分析器的情况下向解析器添加运算符 .

    2)在 bison 中指定 %type 时,使用联合中的标记名,而不是C类型 . 一些(但不是全部)的野牛版本让你可以使用C类型,如果它是一个简单的类型,但你可以't count on it; it'不是posix标准,如果你使用较旧或较新版本的野牛它可能会破坏 . (例如,它不适用于bison 3.0 . )所以你应该写,例如:

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

相关问题