quote-scanner.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. var COMMENT_START_MARK = '/*';
  2. function QuoteScanner(data) {
  3. this.data = data;
  4. }
  5. var findQuoteEnd = function (data, matched, cursor, oldCursor) {
  6. var commentEndMark = '*/';
  7. var escapeMark = '\\';
  8. var blockEndMark = '}';
  9. var dataPrefix = data.substring(oldCursor, cursor);
  10. var commentEndedAt = dataPrefix.lastIndexOf(commentEndMark, cursor);
  11. var commentStartedAt = findLastCommentStartedAt(dataPrefix, cursor);
  12. var commentStarted = false;
  13. if (commentEndedAt >= cursor && commentStartedAt > -1)
  14. commentStarted = true;
  15. if (commentStartedAt < cursor && commentStartedAt > commentEndedAt)
  16. commentStarted = true;
  17. if (commentStarted) {
  18. var commentEndsAt = data.indexOf(commentEndMark, cursor);
  19. if (commentEndsAt > -1)
  20. return commentEndsAt;
  21. commentEndsAt = data.indexOf(blockEndMark, cursor);
  22. return commentEndsAt > -1 ? commentEndsAt - 1 : data.length;
  23. }
  24. while (true) {
  25. if (data[cursor] === undefined)
  26. break;
  27. if (data[cursor] == matched && (data[cursor - 1] != escapeMark || data[cursor - 2] == escapeMark))
  28. break;
  29. cursor++;
  30. }
  31. return cursor;
  32. };
  33. function findLastCommentStartedAt(data, cursor) {
  34. var position = cursor;
  35. while (position > -1) {
  36. position = data.lastIndexOf(COMMENT_START_MARK, position);
  37. if (position > -1 && data[position - 1] != '*') {
  38. break;
  39. } else {
  40. position--;
  41. }
  42. }
  43. return position;
  44. }
  45. function findNext(data, mark, startAt) {
  46. var escapeMark = '\\';
  47. var candidate = startAt;
  48. while (true) {
  49. candidate = data.indexOf(mark, candidate + 1);
  50. if (candidate == -1)
  51. return -1;
  52. if (data[candidate - 1] != escapeMark)
  53. return candidate;
  54. }
  55. }
  56. QuoteScanner.prototype.each = function (callback) {
  57. var data = this.data;
  58. var tempData = [];
  59. var nextStart = 0;
  60. var nextEnd = 0;
  61. var cursor = 0;
  62. var matchedMark = null;
  63. var singleMark = '\'';
  64. var doubleMark = '"';
  65. var dataLength = data.length;
  66. for (; nextEnd < data.length;) {
  67. var nextStartSingle = findNext(data, singleMark, nextEnd);
  68. var nextStartDouble = findNext(data, doubleMark, nextEnd);
  69. if (nextStartSingle == -1)
  70. nextStartSingle = dataLength;
  71. if (nextStartDouble == -1)
  72. nextStartDouble = dataLength;
  73. if (nextStartSingle < nextStartDouble) {
  74. nextStart = nextStartSingle;
  75. matchedMark = singleMark;
  76. } else {
  77. nextStart = nextStartDouble;
  78. matchedMark = doubleMark;
  79. }
  80. if (nextStart == -1)
  81. break;
  82. nextEnd = findQuoteEnd(data, matchedMark, nextStart + 1, cursor);
  83. if (nextEnd == -1)
  84. break;
  85. var text = data.substring(nextStart, nextEnd + 1);
  86. tempData.push(data.substring(cursor, nextStart));
  87. if (text.length > 0)
  88. callback(text, tempData, nextStart);
  89. cursor = nextEnd + 1;
  90. }
  91. return tempData.length > 0 ?
  92. tempData.join('') + data.substring(cursor, data.length) :
  93. data;
  94. };
  95. module.exports = QuoteScanner;