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

scala – 为什么这组解析器组合器溢出堆栈?

发布时间:2020-12-16 08:46:41 所属栏目:安全 来源:网络整理
导读:TL; DR 我的EBNF语法规范的解析器组合器溢出了堆栈.为什么?我如何解决它? 背景 我试图通过scala库中的组合器为EBNF syntax定义一个解析器.实际上,代码构建了一个语法的AST,但我已经剥离了这些位并内联了一个实用方法来生成一个MVCE(下面). 问题 写入的代码
TL; DR

我的EBNF语法规范的解析器组合器溢出了堆栈.为什么?我如何解决它?

背景

我试图通过scala库中的组合器为EBNF syntax定义一个解析器.实际上,代码构建了一个语法的AST,但我已经剥离了这些位并内联了一个实用方法来生成一个MVCE(下面).

问题

写入的代码在运行时会产生堆栈溢出(也在下面).我无法理解的是它似乎在解析的跳过空白部分溢出.我该如何解决这个错误?如果不能解析EBNF语法真的很不幸 – 我打算为它开发一些工具.

MVCE

package org.benknoble.ebnf

import scala.util.parsing.combinator._

class EbnfParserSimple extends RegexParsers {

  def nonterminal: Parser[String] = """<[^>]+>""".r

  def goesTo: Parser[String] = """::="""

  def epsilon: Parser[String] = "ε"

  def terminal: Parser[String] = ""[^"]+"".r

  def sequence: Parser[String] =
    exp ~ exp ^^ { case left ~ right => left + right }

  def alternation: Parser[String] =
    exp ~ "|" ~ exp ^^ { case left ~ _ ~ right => left + "|" + right }

  def opt: Parser[String] =
    "[" ~ exp ~ "]" ^^ { case lb ~ e ~ rb => lb + e + rb }

  def repetition: Parser[String] =
    "{" ~ exp ~ "}" ^^ { case lb ~ e ~ rb => lb + e + rb }

  def group: Parser[String] =
    "(" ~ exp ~ ")" ^^ { case lb ~ e ~ rb => lb + e + rb }

  def exp: Parser[String] =
    (epsilon
      | terminal
      | nonterminal
      | sequence
      | alternation
      | opt
      | repetition
      | group)

  def rule: Parser[String] = nonterminal ~ goesTo ~ exp ~ ";" ^^ {
    case nt ~ delim ~ e ~ semi => nt + delim + e + semi
  }

  def join[A](sep: String,list: Seq[A]): String = list match {
    case h :: t => h.toString() + t.foldLeft("")(_.toString() + sep + _.toString())
    case Nil => ""
  }

  def root: Parser[String] = phrase(
    rep(rule) ^^ {
      case rules =>
        val joined = join(" ;n",rules)
        if (joined.isEmpty)
          joined
        else
          joined + " ;"
    }
  )

}

object Main extends App {
  val parser = new EbnfParserSimple()
  val grammar = """<A> ::= ["a"|ε]"c" ; """
// <B> ::= <A>"b" ;
// <C> ::= {<B>}"$" ;
// <D> ::= "a""b""d" ;
// <E> ::= ("a"|"b")"c" ;
// """
  val rule = parser.root
  println(parser.parse(rule,grammar))
}

错误跟踪

完整日志可以在as a Gist找到.

[info] Loading project definition from /Users/Knoble/loner/project
[info] Loading settings for project root from build.sbt ...
[info] Set current project to loner (in build file:/Users/Knoble/loner/)
[info] Set current project to ebnf (in build file:/Users/Knoble/loner/)
[info] Running org.benknoble.ebnf.Main 
[error] (run-main-0) java.lang.StackOverflowError
[error] java.lang.StackOverflowError
[error]     at java.util.regex.Pattern.compile(Pattern.java:1673)
[error]     at java.util.regex.Pattern.<init>(Pattern.java:1351)
[error]     at java.util.regex.Pattern.compile(Pattern.java:1028)
[error]     at scala.util.matching.Regex.<init>(Regex.scala:226)
[error]     at scala.collection.immutable.StringLike.r(StringLike.scala:284)
[error]     at scala.collection.immutable.StringLike.r$(StringLike.scala:284)
[error]     at scala.collection.immutable.StringOps.r(StringOps.scala:33)
[error]     at scala.collection.immutable.StringLike.r(StringLike.scala:273)
[error]     at scala.collection.immutable.StringLike.r$(StringLike.scala:273)
[error]     at scala.collection.immutable.StringOps.r(StringOps.scala:33)
[error]     at org.benknoble.ebnf.EbnfParserSimple.terminal(EbnfParser_strings.scala:13)
[error]     at org.benknoble.ebnf.EbnfParserSimple.$anonfun$exp$1(EbnfParser_strings.scala:32)
[error]     at scala.util.parsing.combinator.Parsers$Parser.p$lzycompute$1(Parsers.scala:253)
[error]     at scala.util.parsing.combinator.Parsers$Parser.p$4(Parsers.scala:253)
[error]     at scala.util.parsing.combinator.Parsers$Parser.$anonfun$append$2(Parsers.scala:254)
[error]     at scala.util.parsing.combinator.Parsers$Failure.append(Parsers.scala:202)
[error]     at scala.util.parsing.combinator.Parsers$Parser.$anonfun$append$1(Parsers.scala:254)
[error]     at scala.util.parsing.combinator.Parsers$$anon$3.apply(Parsers.scala:222)
[error]     at scala.util.parsing.combinator.Parsers$Parser.$anonfun$append$1(Parsers.scala:254)
[...]
[error]     at scala.util.parsing.combinator.Parsers$$anon$3.apply(Parsers.scala:222)
[error]     at scala.util.parsing.combinator.Parsers$Parser.$anonfun$append$1(Parsers.scala:254)
[error]     at scala.util.parsing.combinator.Parsers$$anon$3.apply(Parsers.scala:222)
[error]     at scala.util.parsing.combinator.Parsers$Parser.$anonfun$append$1(Parsers.scala:254)
[error]     at scala.util.parsing.combinator.Parsers$$anon$3.apply(Parsers.scala:222)
[error]     at scala.util.parsing.combinator.Parsers$Parser.$anonfun$append$1(Parsers.scala:254)
[error]     at scala.util.parsing.combinator.Parsers$$anon$3.apply(Parsers.scala:222)
[error]     at scala.util.parsing.combinator.Parsers$Parser.$anonfun$append$1(Parsers.scala:254)
[error]     at scala.util.parsing.combinator.Parsers$$anon$3.apply(Parsers.scala:222)
[error]     at scala.util.parsing.combinator.Parsers$Parser.$anonfun$flatMap$1(Parsers.scala:239)
[error]     at scala.util.parsing.combinator.Parsers$$anon$3.apply(Parsers.scala:222)
[error] Nonzero exit code: 1
[error] (Compile / run) Nonzero exit code: 1
[error] Total time: 1 s,completed 12 mars 2019 21:11:15

解决方法

我最终通过 techniques found in this answer删除左递归来解决我的问题.下面找到工作代码.

我必须仔细考虑转变:特别是交替. ^^ {_.reduce(_ _)}和序列. ^^ {_.reduce(_ _)} – 将那些转换回AST生成器可能是非平凡的(因为那些只需要左右的构造函数).重复也困扰了我一点,但没有提取帮助函数,这是唯一要做的事情.

package org.benknoble.ebnf

import scala.util.parsing.combinator._

class EbnfParserSimple extends RegexParsers {

