Javascript. Iterpretator pattern

Паттерн Интерпретатор (Iterpretator pattern - Little (Small) Language) используется для создания языковых интерпретаторов. Определяется представление своей грамматики в виде класса вместе с интерпретатором для обработки серий. В архитектуру вводится класс, представляющий каждое правило языка. Интерпретация языка осуществляется вызовом метода interpret() для каждого типа выражения. Метод получает контекст (содержащий входной поток разбираемой программы), идентифицирует входные данные и обрабатывает их. Данный паттерн относится к поведенческим паттернам. Ниже приведены примеры реализации паттерна.


var Expression = function () {
    this.interpret = function () {
        throw new Error("You have not implement abstract method");
    };
};

var TerminalExpression = function (data) {
    this.interpret = function (context) {
        if (context.indexOf(data) >= 0) {
return true;
}
        return false;
    };
};
TerminalExpression.prototype = new Expression();
TerminalExpression.prototype.constructor = TerminalExpression;

var OrExpression = function (expr1, expr2) {
    if (!(expr1 instanceof Expression) || !(expr2 instanceof Expression)) {
        throw new Error("In argument given incorrect type");
    }
    this.interpret = function (context) {
        return expr1.interpret(context) || expr2.interpret(context)
    };
};
OrExpression.prototype = new Expression();
OrExpression.prototype.constructor = OrExpression;

var AndExpression = function (expr1, expr2) {
    if (!(expr1 instanceof Expression) || !(expr2 instanceof Expression)) {
        throw new Error("In argument given incorrect type");
    }
    this.interpret = function (context) {
        return expr1.interpret(context) && expr2.interpret(context)
    };
};
AndExpression.prototype = new Expression();
AndExpression.prototype.constructor = AndExpression;

var Application = function () {
//Rule: Robert and John are male
var getMaleExpression = function () {
var robert = new TerminalExpression("Robert"),
john = new TerminalExpression("John");
return new OrExpression(robert, john);
};
//Rule: Julie is a married women
var getMarriedWomanExpression = function () {
var julie = new TerminalExpression("Julie"),
married = new TerminalExpression("Married");
return new AndExpression(julie, married);
};
this.run = function () {
var isMale = getMaleExpression(),
isMarriedWoman  = getMarriedWomanExpression();
console.log("John is male? " + isMale.interpret("John"));
console.log("Julie is a married women? " + isMarriedWoman.interpret("Married Julie"));
};
};

var app = new Application();
app.run();

На выходе:

John is male? true
Julie is a married women? true

Вот еще одна реализация (http://www.dofactory.com/javascript/interpreter-design-pattern).

var Context = function (input) {
    this.input = input;
    this.output = 0;
};

Context.prototype = {
    startsWith : function (str) {
        return this.input.substr(0, str.length) === str;
    }
};

var Expression = function (name, one, four, five, nine, multiplier) {
    this.name = name;
    this.one = one;
    this.four = four;
    this.five = five;
    this.nine = nine;
    this.multiplier = multiplier;
};

Expression.prototype = {
    interpret: function (context) {
        if (context.input.length == 0) {
            return;
        }
        else if (context.startsWith(this.nine)) {
            context.output += (9 * this.multiplier);
            context.input = context.input.substr(2);
        }
        else if (context.startsWith(this.four)) {
            context.output += (4 * this.multiplier);
            context.input = context.input.substr(2);
        }
        else if (context.startsWith(this.five)) {
            context.output += (5 * this.multiplier);
            context.input = context.input.substr(1);
        }
        while (context.startsWith(this.one)) {
            context.output += (1 * this.multiplier);
            context.input = context.input.substr(1);
        }
    }
};

var Application = function () {
this.run = function () {
var roman = "MCMXXVIII"
var context = new Context(roman);
var tree = [];
 
tree.push(new Expression("thousand", "M", " " , " ", " " , 1000));
tree.push(new Expression("hundred",  "C", "CD", "D", "CM", 100));
tree.push(new Expression("ten",      "X", "XL", "L", "XC", 10));
tree.push(new Expression("one",      "I", "IV", "V", "IX", 1));
 
for (var i = 0, len = tree.length; i < len; i++) {
tree[i].interpret(context);
}
 
console.log(roman + " = " + context.output);
};
};

var app = new Application();
app.run();

На выходе получаем сообщение:

MCMXXVIII = 1928