PageRenderTime 47ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/data/addon/scripts/jsdecoder.js

https://github.com/jinbo51/DiscuzX
JavaScript | 1149 lines | 1131 code | 9 blank | 9 comment | 2 complexity | 47379b5dd85ef8e50a88b4c27f253ff3 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /*
  2. * DO NOT REMOVE THIS NOTICE
  3. *
  4. * PROJECT: JsDecoder
  5. * VERSION: 1.1.0
  6. * COPYRIGHT: (c) 2004-2008 Cezary Tomczak
  7. * LINK: http://code.gosu.pl
  8. * LICENSE: GPL
  9. */
  10. function JsDecoder()
  11. {
  12. this.s = '';
  13. this.len = 0;
  14. this.i = 0;
  15. this.lvl = 0; /* indent level */
  16. this.code = [''];
  17. this.row = 0;
  18. this.switches = [];
  19. this.lastWord = '';
  20. this.nextChar = '';
  21. this.prevChar = '';
  22. this.isAssign = false;
  23. this.decode = function ()
  24. {
  25. this.s = this.s.replace(/[\r\n\f]+/g, "\n");
  26. this.len = this.s.length;
  27. while (this.i < this.len)
  28. {
  29. var c = this.s.charAt(this.i);
  30. this.charInit();
  31. this.switch_c(c);
  32. this.i++;
  33. }
  34. return this.code.join("\n");
  35. };
  36. this.switch_c = function(c)
  37. {
  38. switch (c)
  39. {
  40. case "\n":
  41. this.linefeed();
  42. break;
  43. case ' ':
  44. case "\t":
  45. this.space();
  46. break;
  47. case '{': this.blockBracketOn(); break;
  48. case '}': this.blockBracketOff(); break;
  49. case ':': this.colon(); break;
  50. case ';': this.semicolon(); break;
  51. case '(': this.bracketOn(); break;
  52. case ')': this.bracketOff(); break;
  53. case '[': this.squareBracketOn(); break;
  54. case ']': this.squareBracketOff(); break;
  55. case '"':
  56. case "'":
  57. this.quotation(c);
  58. break;
  59. case '/':
  60. if ('/' == this.nextChar) {
  61. this.lineComment();
  62. } else if ('*' == this.nextChar) {
  63. this.comment();
  64. } else {
  65. this.slash();
  66. }
  67. break;
  68. case ',': this.comma(); break;
  69. case '.': this.dot(); break;
  70. case '~':
  71. case '^':
  72. this.symbol1(c);
  73. break;
  74. case '-': case '+': case '*': case '%':
  75. case '<': case '=': case '>': case '?':
  76. case ':': case '&': case '|': case '/':
  77. this.symbol2(c);
  78. break;
  79. case '!':
  80. if ('=' == this.nextChar) {
  81. this.symbol2(c);
  82. } else {
  83. this.symbol1(c);
  84. }
  85. break;
  86. default:
  87. if (/\w/.test(c)) { this.alphanumeric(c); }
  88. else { this.unknown(c); }
  89. break;
  90. }
  91. c = this.s.charAt(this.i);
  92. if (!/\w/.test(c)) {
  93. this.lastWord = '';
  94. }
  95. };
  96. this.blockBracketOn = function ()
  97. {
  98. this.isAssign = false;
  99. var nextNW = this.nextNonWhite(this.i);
  100. if ('}' == nextNW) {
  101. var ss = (this.prevChar == ')' ? ' ' : '');
  102. this.write(ss+'{');
  103. this.lvl++;
  104. return;
  105. }
  106. if (/^\s*switch\s/.test(this.getCurrentLine())) {
  107. this.switches.push(this.lvl);
  108. }
  109. var line = this.getCurrentLine();
  110. var line_row = this.row;
  111. var re = /(,)\s*(\w+\s*:\s*function\s*\([^\)]*\)\s*)$/;
  112. if (re.test(line)) {
  113. this.replaceLine(this.code[line_row].replace(re, '$1'));
  114. this.writeLine();
  115. var match = re.exec(line);
  116. this.write(match[2]);
  117. }
  118. /* example: return {
  119. title: 'Jack Slocum',
  120. iconCls: 'user'}
  121. After return bracket cannot be on another line
  122. */
  123. if (/^\s*return\s*/.test(this.code[this.row])) {
  124. if (/^\s*return\s+\w+/.test(this.code[this.row])) {
  125. this.writeLine();
  126. } else if (this.prevChar != ' ') {
  127. this.write(' ');
  128. }
  129. this.write('{');
  130. this.writeLine();
  131. this.lvl++;
  132. return;
  133. }
  134. if (/function\s*/.test(this.code[this.row]) || this.isBlockBig()) {
  135. //this.writeLine();
  136. } else {
  137. if (this.prevChar != ' ' && this.prevChar != "\n" && this.prevChar != '(') {
  138. /* && this.prevChar != '(' && this.prevChar != '[' */
  139. this.write(' ');
  140. }
  141. }
  142. this.write('{');
  143. this.lvl++;
  144. if ('{' != nextNW) {
  145. this.writeLine();
  146. }
  147. };
  148. this.isBlockBig = function()
  149. {
  150. var i = this.i + 1;
  151. var count = 0;
  152. var opened = 0;
  153. var closed = 0;
  154. while (i < this.len - 1)
  155. {
  156. i++;
  157. var c = this.s.charAt(i);
  158. if (/\s/.test(c)) {
  159. continue;
  160. }
  161. if ('}' == c && opened == closed) {
  162. break;
  163. }
  164. if ('{' == c) { opened++; }
  165. if ('}' == c) { closed++; }
  166. count++;
  167. if (count > 80) {
  168. return true;
  169. }
  170. }
  171. return (count > 80);
  172. };
  173. this.blockBracketOff = function ()
  174. {
  175. var nextNW = this.nextNonWhite(this.i);
  176. var prevNW = this.prevNonWhite(this.i);
  177. var line = this.getCurrentLine();
  178. if (prevNW != '{')
  179. {
  180. if (line.length && nextNW != ';' && nextNW != '}' && nextNW != ')' && nextNW != ',') {
  181. //this.semicolon();
  182. this.writeLine();
  183. } else if (line.length && prevNW != ';' && nextNW == '}' && this.isAssign) {
  184. this.semicolon();
  185. } else if (line.length && this.isAssign && prevNW != ';') {
  186. this.semicolon();
  187. } else if (line.length && prevNW != ';') {
  188. if (/^\s*(else)?\s*return[\s(]+/i.test(line)) {
  189. this.semicolon();
  190. } else {
  191. this.writeLine();
  192. }
  193. }
  194. }
  195. this.write('}');
  196. if (',' == nextNW) {
  197. this.write(',');
  198. this.goNextNonWhite();
  199. }
  200. var next3 = this.nextManyNW(3);
  201. if (next3 == '(),') {
  202. this.write('(),');
  203. this.goNextManyNW('(),');
  204. this.writeLine();
  205. }
  206. else if (next3 == '();') {
  207. this.write('();');
  208. this.goNextManyNW('();');
  209. this.writeLine();
  210. }
  211. else if (next3 == '():') {
  212. this.write('()');
  213. this.goNextManyNW('()');
  214. this.write(' : ');
  215. this.goNextNonWhite();
  216. }
  217. else
  218. {
  219. if ('{' == prevNW) {
  220. if (',' == nextNW && this.getCurrentLine().length < 80) {
  221. this.write(' ');
  222. } else {
  223. if (this.nextWord() || '}' == nextNW) {
  224. this.writeLine();
  225. }
  226. }
  227. } else {
  228. if (')' != nextNW && ']' != nextNW) {
  229. if (',' == nextNW && /^[\s\w,]+\)/.test(this.s.substr(this.i, 20))) {
  230. this.write(' ');
  231. } else {
  232. this.writeLine();
  233. }
  234. }
  235. }
  236. }
  237. this.lvl--;
  238. if (this.switches.length && this.switches[this.switches.length - 1] == this.lvl)
  239. {
  240. var row = this.row - 1;
  241. var spaces1 = str_repeat(' ', this.lvl * 4);
  242. var spaces2 = str_repeat(' ', (this.lvl + 1) * 4);
  243. var sw1 = new RegExp('^'+spaces1+'(switch\\s|{)');
  244. var sw2 = new RegExp('^'+spaces2+'(case|default)[\\s:]');
  245. var sw3 = new RegExp('^'+spaces2+'[^\\s]');
  246. while (row > 0) {
  247. row--;
  248. if (sw1.test(this.code[row])) {
  249. break;
  250. }
  251. if (sw2.test(this.code[row])) {
  252. continue;
  253. }
  254. this.replaceLine(' ' + this.code[row], row);
  255. /*
  256. if (sw3.test(this.code[row])) {
  257. this.replaceLine(' ' + this.code[row], row);
  258. }
  259. */
  260. }
  261. this.switches.pop();
  262. }
  263. // fix missing brackets for sub blocks
  264. if (this.sub) {
  265. return;
  266. }
  267. var re1 = /^(\s*else\s*if)\s*\(/;
  268. var re2 = /^(\s*else)\s+[^{]+/;
  269. var part = this.s.substr(this.i+1, 100);
  270. if (re1.test(part)) {
  271. this.i += re1.exec(part)[1].length;
  272. this.write('else if');
  273. this.lastWord = 'if';
  274. //debug(this.getCurrentLine(), 're1');
  275. this.fixSub('else if');
  276. //debug(this.getCurrentLine(), 're1 after');
  277. } else if (re2.test(part)) {
  278. this.i += re2.exec(part)[1].length;
  279. this.write('else');
  280. this.lastWord = 'else';
  281. //debug(this.getCurrentLine(), 're2');
  282. this.fixSub('else');
  283. //debug(this.getCurrentLine(), 're2 after');
  284. }
  285. };
  286. this.bracketOn = function ()
  287. {
  288. if (this.isKeyword() && this.prevChar != ' ' && this.prevChar != "\n") {
  289. this.write(' (');
  290. } else {
  291. this.write('(');
  292. }
  293. };
  294. this.bracketOff = function ()
  295. {
  296. this.write(')');
  297. /*
  298. if (/\w/.test(this.nextNonWhite(this.i))) {
  299. this.semicolon();
  300. }
  301. */
  302. if (this.sub) {
  303. return;
  304. }
  305. var re = new RegExp('^\\s*(if|for|while|do)\\s*\\([^{}]+\\)$', 'i');
  306. var line = this.getCurrentLine();
  307. if (re.test(line)) {
  308. var c = this.nextNonWhite(this.i);
  309. if ('{' != c && ';' != c && ')' != c) {
  310. var opened = 0;
  311. var closed = 0;
  312. var foundFirst = false;
  313. var semicolon = false;
  314. var fix = false;
  315. for (var k = 0; k < line.length; k++) {
  316. if (line.charAt(k) == '(') {
  317. foundFirst = true;
  318. opened++;
  319. }
  320. if (line.charAt(k) == ')') {
  321. closed++;
  322. if (foundFirst && opened == closed) {
  323. if (k == line.length - 1) {
  324. fix = true;
  325. } else {
  326. break;
  327. }
  328. }
  329. }
  330. }
  331. if (fix) {
  332. //alert(this.s.substr(this.i));
  333. //throw 'asdas';
  334. //alert(line);
  335. this.fixSub(re.exec(line)[1]);
  336. /*
  337. this.writeLine();
  338. this.lvl2++;
  339. var indent = '';
  340. for (var j = 0; j < this.lvl2; j++) {
  341. indent += ' ';
  342. }
  343. this.write(indent);
  344. */
  345. }
  346. }
  347. }
  348. };
  349. this.sub = false;
  350. this.orig_i = null;
  351. this.orig_lvl = null;
  352. this.orig_code = null;
  353. this.orig_row = null;
  354. this.orig_switches = null;
  355. this.restoreOrig = function (omit_i)
  356. {
  357. this.sub = false;
  358. if (!omit_i) { this.i = this.orig_i; }
  359. this.lvl = this.orig_lvl;
  360. this.code = this.orig_code;
  361. this.row = this.orig_row;
  362. this.switches = this.orig_switches;
  363. this.prevCharInit();
  364. this.lastWord = '';
  365. this.charInit();
  366. this.isAssign = false;
  367. };
  368. this.combineSub = function ()
  369. {
  370. //debug(this.orig_code, 'orig_code');
  371. for (i = 0; i < this.code.length; i++) {
  372. var line = this.orig_code[this.orig_row];
  373. if (0 == i && line.length) {
  374. if (line.substr(line.length-1, 1) != ' ') {
  375. this.orig_code[this.orig_row] += ' ';
  376. }
  377. this.orig_code[this.orig_row] += this.code[i].trim();
  378. } else {
  379. this.orig_code[this.orig_row+i] = this.code[i];
  380. }
  381. }
  382. //debug(this.code, 'sub_code');
  383. //debug(this.orig_code, 'code');
  384. };
  385. this.fixSub = function (keyword)
  386. {
  387. // repair missing {}: for, if, while, do, else, else if
  388. if (this.sub) {
  389. return;
  390. }
  391. if ('{' == this.nextNonWhite(this.i)) {
  392. return;
  393. }
  394. var firstWord = this.nextWord();
  395. //debug(this.code, 'fixSub('+keyword+') start');
  396. this.orig_i = this.i;
  397. this.orig_lvl = this.lvl;
  398. this.orig_code = this.code;
  399. this.orig_row = this.row;
  400. this.orig_switches = this.switches;
  401. this.sub = true;
  402. this.code = [''];
  403. this.prevChar = '';
  404. this.row = 0;
  405. this.switches = [];
  406. this.isAssign = false;
  407. this.i++;
  408. var b1 = 0;
  409. var b2 = 0;
  410. var b3 = 0;
  411. if ('else if' == keyword) {
  412. var first_b2_closed = false;
  413. }
  414. var found = false;
  415. /*
  416. try catch
  417. switch
  418. while do
  419. if else else else...
  420. todo: nestings
  421. if ()
  422. if ()
  423. if ()
  424. for ()
  425. if () asd();
  426. else
  427. asd();
  428. else
  429. if ()
  430. try {
  431. } catch {}
  432. else
  433. if ()
  434. */
  435. var b1_lastWord = false;
  436. var b2_lastWord = false;
  437. while (!found && this.i < this.len)
  438. {
  439. var c = this.s.charAt(this.i);
  440. this.charInit();
  441. switch (c)
  442. {
  443. case '{': b1++; break;
  444. case '}':
  445. b1--;
  446. // case: for(){if (!c.m(g))c.g(f, n[t] + g + ';')}
  447. if (0 == b1 && 0 == b2 && 0 == b3 && this.lvl-1 == this.orig_lvl)
  448. {
  449. var nextWord = this.nextWord();
  450. if ('switch' == firstWord) {
  451. found = true;
  452. break;
  453. }
  454. if ('try' == firstWord && 'catch' == b1_lastWord) {
  455. found = true;
  456. break;
  457. }
  458. if ('while' == firstWord && 'do' == b1_lastWord) {
  459. found = true;
  460. break;
  461. }
  462. if ('if' == firstWord) {
  463. // todo
  464. }
  465. if ('if' == keyword && 'else' == nextWord && 'if' != firstWord) {
  466. found = true;
  467. break;
  468. }
  469. b1_lastWord = nextWord;
  470. }
  471. break;
  472. case '(': b2++; break;
  473. case ')':
  474. b2--;
  475. if ('else if' == keyword && 0 == b2 && !first_b2_closed) {
  476. if (this.nextNonWhite(this.i) == '{') {
  477. this.write(c);
  478. this.combineSub();
  479. this.restoreOrig(true);
  480. //debug(this.code, 'fixSub('+keyword+') b2 return');
  481. //debug(this.s.charAt(this.i), ' b2 current char');
  482. return;
  483. }
  484. // do not restore orig i
  485. this.write(c);
  486. this.combineSub();
  487. this.restoreOrig(true);
  488. this.fixSub('if');
  489. //debug(this.code, 'fixSub('+keyword+') b2 return');
  490. return;
  491. }
  492. break;
  493. case '[': b3++; break;
  494. case ']': b3--; break;
  495. case ';':
  496. //debug(this.getCurrentLine(), 'semicolon');
  497. //debug([b1, b2, b3]);
  498. if (0 == b1 && 0 == b2 && 0 == b3 && this.lvl == this.orig_lvl && 'if' != firstWord) {
  499. found = true;
  500. }
  501. break;
  502. }
  503. if (-1 == b1 && b2 == 0 && b3 == 0 && this.prevNonWhite(this.i) != '}') {
  504. this.write(';');
  505. this.i--;
  506. found = true;
  507. } else if (b1 < 0 || b2 < 0 || b3 < 0) {
  508. found = false;
  509. break;
  510. } else {
  511. this.switch_c(c);
  512. }
  513. this.i++;
  514. }
  515. this.i--;
  516. if (found)
  517. {
  518. /*
  519. var re = /^\s*(else\s+[\s\S]*)$/;
  520. if ('if' == keyword && re.test(this.getCurrentLine())) {
  521. this.i = this.i - re.exec(this.getCurrentLine())[1].length;
  522. this.code[this.row] = '';
  523. }
  524. */
  525. this.s = this.s.substr(0, this.orig_i+1) + '{' + this.code.join("\n") + '}' + this.s.substr(this.i+1);
  526. this.len = this.s.length;
  527. }
  528. //debug("{\n" + this.code.join("\n") + '}', 'fixSub('+keyword+') result');
  529. //debug(found, 'found');
  530. this.restoreOrig(false);
  531. };
  532. this.squareBracketOn = function ()
  533. {
  534. this.checkKeyword();
  535. this.write('[');
  536. };
  537. this.squareBracketOff = function ()
  538. {
  539. this.write(']');
  540. };
  541. this.isKeyword = function ()
  542. {
  543. // Check if this.lastWord is a keyword
  544. return this.lastWord.length && this.keywords.indexOf(this.lastWord) != -1;
  545. };
  546. this.linefeed = function () {};
  547. this.space = function ()
  548. {
  549. if (!this.prevChar.length) {
  550. return;
  551. }
  552. if (' ' == this.prevChar || "\n" == this.prevChar) {
  553. return;
  554. }
  555. if ('}' == this.prevChar && ']' == this.nextChar) {
  556. //return;
  557. }
  558. this.write(' ');
  559. return;
  560. /*
  561. if (this.isKeyword()) {
  562. this.write(' ');
  563. this.lastWord = '';
  564. } else {
  565. var multi = ['in', 'new'];
  566. for (var i = 0; i < multi.length; i++) {
  567. var isKeywordNext = true;
  568. for (var j = 0; j < multi[i].length; j++) {
  569. if (multi[i][j] != this.s.charAt(this.i + 1 + j)) {
  570. isKeywordNext = false;
  571. break;
  572. }
  573. }
  574. if (isKeywordNext) {
  575. this.write(' ');
  576. this.lastWord = '';
  577. break;
  578. }
  579. }
  580. }
  581. */
  582. };
  583. this.checkKeyword = function ()
  584. {
  585. if (this.isKeyword() && this.prevChar != ' ' && this.prevChar != "\n") {
  586. this.write(' ');
  587. }
  588. };
  589. this.nextWord = function ()
  590. {
  591. var i = this.i;
  592. var word = '';
  593. while (i < this.len - 1)
  594. {
  595. i++;
  596. var c = this.s.charAt(i);
  597. if (word.length) {
  598. if (/\s/.test(c)) {
  599. break;
  600. } else if (/\w/.test(c)) {
  601. word += c;
  602. } else {
  603. break;
  604. }
  605. } else {
  606. if (/\s/.test(c)) {
  607. continue;
  608. } else if (/\w/.test(c)) {
  609. word += c;
  610. } else {
  611. break;
  612. }
  613. }
  614. }
  615. if (word.length) {
  616. return word;
  617. }
  618. return false;
  619. };
  620. this.nextManyNW = function(many)
  621. {
  622. var ret = '';
  623. var i = this.i;
  624. while (i < this.len - 1)
  625. {
  626. i++;
  627. var c = this.s.charAt(i);
  628. if (!/^\s+$/.test(c)) {
  629. ret += c;
  630. if (ret.length == many) {
  631. return ret;
  632. }
  633. }
  634. }
  635. return false;
  636. }
  637. this.goNextManyNW = function (cc)
  638. {
  639. var ret = '';
  640. var i = this.i;
  641. while (i < this.len - 1)
  642. {
  643. i++;
  644. var c = this.s.charAt(i);
  645. if (!/^\s+$/.test(c)) {
  646. ret += c;
  647. if (ret == cc) {
  648. this.i = i;
  649. this.charInit();
  650. return true;
  651. }
  652. if (ret.length >= cc.length) {
  653. return false;
  654. }
  655. }
  656. }
  657. return false;
  658. };
  659. this.nextNonWhite = function (i)
  660. {
  661. while (i < this.len - 1)
  662. {
  663. i++;
  664. var c = this.s.charAt(i);
  665. if (!/^\s+$/.test(c)) {
  666. return c;
  667. }
  668. }
  669. return false;
  670. };
  671. this.prevNonWhite = function (i)
  672. {
  673. while (i > 0)
  674. {
  675. i--;
  676. var c = this.s.charAt(i);
  677. if (!/^\s+$/.test(c)) {
  678. return c;
  679. }
  680. }
  681. return false;
  682. };
  683. this.goNextNonWhite = function ()
  684. {
  685. // you need to write() this nonWhite char when calling this func
  686. var i = this.i;
  687. while (i < this.len - 1)
  688. {
  689. i++;
  690. var c = this.s.charAt(i);
  691. if (!/^\s+$/.test(c)) {
  692. this.i = i;
  693. this.charInit();
  694. return true;
  695. }
  696. }
  697. return false;
  698. };
  699. this.colon = function ()
  700. {
  701. //alert(this.getCurrentLine());
  702. /* case 6: expr ? stat : stat */
  703. var line = this.getCurrentLine();
  704. if (/^\s*case\s/.test(line) || /^\s*default$/.test(line)) {
  705. this.write(':');
  706. this.writeLine();
  707. } else {
  708. this.symbol2(':');
  709. }
  710. };
  711. this.isStart = function ()
  712. {
  713. return this.getCurrentLine().length === 0;
  714. };
  715. this.backLine = function ()
  716. {
  717. if (!this.isStart) {
  718. throw 'backLine() may be called only at the start of the line';
  719. }
  720. this.code.length = this.code.length-1;
  721. this.row--;
  722. };
  723. this.semicolon = function ()
  724. {
  725. /* for statement: for (i = 1; i < len; i++) */
  726. this.isAssign = false;
  727. if (this.isStart()) {
  728. this.backLine();
  729. }
  730. this.write(';');
  731. if (/^\s*for\s/.test(this.getCurrentLine())) {
  732. this.write(' ');
  733. } else {
  734. this.writeLine();
  735. }
  736. };
  737. this.quotation = function (quotation)
  738. {
  739. this.checkKeyword();
  740. var escaped = false;
  741. this.write(quotation);
  742. while (this.i < this.len - 1) {
  743. this.i++;
  744. var c = this.s.charAt(this.i);
  745. if ('\\' == c) {
  746. escaped = (escaped ? false : true);
  747. }
  748. this.write(c);
  749. if (c == quotation) {
  750. if (!escaped) {
  751. break;
  752. }
  753. }
  754. if ('\\' != c) {
  755. escaped = false;
  756. }
  757. }
  758. //debug(this.getCurrentLine(), 'quotation');
  759. //debug(this.s.charAt(this.i), 'char');
  760. };
  761. this.lineComment = function ()
  762. {
  763. this.write('//');
  764. this.i++;
  765. while (this.i < this.len - 1) {
  766. this.i++;
  767. var c = this.s.charAt(this.i);
  768. if ("\n" == c) {
  769. this.writeLine();
  770. break;
  771. }
  772. this.write(c);
  773. }
  774. };
  775. this.comment = function ()
  776. {
  777. this.write('/*');
  778. this.i++;
  779. var c = '';
  780. var prevC = '';
  781. while (this.i < this.len - 1)
  782. {
  783. this.i++;
  784. prevC = c;
  785. c = this.s.charAt(this.i);
  786. if (' ' == c || "\t" == c || "\n" == c) {
  787. if (' ' == c) {
  788. if (this.getCurrentLine().length > 100) {
  789. this.writeLine();
  790. } else {
  791. this.write(' ', true);
  792. }
  793. } else if ("\t" == c) {
  794. this.write(' ', true);
  795. } else if ("\n" == c) {
  796. this.writeLine();
  797. }
  798. } else {
  799. this.write(c, true);
  800. }
  801. if ('/' == c && '*' == prevC) {
  802. break;
  803. }
  804. }
  805. this.writeLine();
  806. };
  807. this.slash = function ()
  808. {
  809. /*
  810. divisor /= or *\/ (4/5 , a/5)
  811. regexp /\w/ (//.test() , var asd = /some/;)
  812. asd /= 5;
  813. bbb = * / (4/5)
  814. asd =( a/5);
  815. regexp = /\w/;
  816. /a/.test();
  817. var asd = /some/;
  818. obj = { sasd : /pattern/ig }
  819. */
  820. var a_i = this.i - 1;
  821. var a_c = this.s.charAt(a_i);
  822. for (a_i = this.i - 1; a_i >= 0; a_i--) {
  823. var c2 = this.s.charAt(a_i);
  824. if (' ' == c2 || '\t' == c2) {
  825. continue;
  826. }
  827. a_c = this.s.charAt(a_i);
  828. break;
  829. }
  830. var a = /^\w+$/.test(a_c) || ']' == a_c || ')' == a_c;
  831. var b = ('*' == this.prevChar);
  832. if (a || b) {
  833. if (a) {
  834. if ('=' == this.nextChar) {
  835. var ss = this.prevChar == ' ' ? '' : ' ';
  836. this.write(ss+'/');
  837. } else {
  838. this.write(' / ');
  839. }
  840. } else if (b) {
  841. this.write('/ ');
  842. }
  843. } else if (')' == this.prevChar) {
  844. this.write(' / ');
  845. } else {
  846. var ret = '';
  847. if ('=' == this.prevChar || ':' == this.prevChar) {
  848. ret += ' /';
  849. } else {
  850. ret += '/';
  851. }
  852. var escaped = false;
  853. while (this.i < this.len - 1) {
  854. this.i++;
  855. var c = this.s.charAt(this.i);
  856. if ('\\' == c) {
  857. escaped = (escaped ? false : true);
  858. }
  859. ret += c;
  860. if ('/' == c) {
  861. if (!escaped) {
  862. break;
  863. }
  864. }
  865. if ('\\' != c) {
  866. escaped = false;
  867. }
  868. }
  869. this.write(ret);
  870. }
  871. };
  872. this.comma = function ()
  873. {
  874. /*
  875. * function arguments seperator
  876. * array values seperator
  877. * object values seperator
  878. */
  879. this.write(', ');
  880. var line = this.getCurrentLine();
  881. if (line.replace(' ', '').length > 100) {
  882. this.writeLine();
  883. }
  884. };
  885. this.dot = function ()
  886. {
  887. this.write('.');
  888. };
  889. this.symbol1 = function (c)
  890. {
  891. if ('=' == this.prevChar && '!' == c) {
  892. this.write(' '+c);
  893. } else {
  894. this.write(c);
  895. }
  896. };
  897. this.symbol2 = function (c)
  898. {
  899. // && !p
  900. // ===
  901. if ('+' == c || '-' == c) {
  902. if (c == this.nextChar || c == this.prevChar) {
  903. this.write(c);
  904. return;
  905. }
  906. }
  907. var ss = (this.prevChar == ' ' ? '' : ' ');
  908. var ss2 = ' ';
  909. if ('(' == this.prevChar) {
  910. ss = '';
  911. ss2 = '';
  912. }
  913. if ('-' == c && ('>' == this.prevChar || '>' == this.prevChar)) {
  914. this.write(' '+c);
  915. return;
  916. }
  917. if (this.symbols2.indexOf(this.prevChar) != -1) {
  918. if (this.symbols2.indexOf(this.nextChar) != -1) {
  919. this.write(c + (this.nextChar == '!' ? ' ' : ''));
  920. } else {
  921. this.write(c + ss2);
  922. }
  923. } else {
  924. if (this.symbols2.indexOf(this.nextChar) != -1) {
  925. this.write(ss + c);
  926. } else {
  927. this.write(ss + c + ss2);
  928. }
  929. }
  930. if ('=' == c && /^[\w\]]$/.test(this.prevNonWhite(this.i)) && /^[\w\'\"\[]$/.test(this.nextNonWhite(this.i))) {
  931. this.isAssign = true;
  932. }
  933. };
  934. this.alphanumeric = function (c)
  935. {
  936. /* /[a-zA-Z0-9_]/ == /\w/ */
  937. if (this.lastWord) {
  938. this.lastWord += c;
  939. } else {
  940. this.lastWord = c;
  941. }
  942. if (')' == this.prevChar) {
  943. c = ' '+c;
  944. }
  945. this.write(c);
  946. };
  947. this.unknown = function (c)
  948. {
  949. //throw 'Unknown char: "'+c+'" , this.i = ' + this.i;
  950. this.write(c);
  951. };
  952. this.charInit = function ()
  953. {
  954. /*
  955. if (this.i > 0) {
  956. //this.prevChar = this.s.charAt(this.i - 1);
  957. var line = this.code[this.row];
  958. if (line.length) {
  959. this.prevChar = line.substr(line.length-1, 1);
  960. } else {
  961. this.prevChar = '';
  962. }
  963. } else {
  964. this.prevChar = '';
  965. }
  966. */
  967. if (this.len - 1 === this.i) {
  968. this.nextChar = '';
  969. } else {
  970. this.nextChar = this.s.charAt(this.i + 1);
  971. }
  972. };
  973. this.write = function (s, isComment)
  974. {
  975. if (isComment) {
  976. if (!/\s/.test(s)) {
  977. if (this.code[this.row].length < this.lvl * 4) {
  978. this.code[this.row] += str_repeat(' ', this.lvl * 4 - this.code[this.row].length);
  979. }
  980. }
  981. this.code[this.row] += s;
  982. } else {
  983. if (0 === this.code[this.row].length) {
  984. var lvl = ('}' == s ? this.lvl - 1 : this.lvl);
  985. for (var i = 0; i < lvl; i++) {
  986. this.code[this.row] += ' ';
  987. }
  988. this.code[this.row] += s;
  989. } else {
  990. this.code[this.row] += s;
  991. }
  992. }
  993. this.prevCharInit();
  994. };
  995. this.writeLine = function ()
  996. {
  997. this.code.push('');
  998. this.row++;
  999. this.prevChar = "\n";
  1000. };
  1001. this.replaceLine = function (line, row)
  1002. {
  1003. if ('undefined' == typeof row) {
  1004. row = false;
  1005. }
  1006. if (row !== false) {
  1007. if (!/^\d+$/.test(row) || row < 0 || row > this.row) {
  1008. throw 'replaceLine() failed: invalid row='+row;
  1009. }
  1010. }
  1011. if (row !== false) {
  1012. this.code[row] = line;
  1013. } else {
  1014. this.code[this.row] = line;
  1015. }
  1016. if (row === false || row == this.row) {
  1017. this.prevCharInit();
  1018. }
  1019. };
  1020. this.prevCharInit = function ()
  1021. {
  1022. this.prevChar = this.code[this.row].charAt(this.code[this.row].length - 1);
  1023. };
  1024. this.writeTab = function ()
  1025. {
  1026. this.write(' ');
  1027. this.prevChar = ' ';
  1028. };
  1029. this.getCurrentLine = function ()
  1030. {
  1031. return this.code[this.row];
  1032. };
  1033. this.symbols1 = '~!^';
  1034. this.symbols2 = '-+*%<=>?:&|/!';
  1035. this.keywords = ['abstract', 'boolean', 'break', 'byte', 'case', 'catch', 'char', 'class',
  1036. 'const', 'continue', 'default', 'delete', 'do', 'double', 'else', 'extends', 'false',
  1037. 'final', 'finally', 'float', 'for', 'function', 'goto', 'if', 'implements', 'import',
  1038. 'in', 'instanceof', 'int', 'interface', 'long', 'native', 'new', 'null', 'package',
  1039. 'private', 'protected', 'public', 'return', 'short', 'static', 'super', 'switch',
  1040. 'synchronized', 'this', 'throw', 'throws', 'transient', 'true', 'try', 'typeof', 'var',
  1041. 'void', 'while', 'with'];
  1042. }
  1043. if (typeof Array.prototype.indexOf == 'undefined') {
  1044. /* Finds the index of the first occurence of item in the array, or -1 if not found */
  1045. Array.prototype.indexOf = function(item) {
  1046. for (var i = 0; i < this.length; i++) {
  1047. if ((typeof this[i] == typeof item) && (this[i] == item)) {
  1048. return i;
  1049. }
  1050. }
  1051. return -1;
  1052. };
  1053. }
  1054. if (!String.prototype.trim) {
  1055. String.prototype.trim = function() {
  1056. return this.replace(/^\s*|\s*$/g, '');
  1057. };
  1058. }
  1059. function str_repeat(str, repeat)
  1060. {
  1061. ret = '';
  1062. for (var i = 0; i < repeat; i++) {
  1063. ret += str;
  1064. }
  1065. return ret;
  1066. }
  1067. var debug_w;
  1068. function debug (arr, name)
  1069. {
  1070. if (!debug_w)
  1071. {
  1072. var width = 600;
  1073. var height = 600;
  1074. var x = (screen.width-width)/2;
  1075. var y = (screen.height-height)/2;
  1076. debug_w = window.open('', '', 'scrollbars=yes,resizable=yes,width='+width+',height='+height+',screenX='+(x)+',screenY='+y+',left='+x+',top='+y);
  1077. debug_w.document.open();
  1078. debug_w.document.write('<html><head><style>body{margin: 1em;padding: 0;font-family: courier new; font-size: 12px;}h1,h2{margin: 0.2em 0;}</style></head><body><h1>Debug</h1></body></html>');
  1079. debug_w.document.close();
  1080. }
  1081. var ret = '';
  1082. if ('undefined' !== typeof name && name.length) {
  1083. ret = '<h2>'+name+'</h2>'+"\n";
  1084. }
  1085. if ('object' === typeof arr) {
  1086. for (var i = 0; i < arr.length; i++) {
  1087. ret += '['+i+'] => '+arr[i]+"\n";
  1088. }
  1089. } else if ('string' == typeof arr) {
  1090. ret += arr;
  1091. } else {
  1092. try { ret += arr.toString(); } catch (e) {}
  1093. ret += ' ('+typeof arr+')';
  1094. }
  1095. debug_w.document.body.innerHTML += '<pre>'+ret+'</pre>';
  1096. }