From a575405afdc8943cd537f54515b833e0e3a04338 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Tue, 8 Jul 2014 14:57:01 +0200 Subject: refactoring and sprinkle some syntactic sugar for better test writing --- src/main/scala/spray/boilerplate/Generator.scala | 2 +- .../scala/spray/boilerplate/TemplateParser.scala | 53 ++++++++-------------- .../spray/boilerplate/TemplateParserSpecs.scala | 6 +-- 3 files changed, 22 insertions(+), 39 deletions(-) diff --git a/src/main/scala/spray/boilerplate/Generator.scala b/src/main/scala/spray/boilerplate/Generator.scala index ca0e104..37b91eb 100644 --- a/src/main/scala/spray/boilerplate/Generator.scala +++ b/src/main/scala/spray/boilerplate/Generator.scala @@ -14,7 +14,7 @@ object Generator { def generate(format: TemplateElement)(idx: Int): String = format match { - case Sequence(els) => els.map(e => generate(e)(idx)).mkString + case Sequence(els@_*) => els.map(e => generate(e)(idx)).mkString case Expand(inner, sep) => (1 to idx).map(generate(inner)).mkString(sep) 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 f97a352..d718e1a 100644 --- a/src/main/scala/spray/boilerplate/TemplateParser.scala +++ b/src/main/scala/spray/boilerplate/TemplateParser.scala @@ -9,8 +9,12 @@ package spray.boilerplate import util.parsing.combinator.RegexParsers import java.lang.RuntimeException -sealed trait TemplateElement -case class Sequence(elements: Seq[TemplateElement]) extends TemplateElement +sealed trait TemplateElement { + def ~(next: TemplateElement): TemplateElement = Sequence(this, next) +} +case class Sequence(elements: TemplateElement*) extends TemplateElement { + override def ~(next: TemplateElement): TemplateElement = Sequence(elements :+ next: _*) +} /** A literal string that shouldn't be changed */ case class LiteralString(literal: String) extends TemplateElement /* An offset to be replaced by the current index */ @@ -23,19 +27,17 @@ object TemplateParser extends RegexParsers { type Tokens = TemplateElement override val skipWhitespace = false - def elements: Parser[TemplateElement] = rep1(element) ^^ { - case one :: Nil => one - case several => Sequence(several) - } - + def elements: Parser[TemplateElement] = rep1(element) ^^ maybeSequence def element: Parser[TemplateElement] = offset| literalString | expand - def offset: Parser[Offset] = "[012]".r ^^ (s => Offset(s.toInt)) + def offset: Parser[Offset] = offsetChars ^^ (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) + not("[#" | """#[^\]]*\]""".r | offsetChars) ~> elem("Any character", _ => true) + + def offsetChars = "[012]".r - def escapedLiteralNumber: Parser[Char] = "##" ~> """[012]""".r ^^ (_.head) + def escapedLiteralNumber: Parser[Char] = "##" ~> offsetChars ^^ (_.head) def outsideTemplate: Parser[LiteralString]= """(?s).+?(?=(\[#)|(\z))""".r ^^ (LiteralString(_)) @@ -43,37 +45,18 @@ object TemplateParser extends RegexParsers { case els ~ x ~ sep => Expand(els, sep.getOrElse(", ")) } def outsideElements: Parser[TemplateElement] = - rep1(expand | outsideTemplate) ^^ { - case one :: Nil => one - case several => Sequence(several) - } + rep1(expand | outsideTemplate) ^^ maybeSequence def separatorChars: Parser[Option[String]] = rep("""[^\]]""".r) ^^ (_.reduceLeftOption(_ + _)) + def maybeSequence(els: Seq[TemplateElement]): TemplateElement = els match { + case one :: Nil => one + case several => Sequence(several: _*) + } + def parse(input:String): TemplateElement = phrase(outsideElements)(new scala.util.parsing.input.CharArrayReader(input.toCharArray)) match { case Success(res,_) => res case x:NoSuccess => throw new RuntimeException(x.msg) } } - -object TestParser extends App { - def check(format: String) { - println(TemplateParser.parse(format)) - println("Template:\n"+format+"\n") - println("Generated Code:\n"+Generator.generateFromTemplate(format,5)) - println("-----End-----\n") - } - - check("""This text - |should not be parsed - |Tuple1 - | - [#Tuple1#] - | - |Product 1""".stripMargin) - - check("[#abc ##1 # ++ ]") - check("[#abc Tuple##22 #]") - check("[#abc Tuple1 #]") -} \ No newline at end of file diff --git a/src/test/scala/spray/boilerplate/TemplateParserSpecs.scala b/src/test/scala/spray/boilerplate/TemplateParserSpecs.scala index a0b8603..1e5e844 100644 --- a/src/test/scala/spray/boilerplate/TemplateParserSpecs.scala +++ b/src/test/scala/spray/boilerplate/TemplateParserSpecs.scala @@ -14,13 +14,13 @@ class TemplateParserSpecs extends Specification { } "multiple expansions" in { parse("[#a#]abc[#b#]") === - Sequence(List(Expand(LiteralString("a"), ", "), LiteralString("abc"), Expand(LiteralString("b"), ", "))) + Expand(LiteralString("a"), ", ") ~ LiteralString("abc") ~ Expand(LiteralString("b"), ", ") } "one surrounded expansion" in { - parse("abc[#a#]def") === Sequence(List(LiteralString("abc"), Expand(LiteralString("a"), ", "), LiteralString("def"))) + parse("abc[#a#]def") === LiteralString("abc") ~ Expand(LiteralString("a"), ", ") ~ LiteralString("def") } "an expanded number" in { - parse("[#T1#]") === Expand(Sequence(List(LiteralString("T"), Offset(1))), ", ") + parse("[#T1#]") === Expand(LiteralString("T") ~ Offset(1), ", ") } "a quoted number" in { parse("[#T##1#]") === Expand(LiteralString("T1"), ", ") -- cgit v1.2.3