0

这是使用 Flex 的词法分析器。

#include <iostream> 
#include <cstdio>

#define YY_DECL extern "C" int yylex()

#include "conv.tab.h"
using namespace std;

%}
eq [ \t]*=
%%

[ \t]           ;
(?:POINT|LINE)  { yylval.ename = strdup(yytext); return ENAME; }
x{eq}           { yylval.xval = atof(yytext);
                    return XVAL; }
y{eq}           { yylval.yval = atof(yytext);
                    return YVAL; }
.               ;
%%

其他文件是 Bison 语法文件

%{
#include <iostream>
#include <cstdio>
#include <stdio.h>
using namespace std;

extern "C" int yylex ();
extern "C" int yyparse (void);
extern "C" FILE *yyin;
extern int line_no;

void yyerror(const char *s);

%}

%union{
    float xval;
    float yval;
    char *ename;
}

%token <ename> ENAME
%token XVAL
%token YVAL

%%

converter:
    converter ENAME { cout << "entity = " << $2 << endl; }
    | converter XVAL {// x -> xval = $2; 
      cout << "x value = " << endl; }
    | converter YVAL {// y -> yval = $2; 
       cout << "y value = " << endl; }
    | ENAME { cout << "entity = " << $1 << endl; }
    | XVAL { cout << "xvalue " << endl; }
    | YVAL { cout << "yvalue " << endl; }

%%
main() {
    FILE *myfile = fopen("conv.aj", "r");

    if (!myfile) {
            cout << "I can't open file" << endl;
            return -1;
    }

    yyin = myfile;

    do{
            yydebug = 1;
            yyparse();
    } while (!feof(yyin));
    yydebug = 2;
}

void yyerror(const char *s) {
    cout << "Parser error! Message: " << s << endl;
    exit(-1);
}

实际上,我想从文件中检索值。我使用了 Bison Debugger 并了解到这些值无法推送到 Bison Stack。所以基本上我想将这些值推送到堆栈上。我的文件就像:POINT x=38 y=47

4

1 回答 1

1

您的词法分析器中没有任何内容与数字匹配,因此输入中的38and47都将由您的默认规则 ( . ;) 处理,这将导致它们被忽略。XVAL在and的规则中YVAL,您调用atoiyytext这将是x=(或y=);这显然不是一个数字,并且atoi可能会返回0

我不清楚您所说的“这些值无法推送到 Bison Stack”是什么意思,但我认为这个问题与 bison 或其堆栈无关。

顺便一提:

  1. xval和的语义类型中不需要有两个不同的成员yval。类型是 a union,而不是 a struct,因此有两个相同类型的成员 ( float) 是多余的。

  2. flex不进行正则表达式捕获。(?:...)因此,避免使用;捕获确实没有意义。它只会掩盖你的语法。您不妨使用:

    POINT|LINE: { yylval.ename = strdup(yytext); 返回 ENAME;}

    另一方面,您最好定义两种不同的令牌类型,这样可以避免strdup. (您似乎没有free重复字符串,因此这strdup也是内存泄漏。)或者,您可以在语义类型中使用枚举值:

    POINT  { yylval.ename_enum=POINT; return ENAME; }
    LINE   { yylval.ename_enum=LINE;  return ENAME; }
    
  3. . ;这不是一个好主意,尤其是在开发过程中,因为它隐藏了错误(例如您拥有的错误)。你可以使用%option nodefaultto Avoidflex的默认规则,然后 flex 会在检测到非法字符时报错。

  4. 除非您使用真正旧版本的bisonand flex,否则您可以将生成的代码编译为c++. 应该不需要使用extern "C"

于 2014-09-05T15:30:44.923 回答