eleks.com
Interpreter Pattern
Design Patterns Program
by Dmytro Verbovyi
Introduction
Given a language, define a
representation for its grammar along
with an interpreter that uses the
representation to interpret sentences
in the language. (GOF) ***
***The basic idea is to have a class for each
symbol(terminal or nonterminal) in a specialized computer
language.
● Frequent changing task
● Queries, terms and
expression
● Regular expressions
● Sentences in the language
represented as abstract syntax
trees (AST)
● Easy to extend and modify
grammar. (Classes
implementation that describes
abstract syntax nodes easily
coded)
● You can easily change the
method of calculating
expressions
Problem solving
Real world example - Barcode
How Barcode works - BNF notation
● <UPC>::=<Manufacture ID><Item Number><Check Digit>
● <Manufacture Id>::=<Digit><Digit><Digit><Digit><Digit><Digit>
● <Item Number>::=<Digit><Digit><Digit><Digit><Digit>
● <Check Digit>::=<Digit>
● <Digit>::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
Scheme
Implemented example - BNF
● <TRAILER>::=<Goods><sPackage><Goods><bPackage><Goods><Goods>
● <sPackage>::=<Goods><Goods>
● <bPackage>::=<Goods><Goods><Goods><Goods>
● <Goods>::= <Table> | <Bed> | <TV> | <LapTop>
Language sentence
<script type="text/template" id="contextTpl">
<h1>{Table}{SPackage}{Bed}{BPackage}{TV}{LapTop}</h1>
</script>
Abstract Expression
//Abstract Expression
class Goods {
constructor(){
this.name = this.__proto__.constructor.name;
}
interpret(context) {
return this.name + ': ' + context.getPrice(this.name) + '<br>';
}
}
Terminal Expressions
//Terminal Expressions
class TV extends Goods {}
class LapTop extends Goods {}
class Table extends Goods {}
class Bed extends Goods {}
Nonterminal Expressions
//Non-Terminal Expresions
class SPackage extends Goods {
constructor() {
super();
this.itemsList = [].slice.call(arguments);
}
add(item) {
this.itemsList.push(item);
}
interpret(context) {
let output = '';
this.itemsList.forEach((exp)=> {
output += exp.interpret(context);
});
return output;
}
}
class BPackage extends SPackage {}
Context
class PriceContext {
constructor(bed, table, tv, laptop, sPackage, bPackage) {
this.bed = bed;
this.table = table;
this.tv = tv;
this.laptop = laptop;
this.spackage = sPackage;
this.bpackage = bPackage;
this.prices = {};
}
setPrice(prices) {
for(let key in prices) {
if(!prices.hasOwnProperty(key)) continue;
this.prices[key] = prices[key];
}
}
getPrice(name) {
return this.prices[name];
}
interpret(expName){
return
this[expName].interpret(this);
}
}
View - slide 1
class View {
constructor(el, tplId) {
this.el = el;
this._vars = {};
this.setTemplate(tplId);
}
setTemplate(tplId) {
this.template = document.getElementById(tplId).innerHTML.replace(/s/g, '');
}
getVars() {
let regex = /{(.*?)}/g,
matches, expressions = [];
while (matches = regex.exec(this.template)) {
expressions.push(matches[1]);
}
return expressions;
}
View - slide 2
render(priceContext) {
let output = this.template,
vars = this.getVars();
vars.forEach((variable)=> {
let expName = variable.toLowerCase(),
re = new RegExp("{" + variable + "}", 'g');
output = output.replace(re, priceContext.interpret(expName));
});
this.el.innerHTML = output;
return this;
}
}
Usage
const Main = () => {
let el = document.body;
let view = new View(el, 'contextTpl');
let smallPackage = new SPackage();
smallPackage.add(new TV());
smallPackage.add(new LapTop());
let bigPackage = new BPackage();
bigPackage.add(new Table());
bigPackage.add(new Bed());
bigPackage.add(new Bed());
bigPackage.add(new TV());
let priceContext = new PriceContext(
new Bed(),
new Table(),
new TV(),
new LapTop(),
smallPackage,
bigPackage
);
priceContext.setPrice({
'Bed': 400,
'TV': 200,
'LapTop': 500,
'Table': 50
});
view.render(priceContext);
};
Sentence and Output
Table: 50
TV: 200
LapTop: 500
Bed: 400
Table: 50
Bed: 400
Bed: 400
TV: 200
TV: 200
LapTop: 500
<script type="text/template" id="contextTpl">
<h1>{Table}{SPackage}{Bed}{BPackage}{TV}{LapTop}</h1>
</script>
Advantages Disadvantages
● You have a simple
language to interpret
● You can easily change
the method of
calculating expressions
● You can represent
sentences in the
language as abstract
syntax trees (AST).
● Difficult to support the
grammar with a large
number of rules
● Each class on each
expression
Related Patterns
● Composite for same proccessing terminal and non-terminal expressions
● Flyweight for sharing terminal expressions
● Iterator for traversing the nodes of non-terminals
Inspired by Technology.
Driven by Value.
Have a questions?

