- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
开始使用 Scala 解析器组合,在继续之前需要更好地掌握失败/错误处理(注意:仍然会进入 Scala)
想要将“a = b, c = d”等字符串解析为元组列表,但在发现悬空逗号时标记用户。
在匹配逗号分隔的属性赋值时考虑匹配失败(“a = b,”):
def commaList[T](inner: Parser[T]): Parser[List[T]] =
rep1sep(inner, ",") | rep1sep(inner, ",") ~> opt(",") ~> failure("Dangling comma")
def propertyAssignment: Parser[(String, String)] = ident ~ "=" ~ ident ^^ {
case id ~ "=" ~ prop => (id, prop)
}
并调用解析器:
p.parseAll(p.commaList(p.propertyAssignment), "name = John , ")
这会导致失败,这并不奇怪,但是:
string matching regex `\p{javaJavaIdentifierStart}\p{javaJavaIdentifierPart}*' expected but end of source found
commList 函数在第一个属性分配上成功,并开始重复给定的逗号,但下一个“ident”失败,因为下一个字符是源数据的末尾。我想我可以发现 commList 中的第二个选择会匹配:
rep1sep(inner, ",") ~> opt(",") ~> failure("Dangling comma")
尼克斯。有想法吗?
最佳答案
斯卡拉兹来救援:-)
当您处理警告时,因失败而退出解析器并不是一个好主意。您可以轻松地将解析器与 Scalaz writer monad 结合起来。使用此 monad,您可以在解析器运行期间将消息添加到部分结果。这些消息可能是信息、警告或错误。解析器完成后,您可以验证结果是否可以使用或者是否包含关键问题。通过这样一个单独的验证器步骤,您通常会得到更好的错误消息。例如,您可以在字符串末尾接受任意字符,但在找到它们时发出错误(例如“最后一条语句后发现垃圾”)。对于用户来说,该错误消息比您在下面的示例中获得的神秘默认消息(“字符串匹配正则表达式‘\z’预期 [...]”)更有帮助。
以下是基于您问题中的代码的示例:
scala> :paste
// Entering paste mode (ctrl-D to finish)
import util.parsing.combinator.RegexParsers
import scalaz._, Scalaz._
object DemoParser extends RegexParsers {
type Warning = String
case class Equation(left : String, right : String)
type PWriter = Writer[Vector[Warning], List[Equation]]
val emptyList : List[Equation] = Nil
def rep1sep2[T](p : => Parser[T], q : => Parser[Any]): Parser[List[T]] =
p ~ rep(q ~> p) ^^ {case x~y => x::y}
def name : Parser[String] = """\w+""".r
def equation : Parser[Equation] = name ~ "=" ~ name ^^ { case n ~ _ ~ v => Equation(n,v) }
def commaList : Parser[PWriter] = rep1sep(equation, ",") ^^ (_.set(Vector()))
def danglingComma : Parser[PWriter] = opt(",") ^^ (
_ map (_ => emptyList.set(Vector("Warning: Dangling comma")))
getOrElse(emptyList.set(Vector("getOrElse(emptyList.set(Vector(""))))
def danglingList : Parser[PWriter] = commaList ~ danglingComma ^^ {
case l1 ~ l2 => (l1.over ++ l2.over).set(l1.written ++ l2.written) }
def apply(input: String): PWriter = parseAll(danglingList, input) match {
case Success(result, _) => result
case failure : NoSuccess => emptyList.set(Vector(failure.msg))
}
}
// Exiting paste mode, now interpreting.
import util.parsing.combinator.RegexParsers
import scalaz._
import Scalaz._
defined module DemoParser
scala> DemoParser("a=1, b=2")
res2: DemoParser.PWriter = (Vector(),List(Equation(a,1), Equation(b,2)))
scala> DemoParser("a=1, b=2,")
res3: DemoParser.PWriter = (Vector(Warning: Dangling comma),List(Equation(a,1), Equation(b,2)))
scala> DemoParser("a=1, b=2, ")
res4: DemoParser.PWriter = (Vector(Warning: Dangling comma),List(Equation(a,1), Equation(b,2)))
scala> DemoParser("a=1, b=2, ;")
res5: DemoParser.PWriter = (Vector(string matching regex `\z' expected but `;' found),List())
scala>
如您所见,它可以很好地处理错误情况。如果您想扩展示例,请为不同类型的错误添加案例类,并在消息中包含当前解析器位置。
顺便说一句。空格问题由 RegexParsers 类处理。如果您想更改空白的处理方式,只需覆盖字段 whiteSpace
。
关于parsing - Scala 解析器失败处理、悬空逗号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18250268/
我遵循了 V. Romeo 关于实体管理的教程(在 GitHub 和 Youtube 上)。 然后我尝试重写类 CEntity、CComponent 和测试 CPosition(主要来自 Romeo
为什么下面的代码中有悬空引用?我认为对 const 的引用总是将临时对象的生命周期延长到它们的范围。 boost::filesystem::recursive_directory_iterator i
我有一个多线程应用程序,将传入消息发布到 rabbitmq 交换。使用 rabbitmq java 客户端,我在应用程序启动时创建了一个 rabbitmq 连接,并在我的所有线程中共享它。每个线程都会
我有一个 Git 存储库,其中有大量提交不在特定分支下,我可以 git show 它们,但是当我尝试列出包含它们的分支时,它没有返回任何内容。 我认为这是悬空提交/树问题(由于 -D 分支),所以我修
我是 Linux 的新手,并且继承了保持我们的单一 Linux 服务器运行的职责。这是我们的SVN服务器,所以比较重要。 原来在我之前维护它的人有一个 cron 任务,当有太多 svnserve 进程
我是一名优秀的程序员,十分优秀!