私は動作するScalaパーサーを持っていますが、ソリューションは私が望むほどクリーンではありません。問題は、一部のプロダクションは空白をトークンの一部と見なす必要がありますが、「高レベル」のプロダクションは空白を無視/スキップできる必要があることです。
下位レベルのパーサーを拡張する典型的なscalaパーサーパターンを使用すると、skipWhitespace設定が継承され、物事がすぐに乱雑になります。
extendsアプローチを使用せずに、低レベルのパーサーのインスタンスを高レベルのパーサーのクラスで使用できるようにする方がよいと思いますが、各インスタンスが表示されるように、それを機能させる方法がわかりません。入力文字のストリームは1つだけです。
これが最下位レベルのパーサーの一部です-
class VulgarFractionParser extends RegexParsers {
override type Elem = Char
override val whiteSpace = "".r
それから私はそれを次のように拡張します
class NumberParser extends VulgarFractionParser with Positional {
ただし、この時点で、NumberParserはFractionParserと同じように空白を明示的に処理する必要があります。NumberParserの場合、それでもかなり管理しやすいですが、次のレベルでは、通常のregexParserと同じように、空白を区切り文字として使用するプロダクションを定義できるようにしたいと考えています。
例は次のようになります。
IBM 33.33/ 1200.00
or
IBM 33.33/33.50 1200.00
2番目の値には、「/」で区切られた2つの部分がある場合と、スラッシュの後に何もない(またはスラッシュがまったく含まれていない)単一の部分しかない場合があります。
def bidOrAskPrice = ("$"?) ~> (bidOrAskPrice1 | bidOrAskPrice2 | bidOrAskPrice3)
def bidOrAskPrice1 = number ~ ("/".r) ~ number ~ (SPACES) ^^ {
case a ~ slash ~ b ~ sp1 => BidOrAsk(a,Some(b))
}
def bidOrAskPrice2 = (number ~ "/" ~ (SPACES)) ^^ { case a ~ slash ~ sp => BidOrAsk(a,None) }
def bidOrAskPrice3 = (number ~ (SPACES?)) ^^ { case a ~ sp => BidOrAsk(a , None)}