Interpreter Design Pattern in Javascript

  • 1.
  • 2.
    Introduction Given a language,define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language. (GOF) *** ***The basic idea is to have a class for each symbol(terminal or nonterminal) in a specialized computer language.
  • 3.
    ● Frequent changingtask ● Queries, terms and expression ● Regular expressions
  • 4.
    ● Sentences inthe language represented as abstract syntax trees (AST) ● Easy to extend and modify grammar. (Classes implementation that describes abstract syntax nodes easily coded) ● You can easily change the method of calculating expressions Problem solving
  • 5.
  • 6.
    How Barcode works- BNF notation ● <UPC>::=<Manufacture ID><Item Number><Check Digit> ● <Manufacture Id>::=<Digit><Digit><Digit><Digit><Digit><Digit> ● <Item Number>::=<Digit><Digit><Digit><Digit><Digit> ● <Check Digit>::=<Digit> ● <Digit>::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
  • 7.
  • 8.
    Implemented example -BNF ● <TRAILER>::=<Goods><sPackage><Goods><bPackage><Goods><Goods> ● <sPackage>::=<Goods><Goods> ● <bPackage>::=<Goods><Goods><Goods><Goods> ● <Goods>::= <Table> | <Bed> | <TV> | <LapTop>
  • 9.
    Language sentence <script type="text/template"id="contextTpl"> <h1>{Table}{SPackage}{Bed}{BPackage}{TV}{LapTop}</h1> </script>
  • 10.
    Abstract Expression //Abstract Expression classGoods { constructor(){ this.name = this.__proto__.constructor.name; } interpret(context) { return this.name + ': ' + context.getPrice(this.name) + '<br>'; } }
  • 11.
    Terminal Expressions //Terminal Expressions classTV extends Goods {} class LapTop extends Goods {} class Table extends Goods {} class Bed extends Goods {}
  • 12.
    Nonterminal Expressions //Non-Terminal Expresions classSPackage extends Goods { constructor() { super(); this.itemsList = [].slice.call(arguments); } add(item) { this.itemsList.push(item); } interpret(context) { let output = ''; this.itemsList.forEach((exp)=> { output += exp.interpret(context); }); return output; } } class BPackage extends SPackage {}
  • 13.
    Context class PriceContext { constructor(bed,table, tv, laptop, sPackage, bPackage) { this.bed = bed; this.table = table; this.tv = tv; this.laptop = laptop; this.spackage = sPackage; this.bpackage = bPackage; this.prices = {}; } setPrice(prices) { for(let key in prices) { if(!prices.hasOwnProperty(key)) continue; this.prices[key] = prices[key]; } } getPrice(name) { return this.prices[name]; } interpret(expName){ return this[expName].interpret(this); } }
  • 14.
    View - slide1 class View { constructor(el, tplId) { this.el = el; this._vars = {}; this.setTemplate(tplId); } setTemplate(tplId) { this.template = document.getElementById(tplId).innerHTML.replace(/s/g, ''); } getVars() { let regex = /{(.*?)}/g, matches, expressions = []; while (matches = regex.exec(this.template)) { expressions.push(matches[1]); } return expressions; }
  • 15.
    View - slide2 render(priceContext) { let output = this.template, vars = this.getVars(); vars.forEach((variable)=> { let expName = variable.toLowerCase(), re = new RegExp("{" + variable + "}", 'g'); output = output.replace(re, priceContext.interpret(expName)); }); this.el.innerHTML = output; return this; } }
  • 16.
    Usage const Main =() => { let el = document.body; let view = new View(el, 'contextTpl'); let smallPackage = new SPackage(); smallPackage.add(new TV()); smallPackage.add(new LapTop()); let bigPackage = new BPackage(); bigPackage.add(new Table()); bigPackage.add(new Bed()); bigPackage.add(new Bed()); bigPackage.add(new TV()); let priceContext = new PriceContext( new Bed(), new Table(), new TV(), new LapTop(), smallPackage, bigPackage ); priceContext.setPrice({ 'Bed': 400, 'TV': 200, 'LapTop': 500, 'Table': 50 }); view.render(priceContext); };
  • 17.
    Sentence and Output Table:50 TV: 200 LapTop: 500 Bed: 400 Table: 50 Bed: 400 Bed: 400 TV: 200 TV: 200 LapTop: 500 <script type="text/template" id="contextTpl"> <h1>{Table}{SPackage}{Bed}{BPackage}{TV}{LapTop}</h1> </script>
  • 18.
    Advantages Disadvantages ● Youhave a simple language to interpret ● You can easily change the method of calculating expressions ● You can represent sentences in the language as abstract syntax trees (AST). ● Difficult to support the grammar with a large number of rules ● Each class on each expression
  • 19.
    Related Patterns ● Compositefor same proccessing terminal and non-terminal expressions ● Flyweight for sharing terminal expressions ● Iterator for traversing the nodes of non-terminals
  • 20.
    Inspired by Technology. Drivenby Value. Have a questions?