Created
May 19, 2014 04:28
-
-
Save db48x/2f4c56ab0a66a4b07bf6 to your computer and use it in GitHub Desktop.
a simple example of javascript parser combinators
This file contains hidden or 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
function token(t) { | |
return function (text) { | |
if (text[0] == t) | |
return text.slice(1); | |
return false; | |
}; | |
} | |
function and() { | |
var args = arguments; | |
return function (text) { | |
var rest = text; | |
for each (arg in args) { | |
rest = arg(rest); | |
if (rest === false) | |
return false; | |
} | |
return rest; | |
}; | |
} | |
function or() { | |
var args = arguments; | |
return function (text) { | |
for each (arg in args) { | |
var rest = arg(text); | |
if (rest !== false) | |
return rest; | |
} | |
return false; | |
}; | |
} | |
function oneormore(parser) { | |
return function (text) { | |
var rest = text; | |
while (rest) { | |
var r = parser(rest); | |
if (r === false) { | |
return rest == text ? false : rest; | |
} | |
rest = r; | |
} | |
return rest == text ? false : rest; | |
}; | |
} | |
function optional(parser) { | |
return function (text) { | |
var rest = parser(text); | |
if (rest === false) | |
return text; | |
return rest; | |
}; | |
} | |
var digit = or(token("0"), | |
token("1"), | |
token("2"), | |
token("3"), | |
token("4"), | |
token("5"), | |
token("6"), | |
token("7"), | |
token("8"), | |
token("9")); | |
var integer = oneormore(digit); | |
var float = or(and(optional(integer), | |
token("."), | |
integer), | |
and(integer, | |
token("."), | |
optional(integer)), | |
integer); | |
var posneg = and(optional(or(token("-"), | |
token("+"))), | |
float); | |
var scientific = and(posneg, | |
optional(and(or(token("e"), | |
token("E")), | |
posneg))); | |
function isNumber(text) { | |
var rest = scientific(text); | |
// return true only if the parser consumed the whole string | |
return rest.length === 0; | |
} | |
console.log("isNumber('') => "+ isNumber('')); // false | |
console.log("isNumber('0') => "+ isNumber('0')); // true | |
console.log("isNumber('1') => "+ isNumber('1')); // true | |
console.log("isNumber('2') => "+ isNumber('2')); // true | |
console.log("isNumber('10') => "+ isNumber('10')); // true | |
console.log("isNumber('10a') => "+ isNumber('10a')); // false | |
console.log("isNumber('a') => "+ isNumber('a')); // false | |
console.log("isNumber('2147483648') => "+ isNumber('2147483648')); // true | |
console.log("isNumber('+42') => "+ isNumber('+42')); // true | |
console.log("isNumber('-42') => "+ isNumber('-42')); // true | |
console.log("isNumber('4+2') => "+ isNumber('4+2')); // false | |
console.log("isNumber('4-2') => "+ isNumber('4-2')); // false | |
console.log("isNumber('+') => "+ isNumber('+')); // false | |
console.log("isNumber('-') => "+ isNumber('-')); // false | |
console.log("isNumber('+-42') => "+ isNumber('+-42')); // false | |
console.log("isNumber('.42') => "+ isNumber('.42')); // true | |
console.log("isNumber('0.42') => "+ isNumber('0.42')); // true | |
console.log("isNumber('04.2') => "+ isNumber('04.2')); // true | |
console.log("isNumber('042.') => "+ isNumber('042.')); // true | |
console.log("isNumber('0.42.0') => "+ isNumber('0.42.0')); // false | |
console.log("isNumber('.') => "+ isNumber('.')); // false | |
console.log("isNumber('0.42a') => "+ isNumber('0.42a')); // false | |
console.log("isNumber('-4.2') => "+ isNumber('-4.2')); // true | |
console.log("isNumber('+4.2') => "+ isNumber('+4.2')); // true | |
console.log("isNumber('4e2') => "+ isNumber('4e2')); // true | |
console.log("isNumber('-4E2') => "+ isNumber('-4E2')); // true | |
console.log("isNumber('+4e-2') => "+ isNumber('+4e-2')); // true | |
console.log("isNumber('0.42E-.1234') => "+ isNumber('0.42E-.1234')); // true | |
console.log("isNumber('42e24e-123') => "+ isNumber('42e24e-123')); // false | |
console.log("isNumber('04.2E-.12.34') => "+ isNumber('04.2E-.12.34')); // false | |
console.log("isNumber('04.2E-.2134') => "+ isNumber('0.42E-.1234')); // true | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment