parser.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. export default parseString;
  2. var NEUTRAL = 1;
  3. var KEYWORD = 2;
  4. var NUMBER = 3;
  5. var QUOTED = 4;
  6. var AFTERQUOTE = 5;
  7. var ENDED = -1;
  8. var whitespace = /\s/;
  9. var latin = /[A-Za-z]/;
  10. var keyword = /[A-Za-z84_]/;
  11. var endThings = /[,\]]/;
  12. var digets = /[\d\.E\-\+]/;
  13. // const ignoredChar = /[\s_\-\/\(\)]/g;
  14. function Parser(text) {
  15. if (typeof text !== 'string') {
  16. throw new Error('not a string');
  17. }
  18. this.text = text.trim();
  19. this.level = 0;
  20. this.place = 0;
  21. this.root = null;
  22. this.stack = [];
  23. this.currentObject = null;
  24. this.state = NEUTRAL;
  25. }
  26. Parser.prototype.readCharicter = function() {
  27. var char = this.text[this.place++];
  28. if (this.state !== QUOTED) {
  29. while (whitespace.test(char)) {
  30. if (this.place >= this.text.length) {
  31. return;
  32. }
  33. char = this.text[this.place++];
  34. }
  35. }
  36. switch (this.state) {
  37. case NEUTRAL:
  38. return this.neutral(char);
  39. case KEYWORD:
  40. return this.keyword(char)
  41. case QUOTED:
  42. return this.quoted(char);
  43. case AFTERQUOTE:
  44. return this.afterquote(char);
  45. case NUMBER:
  46. return this.number(char);
  47. case ENDED:
  48. return;
  49. }
  50. };
  51. Parser.prototype.afterquote = function(char) {
  52. if (char === '"') {
  53. this.word += '"';
  54. this.state = QUOTED;
  55. return;
  56. }
  57. if (endThings.test(char)) {
  58. this.word = this.word.trim();
  59. this.afterItem(char);
  60. return;
  61. }
  62. throw new Error('havn\'t handled "' +char + '" in afterquote yet, index ' + this.place);
  63. };
  64. Parser.prototype.afterItem = function(char) {
  65. if (char === ',') {
  66. if (this.word !== null) {
  67. this.currentObject.push(this.word);
  68. }
  69. this.word = null;
  70. this.state = NEUTRAL;
  71. return;
  72. }
  73. if (char === ']') {
  74. this.level--;
  75. if (this.word !== null) {
  76. this.currentObject.push(this.word);
  77. this.word = null;
  78. }
  79. this.state = NEUTRAL;
  80. this.currentObject = this.stack.pop();
  81. if (!this.currentObject) {
  82. this.state = ENDED;
  83. }
  84. return;
  85. }
  86. };
  87. Parser.prototype.number = function(char) {
  88. if (digets.test(char)) {
  89. this.word += char;
  90. return;
  91. }
  92. if (endThings.test(char)) {
  93. this.word = parseFloat(this.word);
  94. this.afterItem(char);
  95. return;
  96. }
  97. throw new Error('havn\'t handled "' +char + '" in number yet, index ' + this.place);
  98. };
  99. Parser.prototype.quoted = function(char) {
  100. if (char === '"') {
  101. this.state = AFTERQUOTE;
  102. return;
  103. }
  104. this.word += char;
  105. return;
  106. };
  107. Parser.prototype.keyword = function(char) {
  108. if (keyword.test(char)) {
  109. this.word += char;
  110. return;
  111. }
  112. if (char === '[') {
  113. var newObjects = [];
  114. newObjects.push(this.word);
  115. this.level++;
  116. if (this.root === null) {
  117. this.root = newObjects;
  118. } else {
  119. this.currentObject.push(newObjects);
  120. }
  121. this.stack.push(this.currentObject);
  122. this.currentObject = newObjects;
  123. this.state = NEUTRAL;
  124. return;
  125. }
  126. if (endThings.test(char)) {
  127. this.afterItem(char);
  128. return;
  129. }
  130. throw new Error('havn\'t handled "' +char + '" in keyword yet, index ' + this.place);
  131. };
  132. Parser.prototype.neutral = function(char) {
  133. if (latin.test(char)) {
  134. this.word = char;
  135. this.state = KEYWORD;
  136. return;
  137. }
  138. if (char === '"') {
  139. this.word = '';
  140. this.state = QUOTED;
  141. return;
  142. }
  143. if (digets.test(char)) {
  144. this.word = char;
  145. this.state = NUMBER;
  146. return;
  147. }
  148. if (endThings.test(char)) {
  149. this.afterItem(char);
  150. return;
  151. }
  152. throw new Error('havn\'t handled "' +char + '" in neutral yet, index ' + this.place);
  153. };
  154. Parser.prototype.output = function() {
  155. while (this.place < this.text.length) {
  156. this.readCharicter();
  157. }
  158. if (this.state === ENDED) {
  159. return this.root;
  160. }
  161. throw new Error('unable to parse string "' +this.text + '". State is ' + this.state);
  162. };
  163. function parseString(txt) {
  164. var parser = new Parser(txt);
  165. return parser.output();
  166. }