-
-
Save karoltarasiuk/98f0b7ffc34563fdb2b8 to your computer and use it in GitHub Desktop.
Function Generator - PEG.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
// from underscore lib | |
var extend = function (obj) { | |
var source, prop; | |
for (var i = 1, length = arguments.length; i < length; i++) { | |
source = arguments[i]; | |
for (prop in source) { | |
if (hasOwnProperty.call(source, prop)) { | |
obj[prop] = source[prop]; | |
} | |
} | |
} | |
return obj; | |
}; | |
//---------- | |
// ABSTRACT | |
//---------- | |
var Expression = function Expression(children, operator) { | |
this.initialize(children, operator); | |
}; | |
extend(Expression.prototype, { | |
numberOfChildren: 0, | |
initialize: function (children, operator) { | |
this.setOperator(operator); | |
this.setChildren(children); | |
}, | |
getName: function() { | |
var funcNameRegex = /function (.{1,})\(/, | |
results = (funcNameRegex).exec((this).constructor.toString()); | |
return (results && results.length > 1) ? results[1] : ""; | |
}, | |
setOperator: function (operator) { | |
this.operator = operator; | |
}, | |
setChildren: function (children) { | |
this.children = children; | |
this.checkNumberOfChildren(this.numberOfChildren); | |
}, | |
checkNumberOfChildren: function () { | |
if (this.numberOfChildren > this.children.length) { | |
throw this.getName() + "(" + this.operator + ") requires " + this.numberOfChildren + " children"; | |
} | |
}, | |
execute: function (params) { | |
throw "Expression.execute is not implemented"; | |
} | |
}); | |
var Primary = function Primary(child) { | |
this.initialize(child); | |
}; | |
extend(Primary.prototype, Expression.prototype, { | |
numberOfChildren: 1, | |
initialize: function (child) { | |
Expression.prototype.initialize.call(this, [child], ''); | |
} | |
}); | |
//--------- | |
// REGULAR | |
//--------- | |
var Empty = function Empty(child) { | |
this.initialize(child); | |
}; | |
extend(Empty.prototype, Primary.prototype, { | |
execute: function (params) { | |
return this.children[0]; | |
} | |
}); | |
var Param = function Param(child) { | |
this.initialize(child); | |
}; | |
extend(Param.prototype, Primary.prototype, { | |
execute: function (params) { | |
var param = this.children[0]; | |
if ("undefined" !== typeof params[param]) { | |
if (params[param] === 'evaluate') { | |
return -1; | |
} else { | |
return params[param]; | |
} | |
} else { | |
throw param + " param not provided"; | |
} | |
} | |
}); | |
var Brackets = function Brackets(child) { | |
this.initialize(child); | |
}; | |
extend(Brackets.prototype, Primary.prototype, { | |
execute: function (params) { | |
return this.children[0].execute(params); | |
} | |
}); | |
var Integer = function Integer(child) { | |
this.initialize(child); | |
}; | |
extend(Integer.prototype, Primary.prototype, { | |
execute: function (params) { | |
return this.children[0]; | |
} | |
}); | |
var Addition = function Addition(children) { | |
this.initialize(children); | |
}; | |
extend(Addition.prototype, Expression.prototype, { | |
numberOfChildren: 2, | |
initialize: function (children) { | |
Expression.prototype.initialize.call(this, children, '+'); | |
}, | |
execute: function (params) { | |
return this.children[0].execute(params) + this.children[1].execute(params); | |
} | |
}); | |
var Subtraction = function Subtraction(children) { | |
this.initialize(children); | |
}; | |
extend(Subtraction.prototype, Expression.prototype, { | |
numberOfChildren: 2, | |
initialize: function (children) { | |
Expression.prototype.initialize.call(this, children, '-'); | |
}, | |
execute: function (params) { | |
return this.children[0].execute(params) - this.children[1].execute(params); | |
} | |
}); | |
var Multiplication = function Multiplication(children) { | |
this.initialize(children); | |
}; | |
extend(Multiplication.prototype, Expression.prototype, { | |
numberOfChildren: 2, | |
initialize: function (children) { | |
Expression.prototype.initialize.call(this, children, '*'); | |
}, | |
execute: function (params) { | |
return this.children[0].execute(params) * this.children[1].execute(params); | |
} | |
}); | |
var Division = function Division(children) { | |
this.initialize(children); | |
}; | |
extend(Division.prototype, Expression.prototype, { | |
numberOfChildren: 2, | |
initialize: function (children) { | |
Expression.prototype.initialize.call(this, children, '/'); | |
}, | |
execute: function (params) { | |
var numerator = this.children[0].execute(params), | |
denominator = this.children[1].execute(params); | |
if (denominator === 0) { | |
throw "Division by 0: " + numerator + "/" + denominator; | |
} | |
return numerator / denominator; | |
} | |
}); | |
} | |
start | |
= expression | |
brackets | |
= "(" inside:expression ")" { return new Brackets(inside); } | |
multiplication | |
= left:primary "*" right:primary { return new Multiplication([left, right]); } | |
division | |
= left:primary "/" right:primary { return new Division([left, right]); } | |
addition | |
= left:primary "+" right:primary { return new Addition([left, right]); } | |
subtraction | |
= left:primary "-" right:primary { return new Subtraction([left, right]); } | |
param | |
= letters:[a-z]+ { return new Param(letters.join("")); } | |
integer "integer" | |
= digits:[0-9]+ { return new Integer(parseInt(digits.join(""), 10)); } | |
empty | |
= "" { return new Empty(0); } | |
expression | |
= operation | |
/ primary | |
operation | |
= multiplication | |
/ division | |
/ addition | |
/ subtraction | |
primary | |
= brackets | |
/ integer | |
/ param | |
/ empty |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var parserObject, | |
parser = PEG.buildParser(parserScript); | |
parserObject = parser.parse('x+((2*3)-2)'); | |
console.log(parserObject.execute({x:3})); | |
parserObject = parser.parse('x+((2*a)-2)'); | |
console.log(parserObject.execute({x:3,a:5})); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment