我正在使用Scala解析器组合器为DSL编写解析器,用于我正在处理的约束编程语言。我希望能够解析的一件事是表达式:
<resource1> <relationship_name> <resource2>
例如:
Teacher canTeach Class
我正在尝试使用以下方式匹配:
stringLiteral ~ stringLiteral ~ stringLiteral
但我真正想要的是能够通过查找第一个和最后一个字符串是否定义资源以及中间字符串实际上是范围内的关系来匹配它。
如何定义一个允许我将这些条件置于匹配然后使用它的函数。
答案 0 :(得分:2)
语法和语法之间存在差异。 stringLiteral ~ stringLiteral ~ stringLiteral
对stringLiteral
的内容没有限制 - 即使你添加了一些限制(如stringLiteral ~ "canTeach" | "canWhatever" ~ stringLiteral
)“ - 在构造解析器之前应该知道它(不是在解析自身时)。但是,你理想的限制似乎是语义,这意味着一些语法正确的句子,如“教师可以教微波”可能在语义上不正确 - 所以这个检查应该在解析之后完成。你有AST作为解析器的输出 - 所以你可以只验证这个AST,如:
case class Knowledge(subject: String, can: Boolean, predicate: String, obj: String)
val knowledges = parse("Teacher can teach Class", "Teacher cannot teach Class")
knowledges.groupBy(x => (x.subject, x.predicate, x.obj)).mapValues(v => if(v.forall(v.head.can == _.can)) Right(v) else Left(v)))