私は、scala RegexParsersを使って、私が使っているプログラミング言語の算術フラグメント専用のパーサーを作成しようとしています。 現状では、私のトップレベルの表現パーサーの形式は次のとおりです。Scala Parserのアドホック演算子の優先順位を表す
parser: Parser[Exp] = binAppExp | otherKindsOfParserLike | lval | int
それは"a.b, a.b[c.d], a[b], {record=expression, like=this}"
のようなものだけで罰金(lvalsを受け付け今、私は"1 + b/c = d"
のような表現を可能にしたいのですが、潜在的に(ソースで。スラールではなく、言語ではない)コンパイル時のユーザー定義演算子
最初の考えは、操作を再帰的かつ数値的に優先順位でエンコードすると、より高い優先順位をアドホックに追加することができ、操作式の右辺の優先順位の低いサブクラスを消費するので、かなり一般的なオペラでそのアイデアのおもちゃを作ろうとしていますators。 だから、私はのようなものに構文解析することを"1 * 2+1"
が期待しています。ここではcase class Call(functionName: String, args: Seq[Exp]) extends Exp
です。
代わりに、IntExp(1)
として解析します。
これがうまくいかない理由はありますか(私は行方不明のまま再帰的に実行されますか?そうであれば、何か間違っていると思われます。それ以外の理由で間違っているのでしょうか?
def binAppExp: Parser[Exp] = {
//assume a registry of operations
val ops = Map(
(7, Set("*", "/")),
(6, Set("-", "+")),
(4, Set("=", "!=", ">", "<", ">=", "<=")),
(3, Set("&")),
(2, Set("|"))
)
//relevant ops for a level of precedence
def opsWithPrecedence(n: Int): Set[String] = ops.getOrElse(n, Set.empty)
//parse an op with some level of precedence
def opWithPrecedence(n: Int): Parser[String] = ".+".r ^? (
{ case s if opsWithPrecedence(n).contains(s) => s },
{ case s => s"SYMBOL NOT FOUND: $s" }
)
//assuming the parse happens, encode it as an AST representation
def folder(h: Exp, t: LangParser.~[String, Exp]): CallExp =
CallExp(t._1, Seq(h, t._2))
val maxPrecedence: Int = ops.maxBy(_._1)._1
def term: (Int => Parser[Exp]) = {
case 0 => lval | int | notApp | "(" ~> term(maxPrecedence) <~ ")"
case n =>
val lowerTerm = term(n - 1)
lowerTerm ~ rep(opWithPrecedence(n) ~ lowerTerm) ^^ {
case h ~ ts => ts.foldLeft(h)(folder)
}
}
term(maxPrecedence)
}
それはdoesnのこれらは正規表現です。文脈自由なもの(BNFのようなもの)かもしれませんが、私は確かに分かりません。 – Laurel
ええ、それは良い点です。私はスカラーパーサーコンビネーターを使用しています(そしてスカラー正規表現パーサーはその一部です)、私は使用しているライブラリーについてのコンテキストを提供したがっています。 – jcc333
OK、私は正規表現「。+」を持っていますが、それがどのように収まるかを知るためにScalaを知りません。CFGパーサーを使ってそのようなものを解析できるはずです。私はそれがあると仮定します)。 – Laurel