aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/ast.js69
-rw-r--r--lib/compress.js4
-rw-r--r--lib/output.js2
-rw-r--r--lib/parse.js2
-rwxr-xr-xtest/run-tests.js4
5 files changed, 57 insertions, 24 deletions
diff --git a/lib/ast.js b/lib/ast.js
index d0acbb41..c93ed4f3 100644
--- a/lib/ast.js
+++ b/lib/ast.js
@@ -41,6 +41,8 @@
***********************************************************************/
+var NODE_HIERARCHY = {};
+
function DEFNODE(type, props, methods, base) {
if (arguments.length < 4) base = AST_Node;
if (!props) props = [];
@@ -73,6 +75,10 @@ function DEFNODE(type, props, methods, base) {
ctor.DEFMETHOD = function(name, method) {
this.prototype[name] = method;
};
+ NODE_HIERARCHY[type] = {
+ def: ctor,
+ base: base
+ };
return ctor;
};
@@ -108,16 +114,6 @@ var AST_Directive = DEFNODE("Directive", "value", {
/* -----[ loops ]----- */
-var AST_LabeledStatement = DEFNODE("LabeledStatement", "label statement", {
- $documentation: "Statement with a label",
- _walk: function(visitor) {
- return visitor._visit(this, function(){
- this.label._walk(visitor);
- this.statement._walk(visitor);
- });
- }
-});
-
var AST_Statement = DEFNODE("Statement", "body", {
$documentation: "Base class of all statements",
_walk: function(visitor) {
@@ -153,6 +149,16 @@ var AST_StatementWithBody = DEFNODE("StatementWithBody", null, {
$documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`."
}, AST_Statement);
+var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
+ $documentation: "Statement with a label",
+ _walk: function(visitor) {
+ return visitor._visit(this, function(){
+ this.label._walk(visitor);
+ this.body._walk(visitor);
+ });
+ }
+}, AST_StatementWithBody);
+
var AST_DWLoop = DEFNODE("DWLoop", "condition", {
$documentation: "Base class for do/while statements.",
_walk: function(visitor) {
@@ -434,9 +440,11 @@ var AST_Seq = DEFNODE("Seq", "first second", {
});
var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
+ $documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`"
});
var AST_Dot = DEFNODE("Dot", null, {
+ $documentation: "A dotted property access expression",
_walk: function(visitor) {
return visitor._visit(this, function(){
this.expression._walk(visitor);
@@ -445,6 +453,7 @@ var AST_Dot = DEFNODE("Dot", null, {
}, AST_PropAccess);
var AST_Sub = DEFNODE("Sub", null, {
+ $documentation: "Index-style property access, i.e. `a[\"foo\"]`",
_walk: function(visitor) {
return visitor._visit(this, function(){
this.expression._walk(visitor);
@@ -454,6 +463,7 @@ var AST_Sub = DEFNODE("Sub", null, {
}, AST_PropAccess);
var AST_Unary = DEFNODE("Unary", "operator expression", {
+ $documentation: "Base class for unary expressions",
_walk: function(visitor) {
return visitor._visit(this, function(){
this.expression._walk(visitor);
@@ -462,12 +472,15 @@ var AST_Unary = DEFNODE("Unary", "operator expression", {
});
var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, {
+ $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`"
}, AST_Unary);
var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, {
+ $documentation: "Unary postfix expression, i.e. `i++`"
}, AST_Unary);
var AST_Binary = DEFNODE("Binary", "left operator right", {
+ $documentation: "Binary expression, i.e. `a + b`",
_walk: function(visitor) {
return visitor._visit(this, function(){
this.left._walk(visitor);
@@ -477,6 +490,7 @@ var AST_Binary = DEFNODE("Binary", "left operator right", {
});
var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", {
+ $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`",
_walk: function(visitor) {
return visitor._visit(this, function(){
this.condition._walk(visitor);
@@ -487,11 +501,13 @@ var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative",
});
var AST_Assign = DEFNODE("Assign", "left operator right", {
+ $documentation: "An assignment expression — `a = b + 5`",
}, AST_Binary);
/* -----[ LITERALS ]----- */
var AST_Array = DEFNODE("Array", "elements", {
+ $documentation: "An array literal",
_walk: function(visitor) {
return visitor._visit(this, function(){
this.elements.forEach(function(el){
@@ -502,6 +518,7 @@ var AST_Array = DEFNODE("Array", "elements", {
});
var AST_Object = DEFNODE("Object", "properties", {
+ $documentation: "An object literal",
_walk: function(visitor) {
return visitor._visit(this, function(){
this.properties.forEach(function(prop){
@@ -512,6 +529,7 @@ var AST_Object = DEFNODE("Object", "properties", {
});
var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
+ $documentation: "Base class for literal object properties",
_walk: function(visitor) {
return visitor._visit(this, function(){
this.value._walk(visitor);
@@ -520,89 +538,104 @@ var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
});
var AST_ObjectKeyVal = DEFNODE("ObjectKeyval", null, {
+ $documentation: "A key: value object property",
}, AST_ObjectProperty);
var AST_ObjectSetter = DEFNODE("ObjectSetter", null, {
+ $documentation: "An object setter property",
}, AST_ObjectProperty);
var AST_ObjectGetter = DEFNODE("ObjectGetter", null, {
+ $documentation: "An object getter property",
}, AST_ObjectProperty);
var AST_Symbol = DEFNODE("Symbol", "scope name global undeclared", {
+ $documentation: "Base class for all symbols",
});
var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "references", {
+ $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
}, AST_Symbol);
var AST_SymbolVar = DEFNODE("SymbolVar", null, {
- $documentation: "Symbol defining a variable or constant"
+ $documentation: "Symbol defining a variable or constant",
}, AST_SymbolDeclaration);
var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
- $documentation: "Symbol naming a function argument"
+ $documentation: "Symbol naming a function argument",
}, AST_SymbolVar);
var AST_SymbolDefun = DEFNODE("SymbolDefun", null, {
- $documentation: "Symbol defining a function"
+ $documentation: "Symbol defining a function",
}, AST_SymbolDeclaration);
var AST_SymbolLambda = DEFNODE("SymbolLambda", null, {
- $documentation: "Symbol naming a function expression"
+ $documentation: "Symbol naming a function expression",
}, AST_SymbolDeclaration);
var AST_SymbolCatch = DEFNODE("SymbolCatch", null, {
- $documentation: "Symbol naming the exception in catch"
+ $documentation: "Symbol naming the exception in catch",
}, AST_SymbolDeclaration);
var AST_Label = DEFNODE("Label", null, {
- $documentation: "Symbol naming a label (declaration)"
+ $documentation: "Symbol naming a label (declaration)",
}, AST_SymbolDeclaration);
var AST_SymbolRef = DEFNODE("SymbolRef", "symbol", {
- $documentation: "Reference to some symbol (not definition/declaration)"
+ $documentation: "Reference to some symbol (not definition/declaration)",
}, AST_Symbol);
var AST_LabelRef = DEFNODE("LabelRef", null, {
- $documentation: "Reference to a label symbol"
+ $documentation: "Reference to a label symbol",
}, AST_SymbolRef);
var AST_This = DEFNODE("This", null, {
+ $documentation: "The `this` symbol",
}, AST_Symbol);
var AST_Constant = DEFNODE("Constant", null, {
+ $documentation: "Base class for all constants",
getValue: function() {
return this.value;
}
});
var AST_String = DEFNODE("String", "value", {
+ $documentation: "A string literal",
}, AST_Constant);
var AST_Number = DEFNODE("Number", "value", {
+ $documentation: "A number literal",
}, AST_Constant);
var AST_RegExp = DEFNODE("Regexp", "pattern mods", {
+ $documentation: "A regexp literal",
initialize: function() {
this.value = new RegExp(this.pattern, this.mods);
}
}, AST_Constant);
var AST_Atom = DEFNODE("Atom", null, {
+ $documentation: "Base class for atoms",
}, AST_Constant);
var AST_Null = DEFNODE("Null", null, {
+ $documentation: "The `null` atom",
value: null
}, AST_Atom);
var AST_Undefined = DEFNODE("Undefined", null, {
+ $documentation: "The `undefined` value",
value: (function(){}())
}, AST_Atom);
var AST_False = DEFNODE("False", null, {
+ $documentation: "The `false` atom",
value: false
}, AST_Atom);
var AST_True = DEFNODE("True", null, {
+ $documentation: "The `true` atom",
value: true
}, AST_Atom);
diff --git a/lib/compress.js b/lib/compress.js
index 5dbe60b0..04d5720b 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -113,8 +113,8 @@ function Compressor(options, false_by_default) {
SQUEEZE(AST_LabeledStatement, function(self, compressor){
self = self.clone();
- self.statement = self.statement.squeeze(compressor);
- return self.label.references.length == 0 ? self.statement : self;
+ self.body = self.body.squeeze(compressor);
+ return self.label.references.length == 0 ? self.body : self;
});
SQUEEZE(AST_Statement, function(self, compressor){
diff --git a/lib/output.js b/lib/output.js
index 6d86a087..810a66a1 100644
--- a/lib/output.js
+++ b/lib/output.js
@@ -457,7 +457,7 @@ function OutputStream(options) {
DEFPRINT(AST_LabeledStatement, function(self, output){
self.label.print(output);
output.colon();
- self.statement.print(output);
+ self.body.print(output);
});
DEFPRINT(AST_SimpleStatement, function(self, output){
self.body.print(output);
diff --git a/lib/parse.js b/lib/parse.js
index 416c363a..9c3f3fb1 100644
--- a/lib/parse.js
+++ b/lib/parse.js
@@ -892,7 +892,7 @@ function parse($TEXT, exigent_mode) {
S.labels.push(label);
var start = S.token, stat = statement();
S.labels.pop();
- return new AST_LabeledStatement({ statement: stat, label: label });
+ return new AST_LabeledStatement({ body: stat, label: label });
};
function simple_statement() {
diff --git a/test/run-tests.js b/test/run-tests.js
index 52018329..1f554e11 100755
--- a/test/run-tests.js
+++ b/test/run-tests.js
@@ -81,7 +81,7 @@ function parse_test(file) {
if (node instanceof U.AST_LabeledStatement
&& tw.parent() instanceof U.AST_Toplevel) {
var name = node.label.name;
- tests[name] = get_one_test(name, node.statement);
+ tests[name] = get_one_test(name, node.body);
return true;
}
if (!(node instanceof U.AST_Toplevel)) croak(node);
@@ -118,7 +118,7 @@ function parse_test(file) {
col: node.label.start.col
})
);
- var stat = node.statement;
+ var stat = node.body;
if (stat instanceof U.AST_BlockStatement)
stat.required = 1;
test[node.label.name] = stat;