From 70dcae84ee17025cb7ca4d1c0167edf5cd4eeb12 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Fri, 5 Aug 2011 21:59:49 -0400 Subject: [PATCH] preserve key+configuration ambiguity through task+extra parsing. fixes #135 --- main/Act.scala | 23 ++++++++++++++--------- util/complete/Parser.scala | 1 + 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/main/Act.scala b/main/Act.scala index 9f042b2d5..7ddb8fcb9 100644 --- a/main/Act.scala +++ b/main/Act.scala @@ -21,11 +21,14 @@ object Act for { proj <- optProjectRef(index, current) confAmb <- config( index configs proj ) - keyConf <- key(index, proj, configs(confAmb, defaultConfigs, proj), keyMap) - taskExtra <- taskExtrasParser(index.tasks(proj, keyConf._2, keyConf._1.label), keyMap, IMap.empty) } - yield { - val (key, conf) = keyConf - val (task, extra) = taskExtra + keyConfs <- key(index, proj, configs(confAmb, defaultConfigs, proj), keyMap) + keyConfTaskExtra <- { + val andTaskExtra = (key: AttributeKey[_], conf: Option[String]) => + taskExtrasParser(index.tasks(proj, conf, key.label), keyMap, IMap.empty) map { case (task, extra) => (key, conf, task, extra) } + oneOf(keyConfs map { _ flatMap andTaskExtra.tupled }) + } + } yield { + val (key, conf, task, extra) = keyConfTaskExtra ScopedKey( Scope( toAxis(proj, Global), toAxis(conf map ConfigKey.apply, Global), task, extra), key ) } } @@ -52,13 +55,15 @@ object Act case Some(_) => explicit :: Nil } - def key(index: KeyIndex, proj: Option[ResolvedReference], confs: Seq[Option[String]], keyMap: Map[String,AttributeKey[_]]): Parser[(AttributeKey[_], Option[String])] = + def key(index: KeyIndex, proj: Option[ResolvedReference], confs: Seq[Option[String]], keyMap: Map[String,AttributeKey[_]]): Parser[Seq[Parser[(AttributeKey[_], Option[String])]]] = { val confMap = confs map { conf => (conf, index.keys(proj, conf)) } toMap; val allKeys = (Set.empty[String] /: confMap.values)(_ ++ _) - token(ID !!! "Expected key" examples allKeys).flatMap { keyString => - val conf = confs.flatMap { conf => if(confMap(conf) contains keyString) conf :: Nil else Nil } headOption; - getKey(keyMap, keyString, k => (k, conf flatMap idFun)) + token(ID !!! "Expected key" examples allKeys).map { keyString => + val valid = confs.filter{ conf => confMap(conf) contains keyString } + def get(conf: Option[String]) = getKey(keyMap, keyString, k => (k, conf)) + val parsers = valid map { conf => getKey(keyMap, keyString, k => (k, conf)) } + if(parsers.isEmpty) get(None) :: Nil else parsers } } def getKey[T](keyMap: Map[String,AttributeKey[_]], keyString: String, f: AttributeKey[_] => T): Parser[T] = diff --git a/util/complete/Parser.scala b/util/complete/Parser.scala index f2545ebe4..a532af46a 100644 --- a/util/complete/Parser.scala +++ b/util/complete/Parser.scala @@ -346,6 +346,7 @@ trait ParserMain def not(p: Parser[_]): Parser[Unit] = new Not(p) + def oneOf[T](p: Seq[Parser[T]]): Parser[T] = p.reduceLeft(_ | _) def seq[T](p: Seq[Parser[T]]): Parser[Seq[T]] = seq0(p, Nil) def seq0[T](p: Seq[Parser[T]], errors: => Seq[String]): Parser[Seq[T]] = {