user461697
user461697

Reputation:

Custom logic for matching with Scala parser combinators

I'm using Scala parser combinators to write parsers for a DSL for a constraint programming language that I'm working on. One of the things I'd like to be able to parse are expressions of the form:

<resource1> <relationship_name> <resource2>

For example:

Teacher canTeach Class

I'm trying to match this using:

stringLiteral ~ stringLiteral ~ stringLiteral

But what I really want is to be able to match it by looking up if the first and last strings are defined resources and if the middle one is actually a relationship that is in scope.

How can I define a function that allows me to put these conditions on matching and then use it.

Upvotes: 2

Views: 136

Answers (1)

dk14
dk14

Reputation: 22374

There is a difference between grammar and syntax. stringLiteral ~ stringLiteral ~ stringLiteral has no restrictions on what stringLiteral is - even if you add some restriction (like stringLiteral ~ "canTeach" | "canWhatever" ~ stringLiteral)" - it should be known before parser is constructed (not during parsing itself). However, your desirable restriction is seems to be semantical which means that some grammatically correct sentences like "Teacher canTeach Microwave" may not be semantically correct - so this check should be done after parsing. You have AST as parser's output - so you could just validate this AST, something like:

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)))

Upvotes: 2

Related Questions