diff options
author | Mihai Bazon <mihai@bazon.net> | 2012-08-19 15:57:50 +0300 |
---|---|---|
committer | Mihai Bazon <mihai@bazon.net> | 2012-08-19 15:57:50 +0300 |
commit | 6c35135ace95bb90c33cadeb8c16a43415eef454 (patch) | |
tree | e0458c73d79bf7bbb360b8ada938d794d683331f /lib/parse.js | |
parent | 4488758d485b0b624d4858f764bdf08b10365d3b (diff) | |
download | tracifyjs-6c35135ace95bb90c33cadeb8c16a43415eef454.tar.gz tracifyjs-6c35135ace95bb90c33cadeb8c16a43415eef454.zip |
simple visitor API and code to figure out scope and references
Diffstat (limited to 'lib/parse.js')
-rw-r--r-- | lib/parse.js | 51 |
1 files changed, 30 insertions, 21 deletions
diff --git a/lib/parse.js b/lib/parse.js index f5796b0f..78b8bb7c 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -836,7 +836,14 @@ function parse($TEXT, exigent_mode) { }); function labeled_statement() { - var label = as_symbol(true); + var label = as_symbol(AST_Label); + if (find_if(function(l){ return l.name == label.name }, S.labels)) { + // ECMA-262, 12.12: An ECMAScript program is considered + // syntactically incorrect if it contains a + // LabelledStatement that is enclosed by a + // LabelledStatement with the same Identifier as label. + croak("Label " + label.name + " defined twice"); + } expect(":"); S.labels.push(label); var start = S.token, stat = statement(); @@ -849,16 +856,13 @@ function parse($TEXT, exigent_mode) { }; function break_cont(type) { - var name = null, label = null; + var label = null; if (!can_insert_semicolon()) { - name = is("name") ? S.token.value : null; + label = as_symbol(AST_LabelRef, true); } - if (name != null) { - next(); - label = find_if(function(l){ return l.name == name }, S.labels); - if (!label) - croak("Label " + name + " without matching loop or statement"); - label = new AST_Label({ name: name, symbol: label }); + if (label != null) { + if (!find_if(function(l){ return l.name == label.name }, S.labels)) + croak("Undefined label " + label.name); } else if (S.in_loop == 0) croak(type.TYPE + " not inside a loop or switch"); @@ -910,7 +914,9 @@ function parse($TEXT, exigent_mode) { }; var function_ = function(in_statement) { - var name = is("name") ? as_symbol(true) : null; + var name = is("name") ? as_symbol(in_statement + ? AST_SymbolDefun + : AST_SymbolLambda) : null; if (in_statement && !name) unexpected(); expect("("); @@ -920,7 +926,7 @@ function parse($TEXT, exigent_mode) { argnames: (function(first, a){ while (!is("punc", ")")) { if (first) first = false; else expect(","); - a.push(as_symbol(true)); + a.push(as_symbol(AST_SymbolFunarg)); } next(); return a; @@ -1010,7 +1016,7 @@ function parse($TEXT, exigent_mode) { var start = S.token; next(); expect("("); - var name = as_symbol(true); + var name = as_symbol(AST_SymbolCatch); expect(")"); bcatch = new AST_Catch({ start : start, @@ -1050,7 +1056,7 @@ function parse($TEXT, exigent_mode) { for (;;) { a.push(new AST_VarDef({ start : S.token, - name : as_symbol(true), + name : as_symbol(AST_SymbolVar), value : is("operator", "=") ? (next(), expression(false, no_in)) : null, end : prev() })); @@ -1099,7 +1105,7 @@ function parse($TEXT, exigent_mode) { var tok = S.token, ret; switch (tok.type) { case "name": - return as_symbol(); + return as_symbol(AST_SymbolRef); case "num": ret = new AST_Number({ start: tok, end: tok, value: tok.value }); break; @@ -1198,8 +1204,8 @@ function parse($TEXT, exigent_mode) { if (name == "get") { a.push(new AST_ObjectGetter({ start : start, - name : name, - func : function_(false), + key : name, + value : function_(false), end : prev() })); continue; @@ -1207,8 +1213,8 @@ function parse($TEXT, exigent_mode) { if (name == "set") { a.push(new AST_ObjectSetter({ start : start, - name : name, - func : function_(false), + key : name, + value : function_(false), end : prev() })); continue; @@ -1252,10 +1258,13 @@ function parse($TEXT, exigent_mode) { } }; - function as_symbol(def) { - if (!is("name")) croak("Name expected"); + function as_symbol(type, noerror) { + if (!is("name")) { + if (!noerror) croak("Name expected"); + return null; + } var name = S.token.value; - var sym = new (name == "this" ? AST_This : def ? AST_Symbol : AST_SymbolRef)({ + var sym = new (name == "this" ? AST_This : type)({ name : String(S.token.value), start : S.token, end : S.token |