私は大学での宿題で、Scala コンビネーターを使用して命題論理を解析するように指示されました。これに数時間取り組んでいて、問題を解決することさえできないので、髪を引き裂こうとしています。最初の段階。
最初の部分は、指定された EBNF 形式に準拠する認識タイプ (タイプは既に個別に提供されています) を構築するレコグナイザーを構築することです。([] は 0 または 1 を意味し、+ は 1 つ以上を意味し、* は 0 以上を意味します)
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)
}
構文のより良いアウトラインへのヒントを形成する助けは信じられないほどの助けになるでしょう。これは、命題論理とパーサーに慣れている人にとってはかなり簡単な問題であることは理解していますが、私は何時間も頭を悩ませており、少しずつハッキングすることに近づいています.
編集: 更新指定された構文は 1 つの項目で間違っていたので、微調整したところ、完全に機能するようになりました:
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~")"