view parser.js @ 69:ba032565c7a5

Fix handling of variable style access to self and parent object messages defined with lambdas. Improve test case for this bug to include parent object access as well as self object access.
author Mike Pavone <pavone@retrodev.com>
date Sat, 14 Jul 2012 19:24:04 -0700
parents 3a169ebb3224
children fdb9785d2c93
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 listlit(val)
{
	this.val = val;
}

function arraylit(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 ? args : [];
	this.expressions = expressions;
}

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

function isLambda(node)
{
	return node instanceof lambda;
}

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 pieces:(hws ("<=" / ">=" / "<" / ">" / "=" / "!=") hws addsub)* { if (pieces.length) { var cur = new op(left, pieces[0][1], pieces[0][3]); for (var i = 1; i < pieces.length; i++) { cur = new op(cur, pieces[i][1], pieces[i][3]); } return cur; } else { return left; } };'+
'addsub = left:muldiv pieces:(hws ("+"/"-"/".") hws muldiv)* { if (pieces.length) { var cur = new op(left, pieces[0][1], pieces[0][3]); for (var i = 1; i < pieces.length; i++) { cur = new op(cur, pieces[i][1], pieces[i][3]); } return cur; } else { return left; } };'+
'muldiv = left:primlitsym pieces:(hws ("*"/"/"/"%") hws primlitsym)* { if (pieces.length) { var cur = new op(left, pieces[0][1], pieces[0][3]); for (var i = 1; i < pieces.length; i++) { cur = new op(cur, pieces[i][1], pieces[i][3]); } return cur; } else { return left; } };'+
'primlitsym = hws val:(float / hex / binary / int / string / symbol / object / array / list / lambda / "(" ws 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(""))); };' +
'binary = "0b" digits:[01]+ { return new intlit(parseInt(digits.join(""), 2)); };' +
'hex = "0x" digits:[0-9a-fA-F]+ { return new intlit(parseInt(digits.join(""), 16)); };' +
'int = sign:"-"? digits:[0-9]+ { return new intlit(parseInt(sign + digits.join(""), 10)); };' +
'string = "\\"" text:(strpart/escape)* "\\"" { return new strlit(text.join("")); };' +
'strpart = text:[^\\"\\\\]+ { return text.join(""); };' + 
'escape = "\\\\" char:[nt\\"r\\\\] { if (char == "n") { return "\\n"; } if (char == "r") { return "\\r"; } return char; };' +
'object = "#{" ws messages:(assignment / funcall)* "}" { return new object(messages); };' +
'array = "#[" ws els:opexpr* "]" { return new arraylit(els); };' +
'list = "[" ws els:opexpr* "]" { return new listlit(els); };' +
'assignment = ws 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);