scala 解析器组合器中的回溯?
看来 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您想在 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).
你的问题不在于回溯。
scala.util.parsing.combinator
中的标准|
运算符将进行回溯。你的问题是左递归 (expr
→call
→args
→smplargs
→expr
)。 Packrat 解析确实可能对此有所帮助。Your problem is not backtracking. The standard
|
operator inscala.util.parsing.combinator
will do backtracking. Your problem is left-recursion (expr
→call
→args
→smplargs
→expr
). Packrat parsing may indeed help with that.