Created
May 4, 2009 15:30
-
-
Save oleganza/106508 to your computer and use it in GitHub Desktop.
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
// BNF parser framework for JavaScript | |
// Oleg Andreev | |
var result = (function(text){ | |
// The Y Combinator | |
var Y=function (gen) { | |
return function(f) {return f(f)}( | |
function(f) { | |
return gen(function() {return f(f).apply(null, arguments)})})} | |
function ToArray(args) | |
{ | |
var arr = [] | |
for (var i = 0; i < args.length; i++) arr.push(args[i]) | |
return arr | |
} | |
function Optional(func) | |
{ | |
return function(text, state) { | |
return func(text, state) || text | |
} | |
} | |
function Char(string) | |
{ | |
return function(text, state) { | |
return ((string.indexOf(text.charAt(0)) > -1) ? text.substr(1) : null) | |
} | |
} | |
function Any() | |
{ | |
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 | |
} | |
} | |
function All() | |
{ | |
var args = ToArray(arguments) | |
return function(text, state) { | |
for each (var arg in args) | |
{ | |
text = arg(text, state) | |
if (!text) return text | |
} | |
return text | |
} | |
} | |
function Capture(func, hook) | |
{ | |
return function(text, state) | |
{ | |
var r = func(text, state) | |
if (r) hook(text.substr(0, text.length - r.length), state) | |
return r | |
} | |
} | |
/* | |
sign := "+" | "-" | |
digit := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
integer := digit integer | digit | |
float := integer "." integer | |
unsigned := float | integer | |
signed := sign optspace unsigned | |
number := signed | unsigned | |
*/ | |
var spacechar = Char(" \t") | |
var optspace = Y(function(os){ return Optional(All(spacechar, os)) }) | |
var space = All(spacechar, optspace) | |
var sign = Char("+-") | |
var digit = Char("0123456789") | |
var integer = Y(function(i){ return All(digit, Optional(i)) }) | |
var float = All(integer, Char("."), integer) | |
var unsigned = Any(float, integer) | |
var signed = All(sign, optspace, unsigned) | |
var number = Capture(Any(signed,unsigned), function(buffer, state) { | |
state.push(buffer) | |
}) | |
var numbers = Y(function(ns){ return All(number, optspace, Optional(ns)) }) | |
var main = All(optspace, numbers, optspace) | |
var scanner = main | |
var numbers = [] | |
var r = scanner(text + " ", numbers) // tail space is intended | |
if(!r) | |
print("Syntax error!") | |
else | |
print("Result is '"+ r +"'") | |
return numbers | |
})(" + 1.23 +45 678") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment