0

これは Flex を使用した Lexical Analyzer です。

#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; }
.               ;
%%

そして他のファイルはバイソン文法ファイルです

%{
#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 スタックにプッシュできないことがわかりました。したがって、基本的にはこれらの値をスタックにプッシュしたいと思います。私のファイルは次のようになります: POINT x=38 y=47

4

1 に答える 1

1

字句アナライザーには数値と一致するものがないため3847入力の と は両方ともデフォルト ルール ( . ;) によって処理され、無視されます。XVALandのルールでは、 (または)になるYVALを呼び出します。これは明らかに数値ではなく、おそらく が返されます。atoiyytextx=y=atoi0

「これらの値を Bison スタックにプッシュできない」という意味がよくわかりませんが、この問題は Bison やそのスタックとは何の関係もないと思います。

ところで:

  1. xvalとのセマンティック型に 2 つの異なるメンバーを含める必要はありませんyval。型は aunionではなく astructであるため、同じ型 ( ) の 2 つのメンバーを持つことfloatは冗長です。

  2. flex正規表現キャプチャを行いません。(?:...)したがって、 ;でキャプチャを回避しても意味がありません。それはあなたの文法を曖昧にするだけです。以下を使用することもできます。

    POINT|LINE: { yylval.ename = strdup(yytext); ENAME を返します。}

    一方で、2 つの異なるトークン タイプを定義したほうがよい場合もありますstrdupfree(重複した文字列を ing していないように見えるためstrdup、メモリ リークでもあります。) あるいは、セマンティック型で列挙値を使用することもできます。

    POINT  { yylval.ename_enum=POINT; return ENAME; }
    LINE   { yylval.ename_enum=LINE;  return ENAME; }
    
  3. . ;エラー(あなたが持っているものなど)を隠すため、特に開発中は本当に良い考えではありません。%option nodefaultのデフォルト ルールを回避するためにを使用できます。そうすれflexば、不正な文字が検出されたときに flex がエラーを表示します。

  4. 非常に古いバージョンのbisonおよびを使用していない限りflex、生成されたコードを としてコンパイルできますc++。使用する必要はないはずですextern "C"

于 2014-09-05T15:30:44.923 に答える