以下のコマンドの文法を定義しようとしています。
object ParserWorkshop {
def main(args: Array[String]) = {
ChoiceParser("todo link todo to database")
ChoiceParser("todo link todo to database deadline: next tuesday context: app.model")
}
}
2 番目のコマンドは、次のようにトークン化する必要があります。
action = todo
message = link todo to database
properties = [deadline: next tuesday, context: app.model]
以下に定義する文法でこの入力を実行すると、次のエラー メッセージが表示されます。
[1.27] parsed: Command(todo,link todo to database,List())
[1.36] failure: string matching regex `\z' expected but `:' found
todo link todo to database deadline: next tuesday context: app.model
^
私が見る限り、メッセージの単語を照合するパターンは、プロパティのキーと値のペアのキーのパターンとほぼ同じであるため、パーサーはメッセージがどこで終了し、プロパティが開始するかを判断できないため、失敗します。次のように、各プロパティに開始トークンを使用することを主張することで、これを解決できます。
todo link todo to database :deadline: next tuesday :context: app.model
しかし、コマンドをできるだけ自然言語に近づけたいと思います。2 つの質問があります。
エラーメッセージは実際にはどういう意味ですか? また、指定された入力文字列で機能するように既存の文法を変更するにはどうすればよいでしょうか?
import scala.util.parsing.combinator._
case class Command(action: String, message: String, properties: List[Property])
case class Property(name: String, value: String)
object ChoiceParser extends JavaTokenParsers {
def apply(input: String) = println(parseAll(command, input))
def command = action~message~properties ^^ {case a~m~p => new Command(a, m, p)}
def action = ident
def message = """[\w\d\s\.]+""".r
def properties = rep(property)
def property = propertyName~":"~propertyValue ^^ {
case n~":"~v => new Property(n, v)
}
def propertyName: Parser[String] = ident
def propertyValue: Parser[String] = """[\w\d\s\.]+""".r
}