Skip to content
This repository has been archived by the owner on Dec 6, 2022. It is now read-only.

Commit

Permalink
grammar completed with proper tests
Browse files Browse the repository at this point in the history
  • Loading branch information
TizianoPerrucci committed Jan 20, 2012
1 parent 22d10f9 commit f4c934e
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 50 deletions.
44 changes: 27 additions & 17 deletions src/main/scala/nl/mac/dsl/DrinkingGrammar.scala
Expand Up @@ -12,8 +12,7 @@ import nl.mac.model.BodyWeights._

class DrinkingGrammar extends JavaTokenParsers with PackratParsers {

//TODO give a better name
lazy val expectedReaction: PackratParser[ExpectedReaction] = state ~ reaction ^^ {case s ~ r => ExpectedReaction(s, r)}
lazy val morningAfterReaction: PackratParser[MorningAfterReaction] = state ~ reaction ^^ {case s ~ r => MorningAfterReaction(s, r)}


lazy val state: PackratParser[DrinkingState] = persona ~ drink ^^ {case p ~ d => DrinkingState(p, d)}
Expand All @@ -23,41 +22,52 @@ class DrinkingGrammar extends JavaTokenParsers with PackratParsers {

lazy val habit: PackratParser[DrinkingHabit] = "I'm" ~> "a" ~> wordLiteral <~ "drinker" ^^ {case h => DrinkingHabits.withName(h)}

//TODO use ^?
lazy val weight: PackratParser[BodyWeight] = "with" ~> "a" ~> wordLiteral <~ "bodyframe" ^^ {case w => BodyWeights.withName(w)}
lazy val weight: PackratParser[BodyWeight] = "with" ~> "a" ~> wordsLiteral ^?(weightExpression, notValidExpression)

def weightExpression: PartialFunction[String, BodyWeight] = {
case "slim bodyframe" => BodyWeights.slim;
case "average bodyframe" => BodyWeights.average;
case "big boned bodyframe" => BodyWeights.bigBoned;
case "heavyweight bodyframe" => BodyWeights.heavy;
}


lazy val drink: PackratParser[Drink] = moderation ~ percentage ^^ {case m ~ p => Drink(m, p)}

lazy val moderation: PackratParser[Moderation] = "when" ~> "I" ~> "drink" ~> "a" ~> wordLiteral <~ "amount" ^^ {case m => Moderations.withName(m)}

//TODO use ^?
lazy val percentage: PackratParser[AlcoholicPercentage] = "of" ~> wordsLiteral ^^ {case p =>
p match {
case "high spirits" => AlcoholicPercentages.spiritHigh
case "low spirits" => AlcoholicPercentages.spiritLow
}
lazy val percentage: PackratParser[AlcoholicPercentage] = "of" ~> wordsLiteral ^?(percentageExpressions, notValidExpression)

def percentageExpressions: PartialFunction[String, AlcoholicPercentage] = {
case "beers" => AlcoholicPercentages.beerLow;
case "heavy beers" => AlcoholicPercentages.beerHigh;
case "glasses of wine" => AlcoholicPercentages.wine;
case "spirits" => AlcoholicPercentages.spiritLow;
case "high spirits" => AlcoholicPercentages.spiritHigh;
}

//TODO give a better name
//TODO give error function for better validation ...
lazy val reaction: PackratParser[BodyReaction] = "my" ~> "reaction" ~> "is" ~> "expected" ~> "to" ~> "be" ~> wordsLiteral ^?(reactionExpression, reactionNotValid)

lazy val reaction: PackratParser[BodyReaction] = "my" ~> "reaction" ~> "is" ~> "expected" ~> "to" ~> "be" ~> wordsLiteral ^?(reactionExpressions, notValidExpression)

def reactionExpression: PartialFunction[String, BodyReaction] = {
def reactionExpressions: PartialFunction[String, BodyReaction] = {
case "as slow as molasses in January" => BodyReactions.slow;
case "ready steady" => BodyReactions.ready;
case "quick and dirty" => BodyReactions.quick;
case "grease lightning!" => BodyReactions.fast;
}

def reactionNotValid(exp: String): String = {
"Expression '" + exp + "' IS NOT VALID!"

def notValidExpression(exp: String): String = {
"Expression '" + exp + "' IS NOT VALID! (talk with your tester ;))"
}


//// additional parsers

def wordsLiteral: Parser[String] = """[\p{Blank}?\w-\d]*""".r

//matches one word/token
def wordLiteral: Parser[String] = """[\w-\d]*""".r

//matches more that one word/token
def wordsLiteral: Parser[String] = """[\p{Blank}?\w-\d]*""".r
}
21 changes: 13 additions & 8 deletions src/main/scala/nl/mac/dsl/DrinkingModel.scala
@@ -1,5 +1,7 @@
package nl.mac.model

//Problem Domain

object DrinkingHabits extends Enumeration {
type DrinkingHabit = Value
val heavy = Value(1)
Expand All @@ -11,9 +13,7 @@ object DrinkingHabits extends Enumeration {
object BodyWeights extends Enumeration {
type BodyWeight = Value
val heavy = Value(1)
//TODO change
//val bigBoned = Value(2)
val big = Value(2)
val bigBoned = Value(2)
val average = Value(3)
val slim = Value(4)
}
Expand All @@ -40,6 +40,8 @@ import nl.mac.model.AlcoholicPercentages._
import nl.mac.model.Moderations._


//Solution Domain

object BodyReactions extends Enumeration {
type BodyReaction = Value
val slow = Value(1)
Expand All @@ -51,13 +53,16 @@ object BodyReactions extends Enumeration {
import nl.mac.model.BodyReactions._


sealed trait DomainElement
sealed trait DomainObject


case class ExpectedReaction(state: DrinkingState, reaction: BodyReaction) extends DomainElement
//This represents the mapping between problem domain and solution domain
//the abstraction is thought in terms of the solution domain
case class MorningAfterReaction(state: DrinkingState, reaction: BodyReaction) extends DomainObject


case class DrinkingState(persona: Persona, drink: Drink) extends DomainElement
case class DrinkingState(persona: Persona, drink: Drink) extends DomainObject

case class Persona(habits: DrinkingHabit, weight: BodyWeight) extends DomainElement
case class Persona(habits: DrinkingHabit, weight: BodyWeight) extends DomainObject

case class Drink(moderation: Moderation, percentage: AlcoholicPercentage) extends DomainElement
case class Drink(moderation: Moderation, percentage: AlcoholicPercentage) extends DomainObject
49 changes: 24 additions & 25 deletions src/test/scala/nl/mac/dsl/DrinkingGrammarTest.scala
Expand Up @@ -5,43 +5,42 @@ import nl.mac.model._

class DrinkingGrammarTest extends SpecificationWithJUnit {

"parse valid accommodation" in {

val input =
"should be a valid sentence" in {
val sentence =
"""
I'm a social drinker with a big bodyframe
I'm a easy drinker with a slim bodyframe
when I drink a countless amount of high spirits
my reaction is expected to be as slow as molasses in Januar
my reaction is expected to be as slow as molasses in January
"""

val result = ExpectedReaction(
DrinkingState(
Persona(DrinkingHabits.social, BodyWeights.big),
Drink(Moderations.countless, AlcoholicPercentages.spiritHigh)
),
val expectedModel = MorningAfterReaction(
DrinkingState(Persona(DrinkingHabits.easy, BodyWeights.slim),Drink(Moderations.countless, AlcoholicPercentages.spiritHigh)),
BodyReactions.slow
)

val p = new DrinkingGrammar
p.parseAll(p.expectedReaction, input) match {
case p.Success(expectedReaction, _) =>
println(expectedReaction.toString)
p.parseAll(p.morningAfterReaction, sentence) match {
case p.Success(morningAfterReaction, _) =>
println(morningAfterReaction.toString)
morningAfterReaction mustEqual expectedModel

case x => fail(x.toString)
}
}

"shouldn't be a valid sentence" in {
val sentence =
"""
I'm a social drinker with a big boned bodyframe
when I drink a countless amount of high spirits
my reaction is expected to be cool
"""

/*
anvrPackage.accommodation.name mustEqual expectedPackage.accommodation.name
anvrPackage.accommodation.units.length mustEqual expectedPackage.accommodation.units.length
anvrPackage.transport.to.head.fromTime mustEqual expectedPackage.transport.to.head.fromTime
anvrPackage.transport.to.head.toTime mustEqual expectedPackage.transport.to.head.toTime
anvrPackage.transport.to.head.number mustEqual expectedPackage.transport.to.head.number
anvrPackage.transport.to.head.classes(0).price mustEqual expectedPackage.transport.to.head.classes(0).price
assert(anvrPackage.transport.to.head.classes(0).priceNote == null)
anvrPackage.transport.to.head.classes(1).price mustEqual expectedPackage.transport.to.head.classes(1).price
anvrPackage.transport.to.head.classes(1).priceNote mustEqual expectedPackage.transport.to.head.classes(1).priceNote
*/
val p = new DrinkingGrammar
p.parseAll(p.morningAfterReaction, sentence) match {
case p.Success(morningAfterReaction, _) => fail("why this sentence is valid?")

case x => fail(x.toString)
case p.Failure(msg, _) => msg mustMatch ".*NOT VALID.*"
}
}
}

0 comments on commit f4c934e

Please sign in to comment.