Date post: | 16-Apr-2017 |
Category: |
Software |
Upload: | dmytro-verbovyi |
View: | 318 times |
Download: | 0 times |
IntroductionGiven 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.
● 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
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
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 Expressionclass Goods { constructor(){ this.name = this.__proto__.constructor.name; } interpret(context) { return this.name + ': ' + context.getPrice(this.name) + '<br>'; }}
Terminal Expressions
//Terminal Expressionsclass TV extends Goods {}
class LapTop extends Goods {}
class Table extends Goods {}
class Bed extends Goods {}
Nonterminal Expressions//Non-Terminal Expresionsclass 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 {}
Contextclass 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 1class 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 2render(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; }}
Usageconst 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: 50TV: 200LapTop: 500Bed: 400Table: 50Bed: 400Bed: 400TV: 200TV: 200LapTop: 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