首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >FastParse。如何严格执行一次规则

FastParse。如何严格执行一次规则
EN

Stack Overflow用户
提问于 2016-08-14 22:45:21
回答 1查看 222关注 0票数 2

我正在尝试使用FastParse API实现以下语法。

  1. Expr只能包含Foo、Bar、Baz子表达式。
  2. Expr必须至少包含一个子表达式Foo/Bar/Bar。它不能是空的
  3. Foo/Bar/Baz可以在Expr内的任何顺序中出现。
  4. Foo/Bar/Baz不能重复,因此只能使用一次。

因此,有效表达式是Expr(Baz(10),Foo(10),Bar(10)),无效表达式是Expr()Expr(Bar(10),Bar(10))

到目前为止,我已经编写了这段代码,它可以强制执行和解析1、2、3规则。但事实证明,第4条规则是很棘手的。

代码语言:javascript
复制
import fastparse.noApi._
import fastparse.WhitespaceApi

object FastParsePOC {

   val White = WhitespaceApi.Wrapper{
      import fastparse.all._
      NoTrace(" ".rep)
   }

   def print(input: Parsed[(String, String, Seq[(String, String)])]) : Unit = {
      input match {
         case Parsed.Success(value, index) =>
            println(s"${value._1} ${value._2}")
            value._3.foreach{case (name, index) => println(s"$name $index")}
         case f @ Parsed.Failure(error, line, col) => println(s"Error: $error $line $col ${f.extra.traced.trace}")
      }
   }

   def main(args: Array[String]) : Unit = {
      import White._
      val base = P("(" ~ (!")" ~ AnyChar).rep(1).! ~ ")")
      val foo = P("Foo".! ~ base)
      val bar = P("Bar".! ~ base)
      val baz = P("Baz".! ~ base)
      val foobarbaz = (foo | bar | baz)
      val parser = P("Expr" ~ "(" ~ foobarbaz ~ ",".? ~ (foobarbaz).rep(sep=",") ~ ")")
      val input3 = "Expr(Baz(20),Bar(10),Foo(30))"
      val parsed = parser.parse(input3)
      print(parsed)
   }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-01-13 18:31:43

您可以使用filter调用检查“精确-一次”约束:

代码语言:javascript
复制
test("foo bar baz") {
  val arg: P0 = P("(") ~ (!P(")") ~ AnyChar).rep(1) ~ ")"

  val subExpr: P[String] = (P("Foo") | P("Bar") | P("Baz")).! ~ arg

  val subExprList: P[Seq[String]] = subExpr.rep(min = 1, sep = P(",")).filter { list =>
    list.groupBy(identity[String]).values.forall(_.length == 1)
  }

  val expr: P[Seq[String]] = P("Expr") ~ "(" ~ subExprList ~ ")"

  expr.parse("Expr(Foo(10))").get.value

  expr.parse("Expr(Foo(10),Bar(20),Baz(30))").get.value

  intercept[Throwable] {
    expr.parse("Expr()").get.value
  }

  intercept[Throwable] {
    expr.parse("Expr(Foo(10),Foo(20))").get.value
  }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38947269

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档