view parser.js @ 19:132c7756860e

Use populateSymbols to generate symbol tables during compilation rather than populating them as we go. This change allows us to refer to symbols defined later in the input stream and also gives the symbol table logic a single home that can be used both by the compiler and editor.
author Mike Pavone <pavone@retrodev.com>
date Sun, 25 Mar 2012 16:11:19 -0700
parents 04ae32e91598
children 40a85f135be5
line wrap: on
line source


function op(left, op, right)
{
	this.left = left;
	this.op = op;
	this.right = right;
}

function symbol(name, symbols)
{
	this.name = name;
	this.symbols = symbols;
}
symbol.prototype.cleanName = function() {
	return this.name[0] == ':' ? this.name.substr(1) : this.name;
}

function intlit(val)
{
	this.val = val;
}

function floatlit(val)
{
	this.val = val;
}

function strlit(val)
{
	this.val = val;
}

function funcall(name, args)
{
	this.name = name;
	this.args = args;
	this.receiver = null;
}

function object(messages)
{
	this.messages = messages;
}

function lambda(args, expressions)
{
	this.args = args;
	this.expressions = expressions;
}

function assignment(sym, expr)
{
	this.symbol = sym;
	this.expression = expr;
}

var grammar = 
'start = ws module:(object / lambda) ws { return module; };' +
'ws = ([ \\t\\n\\r] / "//" [^\\n]* "\\n")*;' +
'hws = ([ \\t] / "/*" ([^*] / "*" ! "/")* "*/" )*;' +
'expr = e:(funcall / methcall / opexpr) ws { return e; };' +
'opexpr = left:addsub hws opn:("<=" / ">=" / "<" / ">" / "=") hws right:opexpr { return new op(left, opn, right); } / addsub;' +
'addsub = left:muldiv hws opn:("+"/"-") hws right:addsub { return new op(left, opn, right); } / muldiv;'+
'muldiv = left:primlitsym hws opn:("*"/"/") hws right:muldiv { return new op(left, opn, right); } / primlitsym;'+
'primlitsym = hws val:(float / int / string / symbol / object / lambda / "(" expr:expr hws ")" { return expr; }) { return val; };' +
'symbol = chars:[a-zA-Z_!?@]+ trailing:(":"? [a-zA-Z_!?@0-9])* ! ":" { for (var i in trailing) { trailing[i] = trailing[i].join(""); } return new symbol(chars.join("") + trailing.join("")); };' +
'float = digits:[0-9]+ "." decimals:[0-9]+ { return new floatlit(parseFloat(digits.join("") + "." + decimals.join(""))); };' +
'int = digits:[0-9]+ { return new intlit(parseInt(digits.join(""), 10)); };' +
'string = "\\"" text:[^\\"]* "\\"" { return new strlit(text.join("")); };' +
'object = "#{" ws messages:assignment* "}" { return new object(messages); };' +
'assignment = hws sym:symbol hws "<-" expr:expr ws { return new assignment(sym, expr); }' +
'lambda = args:((& ":") argname+  )? "{" ws exprs:(assignment / expr)* "}" { return new lambda(args[1], exprs); };' +
'argname = init:":"? chars:[a-zA-Z_!?@]+ trailing:[a-zA-Z_!?@0-9]* hws { return new symbol(init + chars.join("") + trailing.join("")); };' +
'funcall = hws parts: funcallpart+ { var fun = ""; var args = []; for (var i in parts) { fun += parts[i].name; args = args.concat(parts[i].args); } return new funcall(fun, args); };' +
'funcallpart = fun:funpart args:opexpr* hws { return { name: fun, args: args}; };' +
'funpart = chars:[a-zA-Z_!?@]+ middle:[a-zA-Z_!?@0-9]* ":" & [ \\t\\n\\r] { return chars.join("") + middle.join("") + ":"; };' +
'methcall = receiver:opexpr hws info:methcallrest { info.receiver = receiver; return info; };' +
'methcallrest = funcall / unarymeth;' +
'unarymeth = name:symbol { return new funcall(name.name, []); };';
var parser = PEG.buildParser(grammar);