aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Rudolph <johannes.rudolph@gmail.com>2014-07-08 14:51:25 +0200
committerJohannes Rudolph <johannes.rudolph@gmail.com>2014-07-08 14:51:25 +0200
commit5f2a8a060191f839a7e632d23344a4337e80e877 (patch)
treedeb55ff5176312da51c55089390f9816c8978c4f
parent6a0844a9be28ab845272cf194773bf6a2b99c552 (diff)
downloadsbt-boilerplate-5f2a8a060191f839a7e632d23344a4337e80e877.tar.gz
sbt-boilerplate-5f2a8a060191f839a7e632d23344a4337e80e877.tar.bz2
sbt-boilerplate-5f2a8a060191f839a7e632d23344a4337e80e877.zip
saner parser and generation model
-rw-r--r--src/main/scala/spray/boilerplate/Generator.scala16
-rw-r--r--src/main/scala/spray/boilerplate/TemplateParser.scala20
-rw-r--r--src/test/scala/spray/boilerplate/TemplateParserSpecs.scala12
3 files changed, 21 insertions, 27 deletions
diff --git a/src/main/scala/spray/boilerplate/Generator.scala b/src/main/scala/spray/boilerplate/Generator.scala
index 0dc79ec..ca0e104 100644
--- a/src/main/scala/spray/boilerplate/Generator.scala
+++ b/src/main/scala/spray/boilerplate/Generator.scala
@@ -12,23 +12,11 @@ object Generator {
def generateFromTemplate(template: String, expandTo: Int): String =
generate(TemplateParser.parse(template))(expandTo)
- def formatNum0(num: Int) = num.formatted("%d")
- def formatNumSpace(num: Int) = num.formatted("%d")
- def replaceInPattern(pattern: String)(idx: Int): String =
- // in likely identifiers replace by '04' etc.
- pattern.replaceAll("(?<=\\w)(?<!\\d)(?<!##)2(?!\\d)", formatNum0(idx + 1))
- .replaceAll("(?<=\\w)(?<!\\d)(?<!##)1(?!\\d)", formatNum0(idx))
- .replaceAll("(?<=\\w)(?<!\\d)(?<!##)0(?!\\d)", formatNum0(idx - 1))
-
- // in other places replace by ' 4' etc.
- .replaceAll("(?<!\\w)(?<!\\d)(?<!##)2(?!\\d)", formatNumSpace(idx + 1))
- .replaceAll("(?<!\\w)(?<!\\d)(?<!##)1(?!\\d)", formatNumSpace(idx))
- .replaceAll("(?<!\\w)(?<!\\d)(?<!##)0(?!\\d)", formatNumSpace(idx - 1))
def generate(format: TemplateElement)(idx: Int): String = format match {
case Sequence(els) => els.map(e => generate(e)(idx)).mkString
case Expand(inner, sep) => (1 to idx).map(generate(inner)).mkString(sep)
- case LiteralString(lit) => replaceInPattern(lit)(idx)
- case FixedString(lit) => lit
+ case Offset(i) => (idx + i - 1).toString
+ case LiteralString(lit) => lit
}
}
diff --git a/src/main/scala/spray/boilerplate/TemplateParser.scala b/src/main/scala/spray/boilerplate/TemplateParser.scala
index 41d971b..f97a352 100644
--- a/src/main/scala/spray/boilerplate/TemplateParser.scala
+++ b/src/main/scala/spray/boilerplate/TemplateParser.scala
@@ -11,10 +11,10 @@ import java.lang.RuntimeException
sealed trait TemplateElement
case class Sequence(elements: Seq[TemplateElement]) extends TemplateElement
-/** A string possibly containing patterns to replace */
+/** A literal string that shouldn't be changed */
case class LiteralString(literal: String) extends TemplateElement
-/** A fixed string that shouldn't be changed */
-case class FixedString(literal: String) extends TemplateElement
+/* An offset to be replaced by the current index */
+case class Offset(i: Int) extends TemplateElement
/** A region in which to apply expansions */
case class Expand(inner: TemplateElement, separator: String) extends TemplateElement
@@ -28,16 +28,16 @@ object TemplateParser extends RegexParsers {
case several => Sequence(several)
}
- def element: Parser[TemplateElement] = literal | fixed | expand
+ def element: Parser[TemplateElement] = offset| literalString | expand
- def literalChar: Parser[String] = """(?s:(?!\[#)(?!#[^\]]*\]).)""".r
- def literalChars: Parser[String] = rep1(literalChar) ^^ { _.reduceLeft(_ + _) }
+ def offset: Parser[Offset] = "[012]".r ^^ (s => Offset(s.toInt))
+ def literalString: Parser[LiteralString] = rep1(escapedLiteralNumber | literalChar) ^^ (chs => LiteralString(chs.mkString))
+ def literalChar: Parser[Char] =
+ not("[#" | """#[^\]]*\]""".r | "[012]".r) ~> elem("Any character", _ => true)
- def literal: Parser[LiteralString] = literalChars ^^ LiteralString
+ def escapedLiteralNumber: Parser[Char] = "##" ~> """[012]""".r ^^ (_.head)
- def fixed: Parser[FixedString] = "##" ~> """\d+""".r ^^ (new String(_)) ^^ FixedString
-
- def outsideTemplate: Parser[FixedString]= """(?s).+?(?=(\[#)|(\z))""".r ^^ (FixedString(_))
+ def outsideTemplate: Parser[LiteralString]= """(?s).+?(?=(\[#)|(\z))""".r ^^ (LiteralString(_))
def expand: Parser[Expand] = "[#" ~> elements ~ "#" ~ separatorChars <~ "]" ^^ {
case els ~ x ~ sep => Expand(els, sep.getOrElse(", "))
diff --git a/src/test/scala/spray/boilerplate/TemplateParserSpecs.scala b/src/test/scala/spray/boilerplate/TemplateParserSpecs.scala
index a0ff049..a0b8603 100644
--- a/src/test/scala/spray/boilerplate/TemplateParserSpecs.scala
+++ b/src/test/scala/spray/boilerplate/TemplateParserSpecs.scala
@@ -7,17 +7,23 @@ class TemplateParserSpecs extends Specification {
"TemplateParser.parse" should {
"without expansion" in {
- parse("abc") === FixedString("abc")
+ parse("abc") === LiteralString("abc")
}
"just expansion" in {
parse("[# def #]") === Expand(LiteralString(" def "), ", ")
}
"multiple expansions" in {
parse("[#a#]abc[#b#]") ===
- Sequence(List(Expand(LiteralString("a"), ", "), FixedString("abc"), Expand(LiteralString("b"), ", ")))
+ Sequence(List(Expand(LiteralString("a"), ", "), LiteralString("abc"), Expand(LiteralString("b"), ", ")))
}
"one surrounded expansion" in {
- parse("abc[#a#]def") === Sequence(List(FixedString("abc"), Expand(LiteralString("a"), ", "), FixedString("def")))
+ parse("abc[#a#]def") === Sequence(List(LiteralString("abc"), Expand(LiteralString("a"), ", "), LiteralString("def")))
+ }
+ "an expanded number" in {
+ parse("[#T1#]") === Expand(Sequence(List(LiteralString("T"), Offset(1))), ", ")
+ }
+ "a quoted number" in {
+ parse("[#T##1#]") === Expand(LiteralString("T1"), ", ")
}
}
}