gpt4 book ai didi

用于递归 bnf 的 Scala Parser Combinators 技巧?

转载 作者:行者123 更新时间:2023-12-04 13:55:22 25 4
gpt4 key购买 nike

我试图匹配这个语法:

pgm ::= exprs
exprs ::= expr [; exprs]
expr ::= ID | expr . [0-9]+

我的 Scala Packrat 解析器组合器如下所示:
import scala.util.parsing.combinator.PackratParsers
import scala.util.parsing.combinator.syntactical._

object Dotter extends StandardTokenParsers with PackratParsers {
lexical.delimiters ++= List(".",";")
def pgm = repsep(expr,";")
def expr :Parser[Any]= ident | expr~"."~num
def num = numericLit

def parse(input: String) =
phrase(pgm)(new PackratReader(new lexical.Scanner(input))) match {
case Success(result, _) => println("Success!"); Some(result)
case n @ _ => println(n);println("bla"); None
}

def main(args: Array[String]) {
val prg = "x.1.2.3;" +
"y.4.1.1;" +
"z;" +
"n.1.10.30"


parse(prg);
}
}

但这不起作用。要么“匹配贪婪”并告诉我:
[1.2] failure: end of input expected 
x.1.2.3;y.4.1.1;z;n.1.10.30

或者如果我更改 ||||我得到一个堆栈溢出:
Exception in thread "main" java.lang.StackOverflowError
at java.lang.Character.isLetter(Unknown Source)
at java.lang.Character.isLetter(Unknown Source)
at scala.util.parsing.combinator.lexical.Lexical$$anonfun$letter$1.apply(Lexical.scala:32)
at scala.util.parsing.combinator.lexical.Lexical$$anonfun$letter$1.apply(Lexical.scala:32)
...

我有点明白为什么我会收到错误;我该怎么做才能解析像上面这样的语法?对我来说似乎并不深奥

编辑:
基于 http://scala-programming-language.1934581.n4.nabble.com/Packrat-parser-guidance-td1956908.html 中引用的论文
我发现我的程序实际上并没有使用新的 Packrat 解析器。

IE。改 Parser[Any]PackratParser[Any]并使用 lazy val而不是 def
我将上面的内容改写为:
import scala.util.parsing.combinator.PackratParsers
import scala.util.parsing.combinator.syntactical._

object Dotter extends StandardTokenParsers with PackratParsers {
lexical.delimiters ++= List(".",";")
lazy val pgm : PackratParser[Any] = repsep(expr,";")
lazy val expr :PackratParser[Any]= expr~"."~num | ident
lazy val num = numericLit

def parse(input: String) =
phrase(pgm)(new PackratReader(new lexical.Scanner(input))) match {
case Success(result, _) => println("Success!"); Some(result)
case n @ _ => println(n);println("bla"); None
}

def main(args: Array[String]) {
val prg = "x.1.2.3 ;" +
"y.4.1.1;" +
"z;" +
"n.1.10.30"


parse(prg);
}
}

最佳答案

问题是(至少部分)您实际上并没有使用 Packrat 解析器。请参阅 Scala 的文档 PackratParsers特质,它说

Using PackratParsers is very similar to using Parsers:

  • any class/trait that extends Parsers (directly or through a subclass) can mix in PackratParsers. Example: object MyGrammar extends StandardTokenParsers with PackratParsers
  • each grammar production previously declared as a def without formal parameters becomes a lazy val, and its type is changed from Parser[Elem] to PackratParser[Elem]. So, for example, def production: Parser[Int] = {...} becomes lazy val production: PackratParser[Int] = {...}
  • Important: using PackratParsers is not an all or nothing decision. They can be free mixed with regular Parsers in a single grammar.


我对 Scala 2.8 的解析器组合器了解不够,无法完全解决这个问题,但是通过以下修改,我能够解析到分号,这是对您所做的改进的改进。
object Dotter extends StandardTokenParsers with PackratParsers {
lexical.delimiters ++= List(".",";")
lazy val pgm:PackratParser[Any] = repsep(expr,";")
lazy val expr:PackratParser[Any]= ident ||| (expr~"."~numericLit)

def parse(input: String) = phrase(expr)(lex(input)) match {
case Success(result, _) => println("Success!"); Some(result)
case n @ _ => println(n);println("bla"); None
}

def lex(input:String) = new PackratReader(new lexical.Scanner(input))
}

关于用于递归 bnf 的 Scala Parser Combinators 技巧?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3343697/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com