Skip to content

Instantly share code, notes, and snippets.

@igstan
Forked from oleganza/gist:106508
Created June 29, 2009 03:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save igstan/137446 to your computer and use it in GitHub Desktop.
Save igstan/137446 to your computer and use it in GitHub Desktop.
// 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