【问题标题】:How to run code on start of yylex and when token is matched in RE-flex如何在 yylex 开始时运行代码以及何时在 RE-flex 中匹配令牌
【发布时间】:2022-06-16 04:05:47
【问题描述】:

我正在使用 RE-flex 为项目生成 c++ 扫描器。我想在匹配令牌时运行代码,并且我遵循了 Flex 的做法,但最终将代码放在了函数之外。当一个令牌匹配时,我怎么能把它放在最后?另外,我想在 yylex 的开头运行代码。当我以 Flex 方式执行此操作时,它会根据开始条件将代码放在 switch 语句中。无论启动条件如何,如何运行此代码?扫描仪文件在此处给出。

%top {
    #include "driver.h"
    #include "y.tab.hh"
    std::string buffer_2;

    bool actionReturned = false, typeReturned = false, headerReturned;
    int actionCount = 0, typeCount = 0;
%}

%{
    #undef YY_USER_ACTION
%}

%option noyywrap nounput noinput batch debug
%option params="driver &drv"
%x HEADER ACTION TYPE

blank [ \t\r]+
newline \n+
id [a-zA-Z_][a-zA-Z0-9_]*

%{
    #define YY_USER_ACTION loc.columns(yyleng);
%}

%%

    yy::location &loc = drv.location;
    loc.step();
    if(actionReturned) {
        actionReturned = false;
        buffer_2.clear();
        return yy::parser::make_ACTION_CLOSE(loc);
    }
    if(typeReturned) {
        typeReturned = false;
        buffer_2.clear();
        return yy::parser::make_TYPE_CLOSE(loc);
    }
    if(headerReturned) {
        headerReturned = false;
        buffer_2.clear();
        return yy::parser::make_HEADER_CLOSE(loc);
    }

<INITIAL>{blank} loc.step();
<INITIAL>{newline} loc.lines(yyleng); loc.step();
<INITIAL>"%empty" return yy::parser::make_EPSILON(loc);
<INITIAL>"%type" return yy::parser::make_TYPE(loc);
<INITIAL>"%union" return yy::parser::make_UNION(loc);
<INITIAL>"%token" return yy::parser::make_TOKEN(loc);
<INITIAL>"%%" return yy::parser::make_DELIMITER(loc);
<INITIAL>";" return yy::parser::make_SEMICOLON(loc);
<INITIAL>"*" return yy::parser::make_KLEENE_STAR(loc);
<INITIAL>"+" return yy::parser::make_ZERO_MORE(loc);
<INITIAL>"?" return yy::parser::make_OPTIONAL(loc);
<INITIAL>"/" return yy::parser::make_PRODUCTION_OR(loc);
<INITIAL>"<-" return yy::parser::make_RULE_OPEN(loc);
<INITIAL>"%{" BEGIN(HEADER); return yy::parser::make_HEADER_OPEN(loc);
<INITIAL>"<" BEGIN(TYPE); ++typeCount; return yy::parser::make_TYPE_OPEN(loc);
<INITIAL>"{" BEGIN(ACTION); ++actionCount; return yy::parser::make_ACTION_OPEN(loc);
<INITIAL>{id} return yy::parser::make_ID(yytext, loc);
<INITIAL>. {
    throw yy::parser::syntax_error(loc, "Unexpected character: " + std::string(yytext));
}
<INITIAL><<EOF>> return yy::parser::make_YYEOF(loc);

<HEADER>"}" {
loc.step();
    if(buffer_2[buffer_2.length() - 1] == '%') {
        // end has been matched
        buffer_2.pop_back();
        headerReturned = true;
        return yy::parser::make_HEADER_CODE(buffer_2, loc);
    }
    buffer_2 += '}';
}
<HEADER>(.|\n) buffer_2 += yytext[0]; loc.step();

<ACTION>"{" ++actionCount; buffer_2 += '{'; loc.step();
<ACTION>"}" {
    --actionCount;
    loc.step()
    if(!actionCount) {
        actionReturned = true;
        BEGIN(INITIAL);
        return yy::parser::make_ACTION_CODE(buffer_2, loc);
    }
    buffer_2 += '}';
}
<ACTION>\n buffer_2 += yytext[0] loc.lines(yyleng); loc.step();
<ACTION>. buffer_2 += yytext[0]; loc.step();

<TYPE>"<" ++typeCount; buffer_2 += '}'; loc.step();
<TYPE>">" {
    --typeCount;
    loc.step();
    if(!typeCount) {
        typeReturned = true;
        BEGIN(INITIAL);
        return yy::parser::make_TYPE_CODE(loc);
    }
    buffer_2 += '>';
}
<TYPE>\n buffer_2 += yytext[0]; loc.lines(yyleng); loc.step();
<TYPE>. buffer_2 += yytext[0]; loc.step();

%%

void driver::scanBegin() {
    yy_flex_debug = traceScanning;
    if(file.empty() || file == "-") {
        fprintf(stderr, "Could not open file\n");
        exit(1);
    }
    if(!(yyin = fopen(file.c_str(), "r"))) {
        fprintf(stderr, "Could not open file\n");
        exit(1);
    }
}

void driver::scanEnd() {
    fclose(yyin);
}

【问题讨论】:

    标签: c++ bison flex-lexer lex


    【解决方案1】:

    使用YY_USER_INIT 宏注入在第一次调用yylex() 时执行的代码。这是 RE-flex 支持的 flex 宏此外,RE-flex 有一个新的代码段 %begin{ ... } 专门用于定义应该在扫描开始之前执行的代码,但在扫描仪初始化之后(即同时点为 flex YY_USER_INIT)。查看 RE-flex 中的Lexer/yyFlexLexer class 结构,快速了解生成的扫描仪的代码结构是什么样的。

    在 flex 和 RE-flex 中也有对 initial code blocks 的定义,它们在模式匹配之前在 yylex() 中执行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-18
      • 2016-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多