我已经为大学的任务设定了一项作业任务,使用Scala组合器来解析命题逻辑,我即将撕掉我的头发,因为我已经工作了几个小时,甚至不能过了第一阶段。
最初的部分是构建一个识别器,用于构建符合给定EBNF格式的识别类型(类型已单独提供)。 ([]表示0或1,+表示一个或多个,*表示零或更多)
prop ::= equiv
equiv ::= impl biArrow impl
p <=> q becomes Equivalent (P, Q)
p <+> q becomes Not (Equivalent (P, Q))
impl ::= disj [impls]
impls ::= (rightArrow disj)+
p => q becomes Implies (P, Q)
| (leftArrow disj)+
p => q becomes Implies (Q, P)
disj ::= conj (disjOp conj)*
p | q becomes Or (P, Q)
conj ::= neg (conjOp neg)
p & q becomes And (P, Q)
neg ::= negs | pos
negs ::= negOp neg
~ p becomes Not (P)
pos ::= ident | "(" prop ")"
ident becomes Literal (true, ident)
我们在组合器中给出的scala代码提供了一个懒惰的prop定义,这是一个错误。我已经开始填写类以匹配上面的代码,但是即使我实现它,我也没有捕到正确的错误,我认为实际上我不明白你如何指定捕获值解析器
trait PropRecognizer extends RegexParsers {
val ident = """[a-zA-Z]\w*""".r
val biArrow = "<=>" | "<+>"
val rightArrow = "=>"
val leftArrow = "<="
val disjOp = "|"
val conjOp = "&"
val negOp = "~"
lazy val pos = ident | "("~prop~")"
lazy val negs: Parser[Any] = negOp~neg
lazy val neg = negs | pos
lazy val conj = neg~(conjOp~neg).* | neg
lazy val disj = conj~(disjOp~conj).* | conj
lazy val impls = (rightArrow~disj).+ | (leftArrow~disj).+ | disj
lazy val impl = disj~impls.? | impls
lazy val equiv = impl~biArrow~impl | impl
lazy val prop: Parser[Any] = rep(equiv)
}
任何帮助,形成一个更好的语法概述的提示将是非常有帮助的,我一直在阅读文档,但似乎仍然无法点击我的脑袋。我理解这对于那些习惯于命题逻辑和解析器的人来说是一个相当容易的问题,但我现在已经抓了好几个小时了,而且我正在接近只是一点一点地破解我的方式。
编辑:更新一个项目给出的语法是错误的,所以我调整了它,现在效果很好:
lazy val prop: Parser[Any] = rep(equiv)
lazy val equiv: Parser[Any] = impl~(biArrow~impl).?
lazy val impl = disj~impls.?
lazy val impls: Parser[Any] = (rightArrow~disj).+ | (leftArrow~disj).+
lazy val disj = conj~(disjOp~conj).*
lazy val conj: Parser[Any] = neg~(conjOp~neg).*
lazy val neg: Parser[Any] = negs | pos
lazy val negs: Parser[Any] = negOp~neg
lazy val pos = ident | "("~prop~")"
答案 0 :(得分:3)
您需要使用^^
运算符/方法将解析后的表达式转换为表示类。例如:
lazy val conj: Parser[And] = neg~conjOp~neg ^^ {case p1~_~p2 => And(p1,p2)}
这假定neg
的类型为Parser[Proposition]
,它是表示任何公式的超类,And
将两个命题作为参数。您需要知道Parser[T]
将解析某些输入并返回类型T
的值作为其结果。
同样Parser
是协变的,因此您可以使用Parser[And]
来解析任何命题。
查看命名逻辑解析器的this示例。