有一个用yacc编写的简单语法,它用逻辑表达式构建一个树,由子表达式和AND(&&),OR(||)和NOT(!)运算符组成。我不会在这里提供语法,因为它没有什么特别之处,它类似于无数的YACC教程示例。
但是,我需要解析这些逻辑表达式,以便根据De Morgan的定律为NOT运算符扩展所有括号。例如,我需要处理表达式
!( ( A && B ) || C ) )
as
( !A || !B ) && !C
是否可以通过修改现有的yacc语法来实现这一点?
答案 0 :(得分:1)
这不是你应该在yacc语法中做的事情;你应该对你的语法结构进行后处理以执行这样的减少。
你的语法应该生成某种类型的AST - 你想走结构并寻找与!((A && B)|| C)
形状匹配的东西并将其转换为 - 放在(!A || !B) && C
。
如果您需要更多指导,可能需要添加更多信息或提出更多问题。
编辑:如果您想要任何帮助,应提供您的语法。这听起来像是一个家庭作业,所以我希望这不是你不提供代码的唯一原因。帮助我们帮助您。我们不知道你在语法的行为中做了什么,所以我们如何猜测我们能为你做些什么呢?
答案 1 :(得分:1)
在构建AST时,可以在YACC的 not (!)运算符的减少操作中执行此操作。您可以在语义操作中编写所需的任何代码。而不是“盲目地”组装不的树节点(你在这种减少动作中找到的常用代码),你可以编写检查孩子的代码,看看是否有需要的形状,如果是这样,构建每个的de Morgan等价树。执行此操作的代码有点乱,因为它必须在树上爬行,匹配节点和重新修剪子树,但它只是笨拙而且不错。请注意,De Morgan定律可以说适用于像(A&& B)||这样的儿童C)和(A || B&& C)),所以你要处理两个主要的子句。
我同意Len;你通常不会在解析器中这样做。它的目的是让你为更复杂的活动设置,除非DeMorganizing是唯一的目的,你需要其他代码来解析各种解析完成之后的各种代码,那么为什么不把所有的处理都留到那里呢? / p>
遵循这个想法,我的recent SO answer on eliminating configured-dead code简化了符号布尔逻辑;它展示了一种使用模式匹配源到源转换来转换布尔逻辑AST的方法。这种方法避免了令人讨厌的树检查/黑客代码。显而易见的是如何使用该技术编写实现de morgans定律的可读变换(实际上我们过去曾做过儿子)。