simple visitor API and code to figure out scope and references

This commit is contained in:
Mihai Bazon
2012-08-19 15:57:50 +03:00
parent 4488758d48
commit 6c35135ace
6 changed files with 474 additions and 102 deletions

View File

@@ -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