在解析整个字符串之前,如何让Bison / YACC无法识别命令?

时间:2010-04-08 15:53:43

标签: c parsing yacc bison

我有一些野牛语法:

input: /* empty */
       | input command
;

command:
        builtin
        | external
;

builtin:
        CD { printf("Changing to home directory...\n"); }
        | CD WORD { printf("Changing to directory %s\n", $2); }
;

我想知道如何让Bison不接受(YYACCEPT?)某事作为command,直到它读取所有输入。所以我可以在下面使用所有这些规则来使用递归或其他任何构建的东西,这会产生一个有效的命令或一些不起作用的东西。

我正在使用上面的代码进行的一个简单测试就是输入“cd mydir mydir”。野牛解析CDWORD然后“嘿!这是一个命令,把它放到顶部!”。然后它找到的下一个标记只是WORD,它没有规则,然后报告错误。

我希望它阅读整行并意识到CD WORD WORD不是规则,然后报告错误。我想我错过了一些明显的东西,非常感谢任何帮助 - 谢谢!

此外 - 我尝试使用input command NEWLINE或类似内容,但它仍然将CD WORD作为命令推送到顶部,然后分别解析额外的WORD

4 个答案:

答案 0 :(得分:2)

有时我通过压扁我的语法处理这些案件。

在你的情况下,为你的词法分析器为换行符和命令分隔符(;)添加标记可能是有意义的,这样你就可以明确地将它们放入你的Bison语法中,这样解析器就可以期待命令的完整输入行了。接受作为一个命令。

sep:   NEWLINE | SEMICOLON
   ;

command:  CD  sep
   |  CD WORD sep
   ;

或者,对于像真实shell这样的任意参数列表:

args:
    /* empty */
  | args WORD
  ;

command:
      CD args sep
   ;

答案 1 :(得分:1)

不要直接调用操作,而是先构建一个抽象语法树。然后根据结果和您的偏好,您可以执行部分​​操作,也可以不执行任何操作。如果在构建树期间出现解析错误,您可能需要使用%destructor指令告诉bison如何进行清理。

这实际上是一种正确的方法,因为你可以完全控制内容和逻辑,而你让bison只需要解析它。

答案 2 :(得分:0)

通常,事情并没有按照你描述的方式完成。

对于Bison / Yakk / Lex,人们通常会仔细设计他们的语法以完全满足他们的需要。因为Bison / Yakk / Lex自然greedy有正则表达式,所以这对你有帮助。

那么,相反如何。

由于您一次解析整个,我认为我们可以利用这一事实来修改语法。

input : /* empty */
      | line


command-break : command-break semi-colon
              | semi-colon

line : commands new-line

commands : commands command-break command
         | commands command-break command command-break
         | command
         | command command-break

...

new-line,'分号is defined in your lex source as something like \ n , \ t``这应该为您提供您正在寻找的命令的UNIX样式语法。各种各样的事情是可能的,它有点膨胀,允许多个分号,并没有考虑到空白,但你应该得到这个想法。

Lex和Yakk是一个强大的工具,我发现它们非常有趣 - 至少,当你没有在截止日期之前。

答案 3 :(得分:0)

难道你不能只改变规则匹配操作以附加到你想要执行的操作列表中吗?然后在处理完整个输入之后,根据您是否看到任何解析错误,决定是否要执行该操作列表中的操作。