Skip to content

Instantly share code, notes, and snippets.

@pasaran
Created October 29, 2012 08:56
Show Gist options
  • Save pasaran/3972474 to your computer and use it in GitHub Desktop.
Save pasaran/3972474 to your computer and use it in GitHub Desktop.
parser.01
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>parser.01</title>
<script src="01.parser.js"></script>
</head>
<body>
<script>
var ast = parse('2 + 3 * (5 - 6)');
console.log( JSON.stringify(ast, null, 4) );
</script>
</body>
</html>
var TOKEN_ADD = /^[+-]/;
var TOKEN_MUL = /^[*/%]/;
var TOKEN_NUMBER = /^[0-9]+(\.[0-9]+)?/;
function parse(s) {
var p = 0;
var cur = s;
var ast = parse(r_expr);
if (cur) {
error('End of string expected');
}
return ast;
// --------------------------------------------------------------------------------------------------------------- //
function parse(rule) {
var start = p;
var ast = rule();
// ast._start = start;
// ast._end = p;
return ast;
}
function test(token) {
var r = token.exec(cur);
return r && r[0];
}
function match(token) {
var result = test(token);
if (!result) {
expected(token);
}
move(result.length);
skip();
return result;
}
function eat(s) {
var l = s.length;
if ( la(l) !== s ) {
expected(s);
}
move(l);
skip();
return s;
}
function skip() {
var r = /^\s+/.exec(cur);
if (r) {
move(r[0].length);
}
}
function move(l) {
l || (l = 1);
p += l;
cur = cur.substr(l);
}
function la(n) {
return cur.substr(0, n || 1);
}
function expected(id) {
error('Token ' + id + 'expected');
}
function error(msg) {
throw Error(msg + ' at ' + p + ' : ' + cur);
}
// --------------------------------------------------------------------------------------------------------------- //
function r_expr() {
return parse(r_add);
}
function r_add() {
var left = parse(r_mul);
if (( op = test(TOKEN_ADD) )) {
match(TOKEN_ADD);
return {
_id: 'add',
op: op,
left: left,
right: parse(r_add)
};
}
return left;
}
function r_mul() {
var left = parse(r_primary);
if (( op = test(TOKEN_MUL) )) {
match(TOKEN_MUL);
return {
_id: 'mul',
op: op,
left: left,
right: parse(r_mul)
};
}
return left;
}
function r_primary() {
if ( la() === '(' ) {
eat('(');
var ast = parse(r_expr);
eat(')');
return ast;
}
return {
_id: 'number',
value: +match(TOKEN_NUMBER)
};
}
// --------------------------------------------------------------------------------------------------------------- //
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment