У меня есть работающий синтаксический анализатор Scala, но решение не такое чистое, как хотелось бы. Проблема в том, что некоторые продукты должны рассматривать пробелы как часть маркера, но продукты «более высокого уровня» должны иметь возможность игнорировать/пропускать пробелы.
Если я использую типичный шаблон синтаксического анализатора scala для расширения синтаксических анализаторов более низкого уровня, тогда настройки skipWhitespace наследуются, и все очень быстро становится беспорядочным.
Думаю, мне было бы лучше не использовать подход с расширением, а иметь экземпляр парсера низкого уровня, доступный в классе парсеров более высокого уровня, но я не уверен, как заставить это работать, чтобы каждый instance будет видеть только один поток вводимых символов.
Вот часть синтаксического анализатора самого низкого уровня.
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-е значение иногда состоит из двух частей, разделенных знаком «/», а иногда имеет только одну часть без ничего после косой черты (или даже вообще не содержащую косую черту).
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)}