Отслеживание возврата в комбинаторах синтаксического анализатора scala?
-
26-09-2019 - |
Вопрос
Похоже, что комбинаторы синтаксического анализа scala не возвращаются назад.У меня есть грамматика (см. Внизу), которая не может правильно разобрать следующий "stmt":
copy in to out .
Это должно быть легко разобрать с помощью обратного отслеживания:
stmt: (to out(copy in))
или я что-то упускаю?
Анализатор:
type ExprP = Parser[Expr]
type ValueP = Parser[ValExpr]
type CallP = Parser[Call]
type ArgsP = Parser[Seq[Expr]]
val ident = "[a-zA-Z\\+\\-\\*/%><\\\\\\=]+".r
val sqstart = "\\[" .r
val sqend = "\\]" .r
val del = "," .r
val end = "\\." .r
def stmt: ExprP = expr <~ end
def expr: ExprP = ucall | call | value
def value: ValueP = ident ^^ {str => IdentExpr(str)}
def call: CallP = (args ~ ident ~ expr) ^^ {case args ~ method ~ upon => Call(args, method, upon)}
def ucall: CallP = (ident ~ expr) ^^ {case method ~ upon => Call(Seq(), method, upon)}
def args: ArgsP = advargs | smplargs
def smplargs: ArgsP = expr ^^ {e => Seq(e)}
def advargs: ArgsP = (sqstart ~> repsep(expr, del) <~ sqend) ^^ {seq => seq}
Решение
Вы хотите использовать PackratParsers
в 2.8. Я думаю, что парсер PackRat является единственным отступлением парсера.
Редактировать: по состоянию на середине 2015 года, вы должны использовать fastparse. вместо. Это не только намного быстрее, но и легче использовать (особенно при строительстве структур данных из разборки).
Другие советы
Ваша проблема не в том, чтобы вернуться назад.Стандартный |
оператор в scala.util.parsing.combinator
сделаем откат назад.Ваша проблема заключается в левой рекурсии (expr
→ call
→ args
→ smplargs
→ expr
).Синтаксический анализ Packrat действительно может помочь в этом.