aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMihai Bazon <mihai@bazon.net>2012-08-16 18:11:04 +0300
committerMihai Bazon <mihai@bazon.net>2012-08-16 18:11:04 +0300
commit7f273c3b89352c6fda528dfee17776cffcfe1fb4 (patch)
treec140b56c5224e1f186a75ab22310b660a4fb7220
parentc0ba9e29861ab08ad8a5131705f421e96d634f4b (diff)
downloadtracifyjs-7f273c3b89352c6fda528dfee17776cffcfe1fb4.tar.gz
tracifyjs-7f273c3b89352c6fda528dfee17776cffcfe1fb4.zip
codegen and dropped the useless walker
-rw-r--r--lib/ast.js264
-rwxr-xr-xlib/node.js16
-rw-r--r--lib/output.js455
-rw-r--r--lib/parse.js13
4 files changed, 450 insertions, 298 deletions
diff --git a/lib/ast.js b/lib/ast.js
index b8b6b072..c5be5f6f 100644
--- a/lib/ast.js
+++ b/lib/ast.js
@@ -23,6 +23,9 @@ function DEFNODE(type, props, methods, base) {
if (methods) for (i in methods) if (HOP(methods, i)) {
ctor.prototype[i] = methods[i];
}
+ ctor.DEFMETHOD = function(name, method) {
+ this.prototype[name] = method;
+ };
return ctor;
};
@@ -34,66 +37,33 @@ var AST_Node = DEFNODE("Node", "start end", {
clone: function() {
return new this.CTOR(this);
},
- // XXX: what was this for?
- // renew: function(args) {
- // var ctor = this.CTOR, props = ctor.props;
- // for (var i in props) if (!HOP(args, i)) args[i] = this[i];
- // return new ctor(args);
- // },
- walk: function(w) {
- w._visit(this);
- }
}, null);
var AST_Directive = DEFNODE("Directive", "value", {
- print: function(output) {
- output.string(this.value);
- }
+
});
var AST_Debugger = DEFNODE("Debugger", null, {
- print: function(output) {
- output.print("debugger");
- }
+
});
var AST_Parenthesized = DEFNODE("Parenthesized", "expression", {
$documentation: "Represents an expression which is always parenthesized. Used for the \
conditions in IF/WHILE/DO and expression in SWITCH/WITH.",
- walk: function(w) {
- w._visit(this, function(){
- this.expression.walk(w);
- });
- }
});
var AST_Bracketed = DEFNODE("Bracketed", "body", {
$documentation: "Represents a block of statements that are always included in brackets. \
Used for bodies of FUNCTION/TRY/CATCH/THROW/SWITCH.",
- walk: function(w) {
- w._visit(this, function(){
- this.body.forEach(function(stat){
- stat.walk(w);
- });
- });
- }
});
/* -----[ loops ]----- */
-var AST_Statement = DEFNODE("Statement", "label body", {
- walk: function(w) {
- w._visit(this, function(){
- if (this.label) this.label.walk(w);
- if (this.body) {
- if (this.body instanceof AST_Node)
- this.body.walk(w);
- else
- this.walk_array(w);
- }
- });
- },
- walk_array: AST_Bracketed.prototype.walk
+var AST_LabeledStatement = DEFNODE("LabeledStatement", "label statement", {
+
+});
+
+var AST_Statement = DEFNODE("Statement", "body", {
});
var AST_SimpleStatement = DEFNODE("SimpleStatement", null, {
@@ -109,64 +79,23 @@ var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
}, AST_Statement);
var AST_Do = DEFNODE("Do", "condition", {
- walk: function(w) {
- w._visit(this, function(){
- this.condition.walk(w);
- AST_Statement.prototype.walk.call(this, w);
- });
- }
}, AST_Statement);
var AST_While = DEFNODE("While", "condition", {
- walk: function(w) {
- w._visit(this, function(){
- this.condition.walk(w);
- AST_Statement.prototype.walk.call(this, w);
- });
- }
}, AST_Statement);
var AST_For = DEFNODE("For", "init condition step", {
- walk: function(w) {
- w._visit(this, function(){
- if (this.init) this.init.walk(w);
- if (this.condition) this.condition.walk(w);
- if (this.step) this.step.walk(w);
- AST_Statement.prototype.walk.call(this, w);
- });
- }
}, AST_Statement);
var AST_ForIn = DEFNODE("ForIn", "init name object", {
- walk: function(w) {
- w._visit(this, function(){
- if (this.init) this.init.walk(w);
- this.object.walk(w);
- AST_Statement.prototype.walk.call(this, w);
- });
- }
}, AST_Statement);
var AST_With = DEFNODE("With", "expression", {
- walk: function(w) {
- w._visit(this, function(){
- this.expression.walk(w);
- AST_Statement.prototype.walk.call(this, w);
- });
- }
}, AST_Statement);
/* -----[ functions ]----- */
var AST_Scope = DEFNODE("Scope", "identifiers", {
- walk: function(w) {
- w._visit(this, function(){
- if (this.identifiers) this.identifiers.forEach(function(el){
- el.walk(w);
- });
- AST_Statement.prototype.walk.call(this, w);
- });
- }
}, AST_Statement);
var AST_Toplevel = DEFNODE("Toplevel", null, {
@@ -174,15 +103,6 @@ var AST_Toplevel = DEFNODE("Toplevel", null, {
}, AST_Scope);
var AST_Lambda = DEFNODE("Lambda", "name argnames", {
- walk: function(w) {
- w._visit(this, function(){
- if (this.name) this.name.walk(w);
- this.argnames.forEach(function(el){
- el.walk(w);
- });
- AST_Scope.prototype.walk.call(this, w);
- });
- }
}, AST_Scope);
var AST_Function = DEFNODE("Function", null, {
@@ -200,11 +120,6 @@ var AST_Jump = DEFNODE("Jump", null, {
});
var AST_Exit = DEFNODE("Exit", "value", {
- walk: function(w) {
- w._visit(this, function(){
- if (this.value) this.value.walk(w);
- });
- }
}, AST_Jump);
var AST_Return = DEFNODE("Return", null, {
@@ -216,11 +131,6 @@ var AST_Throw = DEFNODE("Throw", null, {
}, AST_Exit);
var AST_LoopControl = DEFNODE("LoopControl", "label", {
- walk: function(w) {
- w._visit(this, function(){
- if (this.label) this.label.walk(w);
- });
- }
}, AST_Jump);
var AST_Break = DEFNODE("Break", null, {
@@ -234,34 +144,17 @@ var AST_Continue = DEFNODE("Continue", null, {
/* -----[ IF ]----- */
var AST_If = DEFNODE("If", "condition consequent alternative", {
- walk: function(w) {
- w._visit(this, function(){
- this.condition.walk(w);
- this.consequent.walk(w);
- if (this.alternative) this.alternative.walk(w);
- });
- }
});
/* -----[ SWITCH ]----- */
var AST_Switch = DEFNODE("Switch", "expression", {
- walk: function(w) {
- w._visit(this, function(){
- this.expression.walk(w);
- AST_Statement.prototype.walk.call(this, w);
- });
- }
}, AST_Statement);
var AST_SwitchBlock = DEFNODE("SwitchBlock", null, {
- walk : AST_Statement.prototype.walk,
- walk_array : AST_Bracketed.prototype.walk
}, AST_Bracketed);
var AST_SwitchBranch = DEFNODE("SwitchBranch", "body", {
- walk : AST_Statement.prototype.walk,
- walk_array : AST_Bracketed.prototype.walk
});
var AST_Default = DEFNODE("Default", null, {
@@ -269,49 +162,22 @@ var AST_Default = DEFNODE("Default", null, {
}, AST_SwitchBranch);
var AST_Case = DEFNODE("Case", "expression", {
- walk: function(w) {
- w._visit(this, function(){
- this.expression.walk(w);
- AST_Statement.prototype.walk.call(this, w);
- });
- }
}, AST_SwitchBranch);
/* -----[ EXCEPTIONS ]----- */
var AST_Try = DEFNODE("Try", "btry bcatch bfinally", {
- walk: function(w) {
- w._visit(this, function(){
- this.btry.walk(w);
- if (this.bcatch) this.bcatch.walk(w);
- if (this.bfinally) this.bfinally.walk(w);
- });
- }
});
var AST_Catch = DEFNODE("Catch", "argname body", {
- walk: function(w) {
- w._visit(this, function(){
- this.argname.walk(w);
- this.body.walk(w);
- });
- }
});
-var AST_Finally = DEFNODE("Finally", null, {
-
-}, AST_Bracketed);
+var AST_Finally = DEFNODE("Finally", "body", {
+});
/* -----[ VAR/CONST ]----- */
var AST_Definitions = DEFNODE("Definitions", "definitions", {
- walk: function(w) {
- w._visit(this, function(){
- this.definitions.forEach(function(el){
- el.walk(w);
- });
- });
- }
});
var AST_Var = DEFNODE("Var", null, {
@@ -323,25 +189,11 @@ var AST_Const = DEFNODE("Const", null, {
}, AST_Definitions);
var AST_VarDef = DEFNODE("VarDef", "name value", {
- walk: function(w) {
- w._visit(this, function(){
- this.name.walk(w);
- if (this.value) this.value.walk(w);
- });
- }
});
/* -----[ OTHER ]----- */
var AST_Call = DEFNODE("Call", "expression args", {
- walk: function(w) {
- w._visit(this, function(){
- this.expression.walk(w);
- this.args.forEach(function(el){
- el.walk(w);
- });
- });
- }
});
var AST_New = DEFNODE("New", null, {
@@ -349,12 +201,6 @@ var AST_New = DEFNODE("New", null, {
}, AST_Call);
var AST_Seq = DEFNODE("Seq", "first second", {
- walk: function(w) {
- w._visit(this, function(){
- this.first.walk(w);
- this.second.walk(w);
- });
- }
});
var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
@@ -362,28 +208,12 @@ var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
});
var AST_Dot = DEFNODE("Dot", null, {
- walk: function(w) {
- w._visit(this, function(){
- this.expression.walk(w);
- });
- }
}, AST_PropAccess);
var AST_Sub = DEFNODE("Sub", null, {
- walk: function(w) {
- w._visit(this, function(){
- this.expression.walk(w);
- this.property.walk(w);
- });
- }
}, AST_PropAccess);
var AST_Unary = DEFNODE("Unary", "operator expression", {
- walk: function(w) {
- w._visit(this, function(){
- this.expression.walk(w);
- });
- }
});
var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, {
@@ -395,22 +225,9 @@ var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, {
}, AST_Unary);
var AST_Binary = DEFNODE("Binary", "left operator right", {
- walk: function(w) {
- w._visit(this, function(){
- this.left.walk(w);
- this.right.walk(w);
- });
- }
});
var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", {
- walk: function(w) {
- w._visit(this, function(){
- this.condition.walk(w);
- this.consequent.walk(w);
- this.alternative.walk(w);
- });
- }
});
var AST_Assign = DEFNODE("Assign", null, {
@@ -420,49 +237,20 @@ var AST_Assign = DEFNODE("Assign", null, {
/* -----[ LITERALS ]----- */
var AST_Array = DEFNODE("Array", "elements", {
- walk: function(w) {
- w._visit(this, function(){
- this.elements.forEach(function(el){
- el.walk(w);
- });
- });
- }
});
var AST_Object = DEFNODE("Object", "properties", {
- walk: function(w) {
- w._visit(this, function(){
- this.properties.forEach(function(prop){
- prop.walk(w);
- });
- });
- }
});
var AST_ObjectProperty = DEFNODE("ObjectProperty");
var AST_ObjectKeyVal = DEFNODE("ObjectKeyval", "key value", {
- walk: function(w) {
- w._visit(this, function(){
- this.value.walk(w);
- });
- }
}, AST_ObjectProperty);
var AST_ObjectSetter = DEFNODE("ObjectSetter", "name func", {
- walk: function(w) {
- w._visit(this, function(){
- this.func.walk(w);
- });
- }
}, AST_ObjectProperty);
var AST_ObjectGetter = DEFNODE("ObjectGetter", "name func", {
- walk: function(w) {
- w._visit(this, function(){
- this.func.walk(w);
- });
- }
}, AST_ObjectProperty);
var AST_Symbol = DEFNODE("Symbol", "name", {
@@ -519,31 +307,3 @@ var AST_False = DEFNODE("False", null, {
var AST_True = DEFNODE("True", null, {
value: true
}, AST_Atom);
-
-/* -----[ Walker ]----- */
-
-function TreeWalker(visitor) {
- this.stack = [];
- if (visitor) this.visit = visitor;
-};
-
-TreeWalker.prototype = {
- visit: function(node){},
- parent: function(n) {
- if (n == null) n = 1;
- return this.stack[this.stack.length - n];
- },
- find_parent: function(type) {
- for (var a = this.stack, i = a.length; --i >= 0;)
- if (a[i] instanceof type) return a[i];
- return null;
- },
- _visit: function(node, descend) {
- this.visit(node);
- if (descend) {
- this.stack.push(node);
- descend.call(node);
- this.stack.pop();
- }
- }
-};
diff --git a/lib/node.js b/lib/node.js
index 571cdd80..9dba3c18 100755
--- a/lib/node.js
+++ b/lib/node.js
@@ -12,9 +12,9 @@
};
load_global("./utils.js");
- load_global("./output.js");
load_global("./ast.js");
load_global("./parse.js");
+ load_global("./output.js");
///
@@ -23,11 +23,13 @@
var ast = parse(fs.readFileSync(filename, "utf8"));
console.timeEnd("parse");
- console.time("walk");
- var w = new TreeWalker(function(node){
- console.log(node.TYPE + " [ start: " + node.start.line + ":" + node.start.col + ", end: " + node.end.line + ":" + node.end.col + "]");
- });
- ast.walk(w);
- console.timeEnd("walk");
+ // console.time("walk");
+ // var w = new TreeWalker(function(node){
+ // console.log(node.TYPE + " [ start: " + node.start.line + ":" + node.start.col + ", end: " + node.end.line + ":" + node.end.col + "] " + node.name);
+ // });
+ // ast.walk(w);
+ // console.timeEnd("walk");
+
+ //console.log(JSON.stringify(ast));
})();
diff --git a/lib/output.js b/lib/output.js
index cf17c3e6..52ab39d6 100644
--- a/lib/output.js
+++ b/lib/output.js
@@ -6,12 +6,16 @@ function OutputStream(options) {
space_colon : false,
ascii_only : false,
inline_script : false,
- width : 80
+ width : 80,
+ beautify : true
});
+ function noop() {};
+
var indentation = 0;
var current_col = 0;
var current_line = 0;
+ var current_pos = 0;
var OUTPUT = "";
function to_ascii(str) {
@@ -44,13 +48,6 @@ function OutputStream(options) {
else return '"' + str.replace(/\x22/g, '\\"') + '"';
};
- function print(str) {
- var a = str.split(/\r?\n/), n = a.length;
- current_line += n;
- current_col += a[n - 1].length;
- OUTPUT += str;
- };
-
function encode_string(str) {
var ret = make_string(str);
if (options.inline_script)
@@ -72,60 +69,452 @@ function OutputStream(options) {
return line;
};
- function with_indent(col, cont) {
+ function last_char() {
+ return OUTPUT.charAt(OUTPUT.length - 1);
+ };
+
+ /* -----[ beautification/minification ]----- */
+
+ var might_need_space = false;
+
+ function print(str) {
+ if (might_need_space) {
+ var ch = str.charAt(0);
+ if ((is_identifier_char(last_char()) && (is_identifier_char(ch) || ch == "\\"))
+ || (/[\+\-]$/.test(OUTPUT) && /^[\+\-]/.test(str)))
+ {
+ OUTPUT += " ";
+ current_col++;
+ current_pos++;
+ }
+ }
+ might_need_space = false;
+ var a = str.split(/\r?\n/), n = a.length;
+ current_line += n;
+ current_col += a[n - 1].length;
+ current_pos += str.length;
+ OUTPUT += str;
+ };
+
+ var space = options.beautify ? function() {
+ print(" ");
+ } : function() {
+ might_need_space = true;
+ };
+
+ var indent = options.beautify ? function() {
+ if (options.beautify) {
+ print(make_indent());
+ }
+ } : noop;
+
+ var with_indent = options.beautify ? function(col, cont) {
if (col === true) col = next_indent();
var save_indentation = indentation;
indentation = col;
var ret = cont();
indentation = save_indentation;
return ret;
- };
+ } : function(col, cont) { return cont() };
- function indent() {
- print(make_indent());
- };
-
- function newline() {
+ var newline = options.indent ? function() {
print("\n");
- };
+ } : noop;
function next_indent() {
return indentation + options.indent_level;
};
- function with_block(cont, beautify) {
+ function with_block(cont) {
var ret;
print("{");
+ newline();
with_indent(next_indent(), function(){
- if (beautify) newline();
ret = cont();
- if (beautify) newline();
});
- if (beautify) indent();
+ newline();
+ indent();
print("}");
return ret;
};
- function with_parens(cont, beautify) {
+ function with_parens(cont) {
print("(");
var ret = with_indent(current_col, cont);
print(")");
return ret;
};
+ function with_square(cont) {
+ print("[");
+ var ret = with_indent(current_col, cont);
+ print("]");
+ return ret;
+ };
+
+ function semicolon() {
+ print(";");
+ };
+
+ function comma() {
+ print(",");
+ space();
+ };
+
+ function colon() {
+ print(":");
+ space();
+ };
+
return {
- get : function() { return OUTPUT },
- indent : indent,
- newline : newline,
- print : print,
- string : function(str) { print(encode_string(str)) },
- with_indent : with_indent,
- with_block : with_block,
- with_parens : with_parens,
- options : function() { return options },
- line : function() { return current_line },
- col : function() { return current_col },
- pos : function() { return OUTPUT.length }
+ get : function() { return OUTPUT },
+ indent : indent,
+ newline : newline,
+ print : print,
+ space : space,
+ comma : comma,
+ colon : colon,
+ print_name : function(name) { print(make_name(name)) },
+ print_string : function(str) { print(encode_string(str)) },
+ with_indent : with_indent,
+ with_block : with_block,
+ with_parens : with_parens,
+ with_square : with_square,
+ options : function() { return options },
+ line : function() { return current_line },
+ col : function() { return current_col },
+ pos : function() { return current_pos }
};
};
+
+/* -----[ code generators ]----- */
+
+(function(DEF){
+ DEF(AST_Directive, function(self, output){
+ output.print_string(self.value);
+ });
+ DEF(AST_Debugger, function(self, output){
+ output.print_string("debugger");
+ });
+ DEF(AST_Parenthesized, function(self, output){
+ output.with_parens(function(){
+ self.expression.print(output);
+ });
+ });
+ DEF(AST_Bracketed, function(self, output){
+ output.with_block(function(){
+ self.body.forEach(function(stmt){
+ output.indent();
+ stmt.print(output);
+ });
+ });
+ });
+ /* -----[ statements ]----- */
+ DEF(AST_LabeledStatement, function(self, output){
+ output.print(self.label + ":");
+ output.space();
+ self.statement.print(output);
+ });
+ DEF(AST_SimpleStatement, function(self, output){
+ self.body.print(output);
+ output.semicolon();
+ });
+ DEF(AST_BlockStatement, function(self, output){
+ AST_Bracketed.prototype.print.call(self, output);
+ });
+ DEF(AST_EmptyStatement, function(self, output){
+ // do nothing here?
+ // output.semicolon();
+ });
+ DEF(AST_Do, function(self, output){
+ output.print("do");
+ output.space();
+ self.body.print(output);
+ output.space();
+ output.print("while");
+ self.condition.print(output);
+ self.semicolon();
+ });
+ DEF(AST_For, function(self, output){
+ output.print("for");
+ output.space();
+ output.with_parens(function(){
+ self.init.print(output);
+ output.semicolon();
+ self.condition.print(output);
+ output.semicolon();
+ self.step.print(output);
+ });
+ output.space();
+ self.body.print(output);
+ });
+ DEF(AST_ForIn, function(self, output){
+ output.print("for");
+ output.space();
+ output.with_parens(function(){
+ if (self.init) {
+ self.init.print(output);
+ } else {
+ self.name.print(output);
+ }
+ output.print(" in ");
+ self.object.print(output);
+ });
+ output.space();
+ self.body.print(output);
+ });
+ DEF(AST_With, function(self, output){
+ output.print("with");
+ output.space();
+ output.with_parens(function(){
+ self.expression.print(output);
+ });
+ output.space();
+ self.body.print(output);
+ });
+ /* -----[ functions ]----- */
+ DEF(AST_Lambda, function(self, output){
+ output.print("function");
+ output.space();
+ if (self.name) {
+ self.name.print(output);
+ output.space();
+ }
+ output.with_parens(function(){
+ self.argnames.forEach(function(arg, i){
+ if (i) output.comma();
+ arg.print(output);
+ });
+ });
+ output.space();
+ self.body.print(output);
+ });
+ /* -----[ exits ]----- */
+ AST_Exit.DEFMETHOD("_do_print", function(output, kind){
+ output.print(kind);
+ output.space();
+ self.value.print(output);
+ output.semicolon();
+ });
+ DEF(AST_Return, function(self, output){
+ self._do_print(output, "return");
+ });
+ DEF(AST_Throw, function(self, output){
+ self._do_print(output, "throw");
+ });
+ /* -----[ loop control ]----- */
+ AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){
+ output.print(kind);
+ if (self.label) {
+ output.space();
+ self.label.print(output);
+ }
+ output.semicolon();
+ });
+ DEF(AST_Break, function(self, output){
+ self._do_print(output, "break");
+ });
+ DEF(AST_Continue, function(self, output){
+ self._do_print(output, "continue");
+ });
+ /* -----[ if ]----- */
+ DEF(AST_If, function(self, output){
+ output.print("if");
+ output.space();
+ output.with_parens(function(){
+ self.condition.print(output);
+ });
+ output.space();
+ self.consequent.print(output);
+ if (self.alternative) {
+ output.space();
+ self.alternative.print(output);
+ }
+ });
+ /* -----[ switch ]----- */
+ DEF(AST_Switch, function(self, output){
+ output.print("switch");
+ output.space();
+ output.with_parens(function(){
+ self.expression.print(output);
+ });
+ output.space();
+ self.body.print(output);
+ });
+ AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){
+ self.body.forEach(function(stmt){
+ output.indent();
+ stmt.print(output);
+ output.newline();
+ });
+ });
+ DEF(AST_Default, function(self, output){
+ output.print("default:");
+ output.newline();
+ self._do_print_body(output);
+ });
+ DEF(AST_Case, function(self, output){
+ output.print("case");
+ output.space();
+ self.expression.print(output);
+ output.print(":");
+ output.newline();
+ self._do_print_body(output);
+ });
+ /* -----[ exceptions ]----- */
+ DEF(AST_Try, function(self, output){
+ output.print("try");
+ output.space();
+ self.btry.print(output);
+ if (self.bcatch) {
+ output.space();
+ self.bcatch.print(output);
+ }
+ if (self.bfinally) {
+ output.space();
+ self.bfinally.print(output);
+ }
+ });
+ DEF(AST_Catch, function(self, output){
+ output.print("catch");
+ output.space();
+ self.body.print(output);
+ });
+ DEF(AST_Finally, function(self, output){
+ output.print("finally");
+ output.space();
+ self.body.print(output);
+ });
+ /* -----[ var/const ]----- */
+ AST_Definitions.DEFMETHOD("_do_print", function(output, kind){
+ output.print(kind);
+ output.space();
+ self.definitions.forEach(function(def, i){
+ if (i) output.space();
+ def.print(output);
+ });
+ output.semicolon();
+ });
+ DEF(AST_Var, function(self, output){
+ self._do_print(output, "var");
+ });
+ DEF(AST_Const, function(self, output){
+ self._do_print(output, "const");
+ });
+ DEF(AST_VarDef, function(self, output){
+ self.name.print(output);
+ if (self.value) {
+ output.space();
+ output.print("=");
+ output.space();
+ self.value.print(output);
+ }
+ });
+ /* -----[ other expressions ]----- */
+ DEF(AST_Call, function(self, output){
+ self.expression.print(output);
+ output.with_parens(function(){
+ self.args.forEach(function(arg, i){
+ if (i) output.comma();
+ arg.print(output);
+ });
+ });
+ });
+ DEF(AST_New, function(self, output){
+ output.print("new");
+ output.space();
+ AST_Call.prototype.print.call(self, output);
+ });
+ DEF(AST_Seq, function(self, output){
+ self.first.print(output);
+ output.comma();
+ self.second.print(output);
+ });
+ DEF(AST_Dot, function(self, output){
+ self.expression.print(output);
+ output.print(".");
+ output.print_name(self.property);
+ });
+ DEF(AST_Sub, function(self, output){
+ self.expression.print(output);
+ output.print("[");
+ self.property.print(output);
+ output.print("]");
+ });
+ DEF(AST_UnaryPrefix, function(self, output){
+ output.print(self.operator);
+ self.expression.print(output);
+ });
+ DEF(AST_UnaryPostfix, function(self, output){
+ self.expression.print(output);
+ output.print(self.operator);
+ });
+ DEF(AST_Binary, function(self, output){
+ self.left.print(output);
+ output.print(self.operator);
+ self.right.print(output);
+ });
+ DEF(AST_Conditional, function(self, output){
+ self.condition.print(output);
+ output.space();
+ output.print("?");
+ output.space();
+ self.consequent.print(output);
+ output.colon();
+ self.alternative.print(output);
+ });
+ /* -----[ literals ]----- */
+ DEF(AST_Array, function(self, output){
+ output.with_square(function(){
+ self.elements.forEach(function(exp, i){
+ if (i) output.comma();
+ exp.print(output);
+ });
+ });
+ });
+ DEF(AST_Object, function(self, output){
+ output.with_block(function(){
+ self.properties.forEach(function(prop, i){
+ if (i) output.comma();
+ prop.print(output);
+ });
+ });
+ });
+ DEF(AST_ObjectKeyVal, function(self, output){
+ output.print_name(self.key);
+ output.colon();
+ self.value.print(output);
+ });
+ DEF(AST_ObjectSetter, function(self, output){
+ throw "not yet done";
+ });
+ DEF(AST_ObjectGetter, function(self, output){
+ throw "not yet done";
+ });
+ DEF(AST_Symbol, function(self, output){
+ output.print_name(self.name);
+ });
+ DEF(AST_This, function(self, output){
+ output.print("this");
+ });
+ DEF(AST_Label, function(self, output){
+ output.print_name(self.name);
+ });
+ DEF(AST_Constant, function(self, output){
+ output.print(self.getValue());
+ });
+ DEF(AST_String, function(self, output){
+ output.print_string(self.getValue());
+ });
+ DEF(AST_RegExp, function(self, output){
+ output.print("/");
+ output.print(self.pattern);
+ output.print("/");
+ if (self.mods) output.print(self.mods);
+ });
+})(function DEF(nodetype, generator) {
+ nodetype.DEFMETHOD("print", function(stream){
+ generator(this, stream);
+ });
+});
diff --git a/lib/parse.js b/lib/parse.js
index 2cd160fa..fdf44ce3 100644
--- a/lib/parse.js
+++ b/lib/parse.js
@@ -833,15 +833,12 @@ function parse($TEXT, exigent_mode) {
expect(":");
S.labels.push(label);
var start = S.token, stat = statement();
- if (exigent_mode && !(stat instanceof AST_LabeledStatement))
- unexpected(start);
S.labels.pop();
- stat.label = label;
- return stat;
+ return new AST_LabeledStatement({ statement: stat });
};
function simple_statement() {
- return new AST_Statement({ body: prog1(expression, semicolon) });
+ return new AST_SimpleStatement({ body: prog1(expression, semicolon) });
};
function break_cont(type) {
@@ -1024,7 +1021,11 @@ function parse($TEXT, exigent_mode) {
next();
bfinally = new AST_Finally({
start : start,
- body : block_(),
+ body : new AST_Bracketed({
+ start : S.token,
+ body : block_(),
+ end : prev()
+ }),
end : prev()
});
}