简体   繁体   English

在令牌替换之类的问题之后,如何让yacc / bison和/或lex / flex重新开始扫描?

[英]How do I get yacc/bison and/or lex/flex to restart scanning after something like token substitution?

Is there a way to force bison and/or flex to restart scanning after I replace some token with something else? 在用其他东西代替某些令牌后,是否有办法强迫野牛和/或flex重新开始扫描?

My particular example would be with replacement for a specific word/string. 我的特定示例是替换特定的单词/字符串。 If I want a word of hello to be replaced by echo hello , how can I get flex or bison to replace hello and then start parsing again (to pick up 2 words instead of just one). 如果我想的话hello要被替换echo hello ,我怎样才能得到弯曲或野牛更换hello ,然后再次开始解析(拿起2个字,而不只是一个)。 So it would be like: 就像这样:

  • Get token WORD (which is a string type) 获取令牌WORD(这是字符串类型)
  • If hello , replace token value with echo hello 如果hello ,请将令牌值替换为echo hello
  • Restart parsing entire input (which is now echo hello ) 重新开始解析整个输入(现在是echo hello
  • Get token WORD ( echo ) 获取令牌WORD( echo
  • Get token WORD ( hello ) 获取令牌WORD( hello

I've seen very tempting functions like yyrestart() , but I don't really understand what that function in particular really accomplishes. 我见过非常诱人的功能,例如yyrestart() ,但我并不真正了解该功能的真正作用。 Any help is greatly appreciated, thanks! 非常感谢任何帮助,谢谢!

Update 4/23/2010 更新4/23/2010

One kind of hack-and-slash solution I've ended up using is for each word that comes through, I check an "alias" array. 我最终使用的一种破解和斜线解决方案是针对出现的每个word ,我检查一个“别名”数组。 If the word has an alias, I replace the value of the word (using, for example, strcopy($1,aliasval) ), and mark an aliasfound flag. 如果word有别名,我将替换单词的值(例如,使用strcopy($1,aliasval) ),并标记一个aliasfound标志。

Once the entire line of input is parsed once, if the aliasfound flag is true, I use yy_scan_string() to switch the buffer state to the input with expanded aliases, and call YYACCEPT . 一旦对整个输入行进行了一次解析,如果aliasfound标志为true,我将使用yy_scan_string()将缓冲区状态切换为具有扩展别名的输入,并调用YYACCEPT

So then it jumps out to the main function and I call yyparse() again, with the buffer still pointing to my string. 因此,它跳到了主函数,我再次调用yyparse() ,缓冲区仍然指向我的字符串。 This continues until no aliases are found. 一直持续到找不到别名为止。 Once all of my grammar actions are complete, I call yyrestart(stdin) to go back to "normal" mode. 完成所有语法操作后,我将调用yyrestart(stdin)返回“正常”模式。

If anyone knows how I can effectively expand my words w/ their alias values, inject into stdin (or some other method), and basically expand all aliases (even nested) as I go, that would be awesome. 如果有人知道我如何才能有效地扩展其单词的别名值,将其注入stdin (或其他方法),并且基本上随便扩展所有别名(甚至嵌套),那就太好了。 I was playing around with yypush_buffer_state() and yypop_buffer_state() , along with yy_switch_to_buffer() , but I couldn't get "inline" substitution with continued parsing working... 我在玩yypush_buffer_state()yypop_buffer_state()以及yy_switch_to_buffer() ,但是在继续解析工作的过程中,我无法获得“内联”替换...

It seems to me that the place to fix this is the lexer. 在我看来,解决此问题的地方是词法分析器。 I would suggest using flex, which supports a state machine (called " Start Conditions " in the flex documentation). 我建议使用flex,它支持状态机(在flex文档中称为“ 开始条件 ”)。 You change states using BEGIN , and the states need to be defined in the definitions section. 您可以使用BEGIN更改状态,并且需要在定义部分中定义状态。

So, for example, you could have a rule like 因此,例如,您可能有一条规则

<INITIAL>hello    BEGIN(in_echo); yyless(0); return (WORD_ECHO);
<in_echo>hello    BEGIN(0); return (WORD_HELLO);

yyless() truncates the yytext to the given value, so this puts the entire input back into the stream. yyless()yytext截断为给定的值,因此这会将整个输入放回流中。

I haven't tried this out myself, but I think this is the structure of the solution you want. 我自己还没有尝试过,但是我认为这是您想要的解决方案的结构。

Adding an "answer" based on what I ended up doing. 根据最终结果添加“答案”。 Want to mark this question as answered. 希望将此问题标记为已回答。

Update 4/23/2010 更新4/23/2010

One kind of hack-and-slash solution I've ended up using is for each word that comes through, I check an "alias" array. 我最终使用的一种破解和斜线解决方案是针对出现的每个单词,我检查一个“别名”数组。 If the word has an alias, I replace the value of the word (using, for example, strcopy($1,aliasval)), and mark an aliasfound flag. 如果单词有别名,则替换单词的值(例如,使用strcopy($ 1,aliasval)),并标记一个aliasfound标志。

Once the entire line of input is parsed once, if the aliasfound flag is true, I use yy_scan_string() to switch the buffer state to the input with expanded aliases, and call YYACCEPT. 一旦对整个输入行进行了一次解析,如果aliasfoundfound标志为true,那么我将使用yy_scan_string()将缓冲区状态切换为具有扩展别名的输入,然后调用YYACCEPT。

So then it jumps out to the main function and I call yyparse() again, with the buffer still pointing to my string. 因此,它跳到了主函数,我再次调用yyparse(),缓冲区仍然指向我的字符串。 This continues until no aliases are found. 一直持续到找不到别名为止。 Once all of my grammar actions are complete, I call yyrestart(stdin) to go back to "normal" mode. 完成所有语法操作后,我将调用yyrestart(stdin)返回“正常”模式。

If anyone knows how I can effectively expand my words w/ their alias values, inject into stdin (or some other method), and basically expand all aliases (even nested) as I go, that would be awesome. 如果有人知道我如何才能有效地扩展其单词的别名值,将其注入stdin(或其他方法),并且基本上随便扩展所有别名(甚至嵌套),那就太好了。 I was playing around with yypush_buffer_state() and yypop_buffer_state(), along with yy_switch_to_buffer(), but I couldn't get "inline" substitution with continued parsing working... 我当时在玩yypush_buffer_state()和yypop_buffer_state()以及yy_switch_to_buffer(),但是在继续解析工作的过程中我无法获得“内联”替换...

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

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