flex + bison,具有不同语法的部分

flex+bison, sections with different syntaxes

我正在使用 flex & bison 开发一个解析器,它应该解析具有不同语法的不同部分的源代码。

想想 php,它只是 "stupidly" 转储所有内容,直到找到 <?php,然后它进入实际解析内容的句法部分,当它找到 ?> 时,它会返回转储。

所以当我在 "dumping" 部分时,扫描仪应该只提供原始字符串。有意义的标记(WHILE、OPENPARENTHESIS、IDENTIFIER 等)只能在句法部分中提供,并且 \ 开始句法部分。

我发现你可以给不同的 flex 规则 "start conditions", 所以我基本上可以在不同的扫描仪之间切换,比如

%x semantic
%x dump
%%
<dump>"\"        { BEGIN(semantic); }
<dump>.           { (*yylval).stringvalue = yytext; return yy::parser::token::CHAR;}
<semantic>"while" {return yy::parser::token::WHILE;}

这正是我所需要的。

我的问题是句法部分的结尾不能用正则表达式来描述,所以这个决定不能在扫描器内完成,它必须由解析器来完成。我基本上希望它回到转储模式 "in between rules"。所以我想做一些像

CODEELEMENT: FOR OPEN STATEMENT SEMICOLON BOOL SEMICOLON STATEMENT CLOSE <<GO TO DUMP MODE>> ELEMENT

你可能会说,这应该成为 C 中 for 循环之类的规则,但是 "body"(ELEMENT)应该再次被读取为转储(这将提供只有一个字符,除非您再次将多个字符与 { 和 } 组合在一起)

我知道 bison 可以执行代码 "in between rules",我尝试声明一个全局变量(呃)"dumpmode",像这样将 {dumpmode = true;} 放入规则中

CODEELEMENT: FOR OPEN STATEMENT SEMICOLON BOOL SEMICOLON STATEMENT CLOSE {dumpmode = true;} ELEMENT

并放

if(dumpmode)
{
    BEGIN(dump);
    dumpmode = false;
}

在 flex 规则前面(这与我在上面链接的页面上的示例相似)

但这是行不通的,它实际上是有道理的 - AFAIK bison 已经需要最终的 ELEMENT 令牌来决定使用该规则(因此代码不会在令牌到来之前执行),但这个令牌只会由转储模式生成,该模式在该过程中此时未激活。

你知道这样做的方法吗?在规则之间从 bison 代码切换 flexer 的启动条件?也许我需要像

这样打破野牛规则
CODEELEMENT: FOR1 FOR2
    ;
FOR1: FOR OPEN STATEMENT SEMICOLON BOOL SEMICOLON STATEMENT CLOSE {dumpmode = true;}
    ;
FOR2: ELEMENT
    ;

但我认为这种方法不适用于 if-then-else 结构...

您是否尝试过函数 void yy_pop_state (),从 Bison 部分调用它?