  def epsilon: Parser[String] = "ε"

  def terminal: Parser[String] = ""[^"]+"".r

  def nonterminal: Parser[String] = """<[^>]+>""".r

  def opt: Parser[String] =
    "[" ~ exp ~ "]" ^^ { case lb ~ e ~ rb => lb + e + rb }

  def repetition: Parser[String] =
    "{" ~ exp ~ "}" ^^ { case lb ~ e ~ rb => lb + e + rb }

  def group: Parser[String] =
    "(" ~ exp ~ ")" ^^ { case lb ~ e ~ rb => lb + e + rb }

  def alternation: Parser[String] =
    chainl1(epsilon
      | terminal
      | nonterminal
      | opt
      | repetition
      | group,"|" ^^^ { (lb: String,rb: String) => lb + "|" + rb })
  //   exp ~ "|" ~ exp ^^ { case left ~ _ ~ right => left + "|" + right }

  def sequence: Parser[String] =
    alternation.+ ^^ { _.reduce(_ + _) }
    // alternation ~ alternation ^^ { case lb ~ rb => lb + rb }
  //   exp ~ exp ^^ { case left ~ right => left + right }

  def exp: Parser[String] =
    sequence.+ ^^ { _.reduce(_ + _) }

  def goesTo: Parser[String] = """::="""

  def rule: Parser[String] = nonterminal ~ goesTo ~ exp ~ ";" ^^ {
    case nt ~ delim ~ e ~ semi => nt + delim + e + semi
  }

  def join[A](sep: String,grammar))
}

(编辑:李大同)

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

    推荐文章
      热点阅读