Skip to content

Instantly share code, notes, and snippets.

@db48x
Created May 19, 2014 04:28
Show Gist options
  • Save db48x/2f4c56ab0a66a4b07bf6 to your computer and use it in GitHub Desktop.
Save db48x/2f4c56ab0a66a4b07bf6 to your computer and use it in GitHub Desktop.
a simple example of javascript parser combinators
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