2016-11-16 56 views
0

我有以下语法(SSCCE):如何最好地处理野牛同样规则的不同动作?

%token WORD 
%% 
program  : word word 
      ; 

word  : WORD // have to translate only for first word 
      ; 

规则word : WORD应具有动作,即对WORD令牌语义值被适当地“翻译”的语义值的左手侧,仅当这是规则program: word word中的第一个word

在野牛中这样做的最佳做法是什么?

我不明白如何做到这一点与行动。我必须扩展语法本身,以此:

%token WORD 
%% 
program  : word_translated word_not_translated 
      ; 

word_translated  : WORD { // translate } 
      ; 

word_not_translated : WORD { // do not translate } 
      ; 

好的,但是我不喜欢。因为语法有两个符号word_translatedword_not_translated,就语法而言,它们完全一样,所以语法太复杂了,应该简化成一个word。增加复杂性的唯一原因是,行动可能会有所不同。

这是做到这一点的唯一方法,这是野牛处理这种情况的最佳做法吗?

+1

是的,这是最好的做法 - 当你需要做同样的符号不同的动作(终端或非终端)的不同的上下文,你只需创建一个新的单例规则。 –

+0

@Chris好的谢谢你,但在此期间,我想出了如何做到这一点:使用'$ 0' –

+0

@ChrisDodd我发现了全面的情况,而不是我的帖子中简单的SSCCE,使用' $ 0','$ -1'等是不切实际的。它真的就像自己构建树并走路。所以你的评论是黄金。你应该让它成为我会接受的答案。 –

回答

1

语义操作最好从任何编译器或解释器中的分析树来执行。如果您试图从野牛规则动作中执行语言语义行为方向,您将永远陷入你描述的那种混乱状态。

只要在野牛行动中构建一个分析树,然后在树完全知道后采取适当的语义行为来行走树。大多数标准的编译器文本都有工作示例。

+0

谢谢!但我不明白这一点。我想我知道什么是“解析树”,根据野牛手册和yacc/bison文本,解析树是野牛构建的,它不适合我在野牛行动中构建它,就像你似乎建议。野牛行动是对野牛建造的分析树进行反应。在我的情况下,就词法分析器而言,这两个WORD令牌是完全一样的 - 它们不能由词法分析器区分。 –

+0

@MarkGaleck其他解析器生成器具有构建树的功能,但bison/yacc不具备这些功能。它必须手动编码。我为我的学生制作了一个教学视频[https://youtu.be/oOFfVZrvhMA?list=PL3czsVugafjNLmIHA8ODBxuwWy8W4Uk9h] –

+0

谢谢!我观看了您的视频并仔细阅读了野牛文档 - 事实上,我错了,野牛不会建树。在视频中,它展示了如何构建分析树,这对学生来说是一个很棒的视频,但对我来说,很明显,不需要解释。对我来说这个问题是“为什么”我需要一个解析树。我发现在其他应用程序中可能需要构建和行走树,并且我发现在我的情况下我可以这样做来解决我的问题。但就我而言,这将是一种矫枉过正,甚至比我的帖子还要复杂。我的应用程序中不需要树。见下文。 –

-1

我会恭敬地不同意Brian的断言,野牛动作应该只用来建立一个解析树,然后解析后,树应该走,在这期间,应该采取真正的行动。否则,一个“总是陷入混乱”。

如果是这样的话,经典奥赖利YACC文本不会说:“通常情况下,动作代码生成对应 输入解析树,这样以后的代码可以处理整个语句或甚至整个 程序一次“。不是“经常”,而是说“永远”。

但是,布赖恩的答案在这方面非常有用,在试图理解它时,我不得不阅读。然后,我发现恕我直言正确的答案,我的问题,因为它张贴。我会为未来浏览器的好处发布答案。

恕我直言,正确的方法是使用$0。随着我的帖子原来的语法,该操作的伪代码将是:

if ($0 is meaningful) 
    $$ = $1 
else 
    $$ = translate($1) 
+0

野牛手册对使用'$ 0 $'说明:“这是一个非常冒险的做法,为了可靠地使用它,您必须确定规则应用的上下文。”目前还不完全清楚你如何在不以某种方式冒险进入未定义行为的情况下验证“$ 0是否有意义”。它可能适用于某个特定架构的特定应用程序等,但它不是一种在不清楚其局限性的情况下应该使用的技术。 – rici

+0

@rici我不是在与“风险”部分争论。但我不同意“目前尚不清楚你如何提出验证意见”。很简单。看看我的SSCCE。应用程序代码可以将'yylval'初始化为一个无效值,或者可以将其声明为'static'并且已知有零位的初始化。 'translate'函数返回一个有效的非零值。这很简单,不是吗? –

+0

只能工作一次。是的,在你的微不足道的语法中,这是可能的,但如果'程序'不是最高级别的非终端,那么对'yylval'具有的值的控制就会少得多。对于语法如此微不足道的野牛来说,这并不值得,所以我认为你实际上已经有了一些更复杂的想法,就像任何人在这个问题上磕磕绊绊一样。你在代码中所做的事绝对是你的担心,我无意试图劝阻你。我的评论和downvote是试图给其他读者附加健康警告。 – rici