2

論理式を評価するためのパーサーを作成しました。flex と bison がグローバル変数 (yylval など) を使用することは知っています。スレッド プログラミング用の純粋なパーサーとリエントラント スキャナーが必要です。私の「.y」ファイルはここにあります:

%{
#include <stdio.h>
#include <string>
#define YYSTYPE bool

void yyerror(char *);

//int  yylex (YYSTYPE* lvalp);

int yylex(void);
bool parseExpression(const std::string& inp);
%}

%token INTEGER
%left '&' '|'

%%

program:
        program statement '\n'
        | /* NULL */
        ;

statement:
        expression                      { printf("%d\n", $1); return $1; }
        ;

expression:
        INTEGER
        | expression '|' expression     { $$ = $1 | $3; }
        | expression '&' expression     { $$ = $1 & $3; }
        | '(' expression ')'            { $$ = $2; }
        | '!' expression                { $$ = !$2; }
        ;

%%

void yyerror(char *s) {
    fprintf(stderr, "%s\n", s);
}


void main(void) {

    std::string inp = "0|0\n";

    bool nasi = parseExpression(inp);
    printf("%s%d\n", "nasi ", nasi);
    printf("Press ENTER to close. ");
    getchar();
}

私の「.y」ファイルはここにあります:

    /* Lexer */
%{
    #include "parser.tab.h"
    #include <stdlib.h>
    #include <string>
    #define YYSTYPE bool
    void yyerror(char *);
%}


%%

[0-1]      {
                if (strcmp(yytext, "0")==0)
                {
                    yylval = false;
                    //*lvalp = false;
                }
                else
                {
                    yylval = true; 
                    //*lvalp = true;
                }

                return INTEGER;
            }

[&|!()\n]     { return *yytext; }

[ \t]   ;       /* skip whitespace */

.               yyerror("Unknown character");

%%

int yywrap(void) {
    return 1;
}

bool parseExpression(const std::string& inp)
{
    yy_delete_buffer(YY_CURRENT_BUFFER);

    /*Copy string into new buffer and Switch buffers*/
    yy_scan_string(inp.c_str());
    bool nasi = yyparse();

    return nasi;


}

両方のファイルに追加%pure_parserし、yylex 宣言を に変更してint yylex (YYSTYPE* lvalp);に置き換えyylvalました*lvalpが、エラーが表示されました: 'lvalp' is undeclared identifier.. 「再入可能」と「純粋」については多くの例がありますが、最適なガイドラインを見つけることができません。

誰かが私を案内してもらえますか?

前もって感謝します。

4

2 に答える 2

5

幸いなことに、私はそれをしました。これが私のコードです。純粋なパーサーを書きたい人にとっては良いガイドラインになると思います。

私のリエントラントスキャナー:

    /* Lexer */
%{
    #include "parser.tab.h"
    #include <stdlib.h>
    #include <string>
    #define YYSTYPE bool
    void yyerror (yyscan_t yyscanner, char const *msg);
%}

%option reentrant bison-bridge

%%

[0-1]      {
                if (strcmp(yytext, "0")==0)
                {
                    *yylval = false;
                }
                else
                {
                    *yylval = true;
                }

                //yylval = atoi(yytext);
                return INTEGER;
            }

[&|!()\n]     { return *yytext; }

[ \t]   ;       /* skip whitespace */

.               yyerror (yyscanner, "Unknown character");

%%

int yywrap(yyscan_t yyscanner)
{
    return 1;
}

bool parseExpression(const std::string& inp)
{
    yyscan_t myscanner;
    yylex_init(&myscanner);
    struct yyguts_t * yyg = (struct yyguts_t*)myscanner;

    yy_delete_buffer(YY_CURRENT_BUFFER,myscanner);

    /*Copy string into new buffer and Switch buffers*/
    yy_scan_string(inp.c_str(), myscanner);

    bool nasi = yyparse(myscanner);
    yylex_destroy(myscanner);
    return nasi;
}

私の純粋なパーサー:

%{
    #include <stdio.h>
    #include <string>

    #define YYSTYPE bool
    typedef void* yyscan_t;
    void yyerror (yyscan_t yyscanner, char const *msg);
    int yylex(YYSTYPE *yylval_param, yyscan_t yyscanner);
    bool parseExpression(const std::string& inp);
%}


%define api.pure full
%lex-param {yyscan_t scanner}
%parse-param {yyscan_t scanner}

%token INTEGER
%left '&' '|'

%%

program:
        program statement '\n'
        | /* NULL */
        ;

statement:
        expression                      { printf("%d\n", $1); return $1; }
        ;

expression:
        INTEGER
        | expression '|' expression     { $$ = $1 | $3; }
        | expression '&' expression     { $$ = $1 & $3; }
        | '(' expression ')'            { $$ = $2; }
        | '!' expression                { $$ = !$2; }
        ;

%%

void yyerror (yyscan_t yyscanner, char const *msg){
    fprintf(stderr, "%s\n", msg);
}


void main(void) {

    std::string inp = "1|0\n";

    bool nasi = parseExpression(inp);
    printf("%s%d\n", "nasi ", nasi);
    printf("Press ENTER to close. ");
    getchar();
}

私がカンニングをして、yyg自分自身を次のように定義したことに注意してください。

struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;

を取得する別の方法が見つかりませんYY_CURRENT_BUFFER。誰かが を取得する最良の方法を知っている場合はYY_CURRENT_BUFFER、教えてください。

于 2014-10-22T12:37:36.873 に答える