From 5f2a8a060191f839a7e632d23344a4337e80e877 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Tue, 8 Jul 2014 14:51:25 +0200 Subject: saner parser and generation model --- src/main/scala/spray/boilerplate/Generator.scala | 16 ++-------------- .../scala/spray/boilerplate/TemplateParser.scala | 20 ++++++++++---------- .../spray/boilerplate/TemplateParserSpecs.scala | 12 +++++++++--- 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)(? 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"), ", ") } } } -- cgit v1.2.3