Парсеры Scala combinator - различают числовые и переменные строки - PullRequest
6 голосов
/ 02 ноября 2008

Я делаю упражнения синтаксического анализатора Cay Horstmann, мне интересно, как лучше различать строки, представляющие числа, и строки, представляющие переменные в операторе match:

def factor: Parser[ExprTree] = (wholeNumber | "(" ~ expr ~ ")" | ident) ^^ {
    case a: wholeNumber  => Number(a.toInt)
    case a: String => Variable(a)
}

Вторая строка "case a: wholeNumber" недопустима. Я думал о регулярном выражении, но не нашел способа заставить его работать с "case".

1 Ответ

6 голосов
/ 02 ноября 2008

Я бы немного разделил его и вставил анализ случая в |. Это одно из преимуществ комбинаторов и действительно LL (*) парсинга в целом:

def factor: Parser[ExprTree] = ( wholeNumber ^^ { Number(_.toInt) }
                               | "(" ~> expr <~ ")" 
                               | ident ^^ { Variable(_) } )

Я прошу прощения, если вы не знакомы с синтаксисом подчеркивания. По сути, это просто означает «подставить n -й параметр в значение функции включения». Таким образом, { Variable(_) } эквивалентно { x => Variable(x) }.

Еще одна магия синтаксиса здесь - это операторы ~> и <~ вместо ~. Эти операторы означают, что синтаксический анализ этого термина должен включать синтаксис обоих символов, но результат должен определяться исключительно результатом expr. Таким образом, "(" ~> expr <~ ")" соответствует точно так же, как и "(" ~ expr ~ ")", но для извлечения внутреннего значения результата из expr.

не требуется дополнительный анализ случая
...