繁体   English   中英

如何通过“win_flex bison”编写纯解析器和可重入扫描器?

[英]How to write a pure parser and reentrant scanner by “win_flex bison”?

我编写了一个用于评估逻辑表达式的解析器。 我知道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. 有很多关于'reentrant'和'pure'的例子,但我找不到最好的指导方针。

有人可以指导我吗?

提前致谢。

幸运的是,我做到了。 这是我的代码。 我认为这对于想要编写纯解析器的人来说可能是一个很好的指南。

我的可重入扫描仪:

    /* 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的最佳方法,请告诉我, YY_CURRENT_BUFFER

这是一个完整的Flex / Bison C ++示例。 一切都是可重入的,不使用全局变量。 解析器/词法分析器都封装在一个放在单独命名空间中的类中。 您可以根据需要在尽可能多的线程中实例化尽可能多的“解释器”。

https://github.com/ezaquarii/bison-flex-cpp-example

免责声明:尚未在Windows上进行测试,但是该代码应该可以通过少量调整进行移植。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM