加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala Parser Combinators用于递归bnf?

发布时间:2020-12-16 18:54:43 所属栏目:安全 来源:网络整理
导读:我试图匹配这种语法: pgm ::= exprsexprs ::= expr [; exprs]expr ::= ID | expr . [0-9]+ 我的scala packrat解析器组合器看起来像这样: import scala.util.parsing.combinator.PackratParsersimport scala.util.parsing.combinator.syntactical._object D
我试图匹配这种语法:

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

或者如果我改变了|到|||我得到一个stackoverflow:

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))
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读