this.scopes = [];
this.indexedScopes = {};
this.timer = new Date() * 1;
-
+ this.debug = false;
}
// list of keywords that should not be used in object literals.
},
warn: function(s) {
+ //print('****************' + s);
this.warnings.push(s);
//println("WARNING:" + htmlescape(s) + "<BR>");
},
this.mode = 'BUILDING_SYMBOL_TREE';
this.parseScope(this.globalScope);
+
+ //print("---------------END PASS 1 ---------------- ");
+
},
mungeSymboltree : function()
{
this.ts.rewind();
this.braceNesting = 0;
this.scopes= [];
- this.mode = 'CHECKING_SYMBOL_TREE';
+ this.mode = 'PASS2_SYMBOL_TREE';
//println("MUNGING?");
log : function(str)
{
- //println("<B>LOG:</B>" + htmlescape(str) + "<BR/>\n");
+ print (" ".substring(0, this.braceNesting*2) + str);
+
+ //println("<B>LOG:</B>" + htmlescape(str) + "<BR/>\n");
},
logR : function(str)
{
parseScope : function(scope) // parse a token stream..
{
//this.timerPrint("parseScope EnterScope");
+ //this.log(">>> ENTER SCOPE" + this.scopes.length);
var symbol;
var token;
var identifier;
var expressionBraceNesting = this.braceNesting;
- var bracketNesting = 0;
+
var parensNesting = 0;
var isObjectLitAr = [ false ];
-
+ var isInObjectLitAr;
this.scopes.push(scope);
token = this.ts.lookTok(1);
while (token) {
// this.timerPrint("parseScope AFTER lookT: " + token.toString());
- print(token.type + '.' + token.name+ ":" + token.data);
+ //this.log(token.data);
+ if (token.type == 'NAME') {
+ // print('*' + token.data);
+ }
switch(token.type + '.' + token.name) {
case "KEYW.VAR":
case "KEYW.CONST": // not really relivant as it's only mozzy that does this.
//this.log("parseScope GOT VAR/CONST : " + token.toString());
while (true) {
token = this.ts.nextTok();
-
- if (token.name == "VAR") { // kludge..
- continue;
- }
+ !this.debug|| print( token.toString());
+
if (!token) { // can return false at EOF!
break;
}
+ if (token.name == "VAR" || token.data == ',') { // kludge..
+ continue;
+ }
//this.logR("parseScope GOT VAR : <B>" + token.toString() + "</B>");
if (token.type !="NAME") {
- println(token.toString());
- throw "var without ident";
+ for(var i = Math.max(this.ts.cursor-10,0); i < this.ts.cursor+1; i++) {
+ print(this.ts.tokens[i].toString());
+ }
+
+ print( "var without ident");
+ Seed.quit()
}
scope.declareIdentifier(token.data, token);
} else {
token.identifier = identifier;
- this.warn("The variable " + token.data + ' (line:' + token.line + ") has already been declared in the same scope...");
+ this.warn("(SCOPE) The variable " + token.data + ' (line:' + token.line + ") has already been declared in the same scope...");
}
}
token = this.ts.nextTok();
+ !this.debug|| print(token.toString());
/*
assert token.getType() == Token.SEMI ||
token.getType() == Token.ASSIGN ||
if (token.name == "IN") {
break;
} else {
+ //var bn = this.braceNesting;
this.parseExpression();
+ //this.braceNesting = bn;
//this.logR("parseScope DONE : <B>ParseExpression</B> - tok is:" + this.ts.lookT(0).toString());
-
- if (this.ts.lookTok(0).data == ';') {
+ token = this.ts.lookTok(1);
+ !this.debug|| print("AFTER EXP: " + token.toString());
+ if (token.data == ';') {
break;
}
}
break;
case "KEYW.FUNCTION":
//println("<i>"+token.data+"</i>");
+ var bn = this.braceNesting;
this.parseFunctionDeclaration();
+ this.braceNesting = bn;
break;
- case "KEYW.LEFT_CURLY": // {
+ case "PUNC.LEFT_CURLY": // {
//println("<i>"+token.data+"</i>");
isObjectLitAr.push(false);
this.braceNesting++;
+
+ //print(">>>>>> OBJLIT PUSH(false)" + this.braceNesting);
break;
- case "KEYW.RIGHT_CURLY": // }
+ case "PUNC.RIGHT_CURLY": // }
//println("<i>"+token.data+"</i>");
this.braceNesting--;
isObjectLitAr.pop();
- //assert braceNesting >= scope.getBraceNesting();
- if (this.braceNesting == scope.braceN) {
+ //print(">>>>>> OBJLIT POP"+ this.braceNesting);
+ //assert braceNesting >= scope.getBra ceNesting();
+
+ if (this.braceNesting < expressionBraceNesting) {
var ls = this.scopes.pop();
ls.getUsedSymbols();
+ // eat symbol if we are currently at {
+ if (this.ts.look(0).data == '{') {
+ this.ts.nextTok();
+ }
+
+ //print("<<<<<<<EXIT SCOPE" +this.scopes.length);
return;
}
break;
// then we are in an object lit.. -> we need to flag the brace as such...
isObjectLitAr.pop();
isObjectLitAr.push(true);
+ //print(">>>>>> OBJLIT REPUSH(true)");
}
- var isInObjectLitAr = isObjectLitAr[isObjectLitAr.length-1];
+ isInObjectLitAr = isObjectLitAr[isObjectLitAr.length-1];
if (isInObjectLitAr && this.ts.lookTok(1).data == ':' &&
( this.ts.lookTok(-1).data == '{' || this.ts.lookTok(-1).data == ':' )) {
if ((this.ts.lookTok(-1).data == "{") && (this.ts.lookTok(1).data == ":")) {
isObjectLitAr.pop();
isObjectLitAr.push(true);
+ //print(">>>>>> OBJLIT REPUSH(true)");
//println("<i>"+token.data+"</i>");
break;
}
// print("DEAL WITH obj lit:");
- var isInObjectLitAr = isObjectLitAr[isObjectLitAr.length-1];
+ isInObjectLitAr = isObjectLitAr[isObjectLitAr.length-1];
if (isInObjectLitAr && (this.ts.lookTok(1).data == ":") && (this.ts.lookTok(-1).data == ",")) {
// skip, it's an object lit key..
break;
}
symbol = token.data;
- if (this.mode == 'CHECKING_SYMBOL_TREE') {
+ if (this.mode == 'PASS2_SYMBOL_TREE') {
//println("GOT IDENT: -2 : " + this.ts.lookT(-2).toString() + " <BR> ..... -1 : " + this.ts.lookT(-1).toString() + " <BR> ");
-
+ //print ("MUNGE?" + symbol);
//println("GOT IDENT: <B>" + symbol + "</B><BR/>");
//if (this.ts.nextT()) break;
}
+ //print("<<<<<<<EXIT SCOPE ERR?" +this.scopes.length);
},
// in the same brace nesting, bracket nesting and paren nesting.
// Parse functions if any...
//println("<i>EXP</i><BR/>");
+ !this.debug || print("PARSE EXPR");
var symbol;
var token;
var currentScope;
var expressionBraceNesting = this.braceNesting;
var bracketNesting = 0;
var parensNesting = 0;
-
+ var isInObjectLitAr;
var isObjectLitAr = [ false ];
while (token = this.ts.lookTok()) {
currentScope = this.scopes[this.scopes.length-1];
//println("<i>"+token.data+"</i>");
-
- switch (token.data.toUpperCase()) {
-
- case ';':
- case ',':
- if (this.braceNesting == expressionBraceNesting &&
- bracketNesting == 0 &&
- parensNesting == 0) {
- return;
- }
- break;
+ //this.log("EXP:" + token.data);
+ switch (token.type) {
+ case 'PUNC':
+ switch(token.data) {
+
+ case ';':
+ case ',':
+ if (this.braceNesting == expressionBraceNesting &&
+ bracketNesting == 0 &&
+ parensNesting == 0) {
+
+ return;
+ }
+ break;
- case 'FUNCTION':
- this.parseFunctionDeclaration();
- break;
+
- case '{': //Token.LC:
- isObjectLitAr.push(false);
-
- this.braceNesting++;
- break;
+ case '{': //Token.LC:
+ isObjectLitAr.push(false);
+
+ this.braceNesting++;
+ ///print(">>>>> EXP PUSH(false)"+this.braceNesting);
+ break;
- case '}': //Token.RC:
- this.braceNesting--;
- isObjectLitAr.pop();
-
- // assert braceNesting >= expressionBraceNesting;
- break;
+ case '}': //Token.RC:
+ this.braceNesting--;
+ isObjectLitAr.pop();
+ //print(">>>>> EXP POP" + this.braceNesting);
+ // assert braceNesting >= expressionBraceNesting;
+ break;
- case '[': //Token.LB:
- bracketNesting++;
- break;
+ case '[': //Token.LB:
+ bracketNesting++;
+ break;
- case ']': //Token.RB:
- bracketNesting--;
- break;
+ case ']': //Token.RB:
+ bracketNesting--;
+ break;
- case '(': //Token.LP:
- parensNesting++;
- break;
+ case '(': //Token.LP:
+ parensNesting++;
+ break;
- case ')': //Token.RP:
- parensNesting--;
+ case ')': //Token.RP:
+ parensNesting--;
+ break;
+ }
break;
- }
- switch(token.type) {
-
+
case 'STRN': // used for object lit detection..
if (this.ts.lookTok(-1).data == "{" && this.ts.lookTok(1).data == ":" ) {
// then we are in an object lit.. -> we need to flag the brace as such...
isObjectLitAr.pop();
isObjectLitAr.push(true);
+ //print(">>>>> EXP PUSH(true)");
}
- var isInObjectLitAr = isObjectLitAr[isObjectLitAr.length-1];
+ isInObjectLitAr = isObjectLitAr[isObjectLitAr.length-1];
if (isInObjectLitAr && this.ts.lookTok(1).data == ":" &&
( this.ts.lookTok(-1).data == "{" || this.ts.lookTok(-1).data == "," )) {
// see if we can replace..
break;
-
-
- /*
- case Token.SPECIALCOMMENT:
- if (mode == BUILDING_SYMBOL_TREE) {
- protectScopeFromObfuscation(currentScope);
- this.warn("Using JScript conditional comments is not recommended." + (munge ? " Moreover, using JScript conditional comments reduces the level of compression!" : ""), true);
- }
- break;
- */
+
+
case 'NAME':
symbol = token.data;
- if (this.ts.lookTok(-1).data == "{" && this.ts.lookTok(1).data == ":") {
+
+ if (this.ts.look(0).data == "{" && this.ts.lookTok(2).data == ":") {
// then we are in an object lit.. -> we need to flag the brace as such...
isObjectLitAr.pop();
isObjectLitAr.push(true);
+ //print(">>>>> EXP PUSH(true)");
break;
}
- var isInObjectLitAr = isObjectLitAr[isObjectLitAr.length-1];
- if (isInObjectLitAr && this.ts.lookTok(-1).data == "," && this.ts.lookTok(1).data == ":") {
+ isInObjectLitAr = isObjectLitAr[isObjectLitAr.length-1];
+ if (isInObjectLitAr && this.ts.lookTok(0).data == "," && this.ts.lookTok(2).data == ":") {
break;
}
-
- if (this.ts.lookTok(-1).data == ".") {
+ //print(this.ts.lookTok(0).data);
+ if (this.ts.lookTok(0).data == ".") {
//skip '.'
break;
}
- if (this.mode == 'CHECKING_SYMBOL_TREE') {
+ if (this.mode == 'PASS2_SYMBOL_TREE') {
identifier = this.getIdentifier(symbol, currentScope);
//println("<B>??</B>");
//println("<B>EID</B>");
- case 'KEYW':
+ case 'KEYW':
+
+ if (token.name == "FUNCTION") {
+
+ this.parseFunctionDeclaration();
+ break;
+ }
+
+
+
symbol = token.data;
if (this.mode == 'BUILDING_SYMBOL_TREE') {
parseFunctionDeclaration : function()
{
-
+ // print("PARSE FUNCTION");
var symbol;
var token;
var currentScope = false;
this.indexedScopes[this.ts.cursor] = fnScope;
} else {
- //println("FETCHING SCOPE" + this.ts.cursor);
+ //qln("FETCHING SCOPE" + this.ts.cursor);
fnScope = this.indexedScopes[this.ts.cursor];
+
}
// Parse function arguments.
var argpos = 0;
- while (!this.ts.lookTok().data == ')') { //(token = consumeToken()).getType() != Token.RP) {
+ while (this.ts.lookTok().data != ')') { //(token = consumeToken()).getType() != Token.RP) {
token = this.ts.nextTok();
-
+ // print ("FUNC ARGS: " + token.toString())
//assert token.getType() == Token.NAME ||
// token.getType() == Token.COMMA;
if (token.type == 'NAME' && this.mode == 'BUILDING_SYMBOL_TREE') {