This code demonstrate how to use Scala StandardTokenParsers parser and combinators. I would like to narrate my experience in designing an external DSL for a retail application using the parser combinator library of Scala.
Few sample DSLs (simplified for brevity) for accepting promotions defination from the business users to define promotion for SKUs or categories.
As we see list of SKUs or categories and amount of discount varies in these promotion definitions. So it good idea to make few promotion templates and keep SKU List, Category list and amount of discount as variable, so that user should supply these variable values to define multiple promotions. This will have following benefits:
- This will allow to parse AST tree at once and eval at runt time based on defined various promotions.
- This will also allow us to define user interface effectively to define such promotions.
The grammar of lexical parser can be extend further to accommodate various other keywords and functions. The current retail promotion grammar supports following keywords: "Promotion", "for", "Sku", "Category", "discount", "percentage", "Var"
The current project has following scala trait or classes:
- PromoFunctions - List of Promotion functions defined based on the promotion object modeling.
- RetailPromotionParser - Retail promotion parser to build AST Tree
- RetailPromotionEval - Evaluate AST tree at run time based on run time context.
Few examples:
- The AST tree for “Promotion for Sku(Var(offer_skulist1),Var(offer_skulist2)),Category(Var(offer_catlist)) discount Var(x_percetage) percentage” will be “PromotionTemplate(List(Rule(SKU,InputList(List(Var(offer_skulist1), Var(offer_skulist2)))), Rule(CATEGORY,InputList(List(Var(offer_catlist1))))),Promo(Var(x_percetage)))”
- The AST tree for “Promotion for Sku(33333,4444,'ssss'),Category(Var(offer_catlist)) discount Var(x_percetage) percentage” will be “PromotionTemplate(List(Rule(SKU,InputList(List(33333, 4444, ssss))), Rule(CATEGORY,InputList(List(Var(offer_catlist1))))),Promo(Var(x_percetage)))”
Any node which is type of Var, means this node require run time value. PromotionTemplate indicates It is promotion template.
The RetailPromotionEval will able to create a new Promotion based on run time dynamic value. For example for above templates if we have following run time values:
- ("offer_skulist1", List("123", "456"))
- ("offer_skulist2", List("789", "123"))
- ("offer_catlist1", List("abc", "xyz"))
- ("x_percetage",List("10"))
Template | Promotion |
---|---|
PromotionTemplate(List(Rule(SKU,InputList(List(Var(offer_skulist1), Var(offer_skulist2)))), Rule(CATEGORY,InputList(List(Var(offer_catlist1))))),Promo(Var(x_percetage))) | Promotion(List(Rule(SKU,InputList(List(123, 456, 789, 123))), Rule(CATEGORY,InputList(List(abc, xyz)))),Promo(10)) |
PromotionTemplate(List(Rule(SKU,InputList(List(33333, 4444, ssss))), Rule(CATEGORY,InputList(List(Var(offer_catlist1))))),Promo(Var(x_percetage))) | Promotion(List(Rule(SKU,InputList(List(33333, 4444, ssss))), Rule(CATEGORY,InputList(List(abc, xyz)))),Promo(10)) |
This is one of the sample for Retail DSL, this can extend for retail orders, retail loyalty offers, etc.