diff options
Diffstat (limited to 'lib/ast.js')
-rw-r--r-- | lib/ast.js | 69 |
1 files changed, 51 insertions, 18 deletions
@@ -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); |