Scalaコンビネーターパーサー-数値文字列と変数文字列を区別する
-
05-07-2019 - |
質問
Cay Horstmannのコンビネーターパーサーエクササイズを行っています。数字を表す文字列と、マッチステートメントの変数を表す文字列を区別する最良の方法について疑問に思います。
def factor: Parser[ExprTree] = (wholeNumber | "(" ~ expr ~ ")" | ident) ^^ {
case a: wholeNumber => Number(a.toInt)
case a: String => Variable(a)
}
そこの2行目、<!> quot; case a:wholeNumber <!> quot;違法です。正規表現について考えましたが、<!> quot; case <!> quot;で動作させる方法を見つけていません。
解決
少し分割して、ケース分析を|
にプッシュします。これは、コンビネーターの利点の1つであり、実際には一般的にLL(*)構文解析を行います。
def factor: Parser[ExprTree] = ( wholeNumber ^^ { Number(_.toInt) }
| "(" ~> expr <~ ")"
| ident ^^ { Variable(_) } )
アンダースコア構文に慣れていない場合は申し訳ありません。基本的には、<!> quot; n 番目のパラメーターを囲んでいる関数の値<!> quot;に置き換えるだけです。したがって、{ Variable(_) }
は{ x => Variable(x) }
と同等です。
ここでのもう1つの構文マジックは、~>
の代わりの<~
および~
演算子です。これらの演算子は、その用語の解析に両方の括弧の構文を含める必要があることを意味しますが、結果はexpr
の結果によってのみ決定される必要があります。したがって、"(" ~> expr <~ ")"
は"(" ~ expr ~ ")"
とまったく同じものに一致しますが、<=>から内部結果値を取得するために追加のケース分析を必要としません。
所属していません StackOverflow