我有一个支持某种自定义语言的库。解析器是使用 scala RegexParsers 编写的。现在我正在尝试使用 fastparse 库重写我们的解析器来加速我们的引擎。问题是:是否可以在我们的伪语言函数中正确解析参数?
这是一个例子:
$out <= doSomething('/mypath[text() != '']', 'def f(a) {a * 2}', ',') <= $in
这是一个带有 3 个参数的函数 doSomething:
- /mypath[text() != '']
- def f(a) {a * 2}
- ,
我期望用参数得到一个函数树:
Function(
name = doSomething
params = List[String](
"/mypath[text() != '']",
"def f(a) {a * 2}",
","
)
)
我所做的:
val ws = P(CharsWhileIn(" \r\n"))
def wsSep(sep: String) = P(ws.? ~ sep ~ ws.?)
val name = P(CharsIn('a' to 'z', 'A' to 'Z'))
val param = P(ws.? ~ "'" ~ CharPred(_ != '\'').rep ~ "'" ~ ws.?)
val params = P("(" ~ param.!.rep(sep = wsSep(",")) ~ ")")
val function = P(name.! ~ params.?).map(case (name, params) => Function(name, params.getOrElse(List())))
这里的问题是单引号在我的代码中表示一个字符串,但在该字符串中有时我们有额外的单引号,如下所示:
/mypath[文本() != '' ]
所以,在我的情况下,我不能使用CharPred(_ != '\'')
我们在字符串中也有一个逗号,就像在第三个参数中一样
这是使用 scala 解析器以某种方式工作,但我无法使用 fastparse 解析相同
有谁知道如何使解析器正常工作?
更新
知道了!主要的魔法在val param
object X {
import fastparse.all._
case class Fn(name: String, params: Seq[String])
val ws = P(CharsWhileIn(" \r\n"))
def wsSep(sep: String) = P(ws.? ~ sep ~ ws.?)
val name = P(CharIn('a' to 'z', 'A' to 'Z').rep)
val param = P(ws.? ~ "'" ~ (!("'" ~ ws.? ~ ("," | ")")) ~ AnyChar).rep ~ "'" ~ ws.?)
val params = P("(" ~ param.!.rep(sep = wsSep(",")) ~ ")")
val function = P(name.! ~ params.?).map{case (name, params) => Fn(name, params.getOrElse(Seq()))}
}
object Test extends App {
val res = X.function.parse("myFunction('/hello[name != '']' , 'def f(a) {mytest}', ',')")
res match {
case Success(r, z) =>
println(s"fn name: ${r.name}")
println(s"params:\n {${r.params.mkString("\n")}\n}")
case Failure(e, z, m) => println(m)
}
}
出去:
name: myFunction
params:
'/hello[name != '']'
'def f(a) {mytest}'
','