Mercurial > repos > tabletprog
view parser.js @ 355:0b4d4f06bf91
Add support for setcc in x86 module. Add support for translating il skipIf:else and il bool instructions in x86 module.
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 15 Apr 2015 21:14:44 -0700 |
parents | f73ebc146af9 |
children |
line wrap: on
line source
function op(left, op, right) { this.left = left; if (op instanceof Array) { op = op[0]; } this.op = op; this.right = right; } op.prototype.valueOf = function(indent) { return this.left.valueOf(indent) + ' ' + this.op.valueOf(indent) + ' ' + this.right.valueOf(indent); }; function symbol(name, symbols) { this.name = name; this.symbols = symbols; this.dirty = false; } symbol.prototype.cleanName = function() { return this.name[0] == ':' ? this.name.substr(1) : this.name; } symbol.prototype.valueOf = function() { return this.name; }; function intlit(val, bits, unsigned) { if (!bits) { bits = 32; } if (unsigned === undefined) { unsigned = false; } this.unsigned = unsigned; this.bits = bits; this.val = val; } intlit.prototype.valueOf = function() { var val = '' + this.val; if (this.bits != 32 || this.unsigned) { val += this.unsigned ? 'u' : 'i' val += this.bits; } return val; }; function floatlit(val, bits) { this.val = val; this.bits = bits; } floatlit.prototype.valueOf = function() { return '' + val; }; function strlit(val) { this.val = val; } strlit.prototype.valueOf = function() { return '"'+this.val+'"'; }; function listlit(val) { this.val = val; } listlit.prototype.valueOf = function(indent) { if (indent === undefined) { indent = ''; } var nextindent = indent + '\t'; var val = '[' for (var i = 0; i < this.val.length; i++) { val += '\n' + nextindent + this.val[i].valueOf(nextindent); } if (this.val.length) { val += '\n' + indent; } val += ']'; return val; }; function arraylit(val) { this.val = val; } arraylit.prototype.valueOf = function(indent) { if (indent === undefined) { indent = ''; } var nextindent = indent + '\t'; var val = '#[' for (var i = 0; i < this.val.length; i++) { val += '\n' + nextindent + this.val[i].valueOf(nextindent); } if (this.val.length) { val += '\n' + indent; } val += ']'; return val; }; function funcall(name, args) { this.name = name; this.args = args; this.receiver = null; this.dirty = false; } funcall.prototype.valueOf = function(indent) { var parts = this.name.split(':'); var val = ''; if (this.receiver) { val += this.receiver.valueOf(indent); } var curarg = 0; for (var i = 0; i < parts.length; i++) { if (val) { val += ' '; } if (parts[i]) { val += parts[i] + ': '; } if (curarg < this.args.length) { val += this.args[curarg++].valueOf(indent); } } while (curarg < this.args.length) { val += ' ' + this.args[curarg++].valueOf(indent); } return val; }; function object(messages) { this.messages = messages; this.name = null; } object.prototype.valueOf = function(indent) { if (indent === undefined) { indent = ''; } var nextindent = indent + '\t'; var val = '#{'; for (var i = 0; i < this.messages.length; i++) { val += '\n' + nextindent + this.messages[i].valueOf(nextindent); } if (val.length > 2) { val += '\n' + indent; } val += '}'; return val; }; function lambda(args, expressions) { this.args = args ? args : []; this.expressions = expressions; } lambda.prototype.valueOf = function(indent) { if (indent === undefined) { indent = ''; } var nextindent = indent + '\t'; var val = ''; for (var i = 0; i < this.args.length; i++) { val += this.args[i].valueOf(indent) + ' '; } val += '{'; for (var i = 0; i < this.expressions.length; i++) { val += '\n' + nextindent + this.expressions[i].valueOf(nextindent); } if (this.expressions.length) { val += '\n' + indent; } val += '}'; return val; }; function assignment(sym, expr) { this.symbol = sym; this.expression = expr; } assignment.prototype.valueOf = function(indent) { return this.symbol.valueOf(indent) + ' <- ' + this.expression.valueOf(indent); }; 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 / assignment / opexpr) ws { return e; };' + 'opexpr = left:compareop pieces:(hws ("&&" / "||") ws compareop)* { 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; } };'+ 'compareop = left:maybecons pieces:(hws ("<=" / ">=" / "<" / ">" / "=" / "!=") ws maybecons)* { 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; } };'+ 'maybecons = consop / addsub;' + 'consop = left:addsub hws "|" ws right:maybecons { return new op(left, "|", right); };'+ 'addsub = left:muldiv pieces:(hws ((("xor"/"and"/"or") ! [a-zA-Z_!?@0-9])/("+"/"-"/".")) ws 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 ("*"/"/"/"%") ws 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 = 0; i < trailing.length; i++) { trailing[i] = trailing[i].join(""); } return new symbol(chars.join("") + trailing.join("")); };' + 'float = digits:[0-9]+ "." decimals:[0-9]+ size:("f" ("32" / "64"))? { var bits = size ? parseInt(size[1], 10) : 64; return new floatlit(parseFloat(digits.join("") + "." + decimals.join("")), bits); };' + 'binary = "0b" digits:[01]+ { return new intlit(parseInt(digits.join(""), 2)); };' + 'hex = "0x" digits:[0-9a-fA-F]+ size:([iu] ("8" / "16" / "32" / "64"))? { var bits = size ? parseInt(size[1], 10) : 0; return new intlit(parseInt(digits.join(""), 16), bits, size[0] == "u"); };' + 'int = sign:"-"? digits:[0-9]+ size:([iu] ("8" / "16" / "32" / "64"))? { var bits = size ? parseInt(size[1], 10) : 0; return new intlit(parseInt(sign + digits.join(""), 10), bits, size[0] == "u"); };' + '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"; } if (char == "t") { return "\\t"; } return char; };' + 'object = "#{" ws messages:(assignment / funexpr)* "}" { return new object(messages); };' + 'array = "#[" ws els:expr* "]" { return new arraylit(els); };' + 'list = "[" ws els:expr* "]" { return new listlit(els); };' + 'opsym = name:("&&" / "||" / "<=" / ">=" / "<" / ">" / "=" / "!=" / "+" / "-" / "." / "*" / "/" / "%" / "|") { return new symbol(name); };' + 'assignment = ws sym:(opsym / symbol) hws "<-" expr:expr ws { return new assignment(sym, expr); }' + 'lambda = args:((& ":") argname+ )? "{" ws exprs: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("")); };' + 'funexpr = f: funcall ws { return f; };' + 'funcall = hws parts: funcallpart+ { var fun = ""; var args = []; for (var i = 0; i < parts.length; i++) { 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);