aboutsummaryrefslogtreecommitdiff
path: root/lib/parse.js
diff options
context:
space:
mode:
authorMihai Bazon <mihai@bazon.net>2012-08-19 15:57:50 +0300
committerMihai Bazon <mihai@bazon.net>2012-08-19 15:57:50 +0300
commit6c35135ace95bb90c33cadeb8c16a43415eef454 (patch)
treee0458c73d79bf7bbb360b8ada938d794d683331f /lib/parse.js
parent4488758d485b0b624d4858f764bdf08b10365d3b (diff)
downloadtracifyjs-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.js51
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