Flex和Bison的用途

4
我是Flex和Bison的新手,我尝试写了一个Flex词法扫描器和一个Bison语法,但是遇到了以下问题:
  • 一个单词有时可能与Flex定义中的不同定义匹配,我希望Bison能够从它的语法中找到正确的Flex定义。
例如,如果单词abc在Flex中可以被视为category1category2,如果出现没有语法错误的category1,则我希望Bison选择category1,而不是category2;但如果它作为category1时出现语法错误,而不是作为category2,那么Flex应该将其归类为category2
有办法做到这一点吗?还是我完全误解了Flex和Bison?

我不确定我理解你的问题。Bison/Flex可以帮助你定义语法。任何符合该定义的内容都不会有语法错误,因此你的“category2”很令人困惑。你能否提供更多关于你正在尝试做什么的细节? - Eduardo
我将标记从flex更改为gnu-flex,因为前者代表Apache Flex框架,显然不是这个问题的主题。 - weltraumpirat
简而言之:你不应该那样做。改写你的语法。 - Thomas Padron-McCarthy
你好,感谢您的回答。这里有一个例子。在flex文本中,例如有cat1 "abcd"和cat2 "abcd"|"efgh"*。然后在bison文本中有句子:cat1 cat2。如果我尝试解析像"abcd abcd"这样的文本,bison会告诉我第一个abcd是cat1,然后第二个也是cat1,所以会出现语法错误。我希望bison能够猜测第二个abcd是cat2,并且该句子是正确的。(我们如何在这些该死的注释中添加换行符?) - user1971969
3个回答

2
这种情况通常涉及到所谓的“半保留字”,或者C#中称为“上下文关键字”的词语。在bison/flex中,这些词语很难处理。(Lemon有一个未记录的特性,你可以使用%fallback指令定义一个令牌的回退选项,非常适用于这种情况;你只需将IDENTIFIER作为任何上下文保留令牌的回退选项即可)。
通过一些努力,您可能能够通过定义像以下非终结符号来实现相同的效果:
identifier : IDENTIFIER | VAR | ADD | REMOVE | DYNAMIC | GLOBAL | ...
/* VAR is special in a local-variable-type: */
local_variable_type_identifier : IDENTIFIER | ADD | REMOVE | DYNAMIC | GLOBAL | ...

你可以通过在整个代码中使用标识符,并解决每个包含将其替换为排除参与冲突的半保留单词的受限非终端符号的冲突来找到需要自定义的位置。

这不是最好的方法,但是我知道这是最好的方法。


哇哇哇,我尝试了很多次,但是我还是不理解你的答案...抱歉。这里有一个我正在尝试做的例子:在flex文本中,例如有cat1 "abcd"*和cat2 "abcd"|"efgh"。然后在bison文本中有句子:cat1 cat2。如果我尝试解析像"abcd abcd"这样的文本,bison会告诉我第一个abcd是cat1,然后第二个也是cat1,所以会出现语法错误。我希望bison能够猜测第二个abcd是cat2,并且该句子是正确的。 - user1971969
@user1971969:从上面的评论来看,你的语法设计有误——或者至少它似乎是上下文敏感的。上下文敏感的语法不容易被Bison处理;它并不是为此而设计的。我认为你走错了路。我想到的是一种语言,其中你可能会有rule1: token1 { start-state-1 } category1 { start-state-0; };rule2: token2 { start-state-2 } category2 { start-state-0; };,其中扫描器在状态1中返回“abc”的category1,在状态2中返回category2。这只是勉强可行的;你的规则可能不是。 - Jonathan Leffler

0

Flex支持“起始状态”和“独占起始状态”,这可能使您实现所需的效果。如果您可以预先确定上下文是这样的,即abc应该是category1,那么您可以告诉Flex启动一个状态,在该状态中将abc分类为category1,而在其他状态中,则将其分类为category2。不要忘记在完成特殊状态后切换回状态。这种技术可以用于使选定的关键字在某些情况下成为关键字,并在其他情况下保留其作为标识符。通常,您可以让词法分析器始终以相同的方式对其进行分类(例如,作为令牌KW_ABC),并让语法使用该令牌。


谢谢您的回答。我不确定是否理解了:在FLEX中,如何指示起始状态或独占起始状态? - user1971969
好的,我明白了。使用 %s 和 %x!我会尝试一下,如果成功了会告诉你的。 - user1971969
再次你好。我尝试了%s和%x,但它们并不符合我的问题,因为在我的情况下,仅使用flex中的rexp无法定义正确的上下文。我不知道该怎么办... - user1971969
嗨,阅读你回答的最后一句话:“通常,您需要让词法分析器始终以相同的方式对其进行分类(例如,作为令牌KW_ABC),然后让语法处理使用该令牌。”,我想知道您在想什么:如何通过语法来处理这种情况? - user1971969
我不会这样设计语法。我必须了解你正在解析什么,才能知道你想要什么。有了这个,我可能有一些帮助的机会。但是如果不了解你想要解析什么,我只能提供模糊的建议。你需要展示一些你想要解析的“句子”示例,并概述这些句子中各种符号应该代表的内容(应该被分类为什么)。 - Jonathan Leffler

-1
再次强调Jonathan Leffler在1月13日19:39的评论,您正在尝试使用上下文无关的解析器生成工具来解析上下文敏感的语言。您需要重新考虑语法或重新考虑解析器生成工具的选择--您所做的相当于试图使用螺丝刀来钉钉子。
如果是我,我会回到书本和互联网上重新审查处理上下文敏感语法解析的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接