我正在使用Scala的解析器组合器编写一个DSL。最近,我将基类从StandardTokenParsers更改为JavaTokenParsers,以利用regex的特性,我认为我需要完成最后一部分的拼图。(见使用scala StandardTokenParser解析分隔的多行字符串)
我要做的是提取一个由一些字符分隔的文本块(本例中为{{和}} )。这个文本块可以跨越多行。到目前为止,我得到的是:
def docBlockRE = regex("""(?s)(?!}}).*""".r)
def docBlock: Parser[DocString] =
"{{" ~> docBlockRE <~ "}}" ^^ { case str => new DocString(str) }}其中DocString是我的DSL中的一个案例类。然而,这是行不通的。如果我按以下方式喂养它,它就会失败:
{{
abc
}}
{{
abc
}}我不知道为什么会失败。如果我在解析器(http://jim-mcbeath.blogspot.com/2011/07/debugging-scala-parser-combinators.html)周围放置了一个Deubg包装器,就会得到以下内容:
docBlock.apply for token
at position 10.2 offset 165 returns [19.1] failure: `}}' expected but end of source found如果我尝试一个带有多行分隔的单个块:
{{
abc
def
}}然后,它也无法用以下方法进行解析:
docBlock.apply for token
at position 10.2 offset 165 returns [16.1] failure: `}}' expected but end of source found如果删除DOTALL指令(?s),那么我可以解析多个单行块(这对我没有多大帮助)。
有没有办法将多行正则表达式与负前瞻相结合?
使用这种方法的另一个问题是,无论我做什么,结束分隔符必须在文本之外的一行上。否则,我会得到与上面看到的错误信息相同的错误信息。这几乎就像我所期望的那样,消极的展望并没有真正发挥作用。
发布于 2014-07-16 03:29:02
在以下方面:
scala> val rr = """(?s).*?(?=}})""".r
rr: scala.util.matching.Regex = (?s).*?(?=}})
scala> object X extends JavaTokenParsers {val r: Parser[String] = rr; val b: Parser[String] = "{{" ~>r<~"}}" ^^ { case s => s } }
defined object X
scala> X.parseAll(X.b, """{{ abc
| def
| }}""")
res15: X.ParseResult[String] =
[3.3] parsed: abc
def更多的是表现出贪婪的不同:
scala> val rr = """(?s)(.*?)(?=}})""".r.unanchored
rr: scala.util.matching.UnanchoredRegex = (?s)(.*?)(?=}})
scala> def f(s: String) = s match { case rr(x) => x case _ => "(none)" }
f: (s: String)String
scala> f("something }} }}")
res3: String = "something "
scala> val rr = """(?s)(.*)(?=}})""".r.unanchored
rr: scala.util.matching.UnanchoredRegex = (?s)(.*)(?=}})
scala> def f(s: String) = s match { case rr(x) => x case _ => "(none)" }
f: (s: String)String
scala> f("something }} }}")
res4: String = "something }} "展望只是意味着“确保这跟随我,但不要消耗它。”
消极的展望只是意味着它不会跟随我。
发布于 2014-07-16 02:42:38
https://stackoverflow.com/questions/24771341
复制相似问题