mark.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. var TokenType = require('../token-types');
  2. module.exports = (function() {
  3. /**
  4. * Mark whitespaces and comments
  5. */
  6. function markSC(tokens) {
  7. var tokensLength = tokens.length,
  8. ws = -1, // flag for whitespaces
  9. sc = -1, // flag for whitespaces and comments
  10. t; // current token
  11. // For every token in the token list, mark spaces and line breaks
  12. // as spaces (set both `ws` and `sc` flags). Mark multiline comments
  13. // with `sc` flag.
  14. // If there are several spaces or tabs or line breaks or multiline
  15. // comments in a row, group them: take the last one's index number
  16. // and save it to the first token in the group as a reference
  17. // (e.g., `ws_last = 7` for a group of whitespaces or `sc_last = 9`
  18. // for a group of whitespaces and comments):
  19. for (var i = 0; i < tokensLength; i++) {
  20. t = tokens[i];
  21. switch (t.type) {
  22. case TokenType.Space:
  23. case TokenType.Tab:
  24. case TokenType.Newline:
  25. t.ws = true;
  26. t.sc = true;
  27. if (ws === -1) ws = i;
  28. if (sc === -1) sc = i;
  29. break;
  30. case TokenType.CommentML:
  31. case TokenType.CommentSL:
  32. if (ws !== -1) {
  33. tokens[ws].ws_last = i - 1;
  34. ws = -1;
  35. }
  36. t.sc = true;
  37. break;
  38. default:
  39. if (ws !== -1) {
  40. tokens[ws].ws_last = i - 1;
  41. ws = -1;
  42. }
  43. if (sc !== -1) {
  44. tokens[sc].sc_last = i - 1;
  45. sc = -1;
  46. }
  47. }
  48. }
  49. if (ws !== -1) tokens[ws].ws_last = i - 1;
  50. if (sc !== -1) tokens[sc].sc_last = i - 1;
  51. }
  52. /**
  53. * Pair brackets
  54. */
  55. function markBrackets(tokens) {
  56. var tokensLength = tokens.length;
  57. var ps = [], // parenthesis
  58. sbs = [], // square brackets
  59. cbs = [], // curly brackets
  60. t; // current token
  61. // For every token in the token list, if we meet an opening (left)
  62. // bracket, push its index number to a corresponding array.
  63. // If we then meet a closing (right) bracket, look at the corresponding
  64. // array. If there are any elements (records about previously met
  65. // left brackets), take a token of the last left bracket (take
  66. // the last index number from the array and find a token with
  67. // this index number) and save right bracket's index as a reference:
  68. for (var i = 0; i < tokens.length; i++) {
  69. t = tokens[i];
  70. switch(t.type) {
  71. case TokenType.LeftParenthesis:
  72. ps.push(i);
  73. break;
  74. case TokenType.RightParenthesis:
  75. if (ps.length) {
  76. t.left = ps.pop();
  77. tokens[t.left].right = i;
  78. }
  79. break;
  80. case TokenType.LeftSquareBracket:
  81. sbs.push(i);
  82. break;
  83. case TokenType.RightSquareBracket:
  84. if (sbs.length) {
  85. t.left = sbs.pop();
  86. tokens[t.left].right = i;
  87. }
  88. break;
  89. case TokenType.LeftCurlyBracket:
  90. cbs.push(i);
  91. break;
  92. case TokenType.RightCurlyBracket:
  93. if (cbs.length) {
  94. t.left = cbs.pop();
  95. tokens[t.left].right = i;
  96. }
  97. break;
  98. }
  99. }
  100. }
  101. return function(tokens) {
  102. markBrackets(tokens);
  103. markSC(tokens);
  104. }
  105. })();