scala 解析器组合器中的回溯?

发布于 2024-10-11 03:37:03 字数 1118 浏览 9 评论 0原文

看来 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}

It seems like scala's parser combinators don't backtrack. I have a grammar (see bottom) which can't parse the following "stmt" correctly:

copy in to out .

That should be easy to parse with backtracking:

stmt: (to out(copy in))

or am I missing something?

Parser:

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}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我做我的改变 2024-10-18 03:37:04

您想在 2.8 中使用 PackratParsers。我认为 Packrat 解析器是唯一的回溯解析器。

编辑:从 2015 年年中开始,您应该使用 fastparse 代替。它不仅速度更快,而且更易于使用(特别是在通过解析构建数据结构时)。

You want to use PackratParsers in 2.8. I think the packrat parser is the only backtracking parser.

Edit: as of mid-year 2015, you should use fastparse instead. It's not only much faster, but also easier to use (especially when building data structures from parsing).

紫南 2024-10-18 03:37:04

你的问题不在于回溯。 scala.util.parsing.combinator 中的标准 | 运算符将进行回溯。你的问题是左递归 (exprcallargssmplargsexpr)。 Packrat 解析确实可能对此有所帮助。

Your problem is not backtracking. The standard | operator in scala.util.parsing.combinator will do backtracking. Your problem is left-recursion (exprcallargssmplargsexpr). Packrat parsing may indeed help with that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文