Find file
cf12681 May 19, 2009
120 lines (106 sloc) 2.56 KB
var Parser = function(grammar)
{
var toArray = function(args) {
var arr = []
for (var i = 0; i < args.length; i++) arr.push(args[i])
return arr
}
// The Y Combinator
var Y = function (gen) {
return (function(f) {return f(f)})(
function(f) {
return gen(function() {return f(f).apply(null, arguments)})
}
)
}
var Optional = function(func)
{
return function(text, state) {
return func(text, state) || [text, state]
}
}
var EOF = function(text, state) { // matches the end of the text
return (text == "" ? [text, state] : null)
}
var Terminator = function(text, state) { // terminates scanner (possibly in the middle of the text)
return ["", state]
}
var Char = function(alphabet)
{
return function(text, state) {
return ((text.length > 0 && alphabet.indexOf(text.charAt(0)) > -1) ? [text.substr(1), state] : null)
}
}
var NotChar = function(alphabet)
{
return function(text, state) {
return ((text.length > 0 && alphabet.indexOf(text.charAt(0)) == -1) ? [text.substr(1), state] : null)
}
}
var Any = function()
{
var args = toArray(arguments)
return function(text, state) {
var r = null
for each (var arg in args)
{
r = arg(text, state)
if (r)
{
return r
}
}
return null
}
}
var All = function()
{
var args = toArray(arguments)
return function(text, state) {
var r = null
for each (var arg in args)
{
r = arg(text, state)
if (!r) return r
text = r[0]
state = r[1]
}
return [text, state]
}
}
// hook: function(buffer, state) { return state }
var Capture = function(func, hook)
{
return function(text, state)
{
var r = func(text, state)
if (r) {
var t = r[0]
var s = r[1]
return [t, hook(text.substr(0, text.length - t.length), s)]
}
return r
}
}
// hook: function(state1) { return state2 }
var Before = function(func, hook)
{
return function(text, state) {
return func(text, hook(state))
}
}
// hook: function(state1, state2) { return state3 }
var After = function(func, hook)
{
return function(text, state) {
var r = func(text, state)
return r && [r[0], hook(state, r[1])]
}
}
return grammar(All, Any, Capture, Char, NotChar, Optional, Y, EOF, Terminator, Before, After)
}
var Parse = function(parser, text, state)
{
var r = parser(text, state)
return r && r[1]
}