reader-doc-parser.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. const stream = require('stream');
  2. const split2 = require('split2');
  3. const pumpify = require('pumpify');
  4. const EXTRA_DOCUMENTATION = require('./extra-documentation.js');
  5. let constant_counter = 0;
  6. const STATE_INIT = constant_counter++;
  7. const STATE_HEADER_FOUND_SKIP_NEXT = constant_counter++;
  8. const STATE_BODY = constant_counter++;
  9. const STATE_LAST_LINE_EMPTY = constant_counter++;
  10. const STATE_FOOTER = constant_counter++;
  11. const SPLIT_DOC = /^((?:[A-Za-z0-9,.'-]+| (?! )|\(digamma\))+) (\([A-Za-z']+\))? *([a-z0-9]+)/
  12. class DocLineParser extends stream.Transform {
  13. constructor() {
  14. super({ objectMode: true });
  15. this._state = STATE_INIT;
  16. this._category = '';
  17. this._emittedFunctionNames = new Set();
  18. }
  19. _setBodyCategory(line) {
  20. this._category = line;
  21. if (EXTRA_DOCUMENTATION.has(this._category)) {
  22. for (const extraDoc of EXTRA_DOCUMENTATION.get(this._category)) {
  23. this._emittedFunctionNames.add(extraDoc.functionName);
  24. this.push(extraDoc);
  25. }
  26. }
  27. }
  28. _parseBodyContent(line) {
  29. const match = line.match(SPLIT_DOC);
  30. if (match === null) return;
  31. const [, description, extra, functionName] = match;
  32. // Ensure that dublicate don't appear
  33. if (!this._emittedFunctionNames.has(functionName)) {
  34. this._emittedFunctionNames.add(functionName);
  35. this.push({
  36. category: this._category,
  37. description: description,
  38. functionName: functionName
  39. });
  40. }
  41. }
  42. _parseBody(line) {
  43. if (line.startsWith(' ')) {
  44. this._setBodyCategory(line.trim());
  45. } else {
  46. this._parseBodyContent(line.trim());
  47. }
  48. }
  49. _transform(line, encoding, done) {
  50. switch (this._state) {
  51. case STATE_INIT:
  52. if (line.startsWith('--------')) {
  53. this._state = STATE_HEADER_FOUND_SKIP_NEXT;
  54. }
  55. break;
  56. case STATE_HEADER_FOUND_SKIP_NEXT:
  57. this._state = STATE_BODY;
  58. break;
  59. case STATE_BODY:
  60. if (line === '') {
  61. this._state = STATE_LAST_LINE_EMPTY;
  62. } else {
  63. this._parseBody(line);
  64. }
  65. break;
  66. case STATE_LAST_LINE_EMPTY:
  67. if (line === '') {
  68. this._state = STATE_FOOTER;
  69. } else {
  70. this._state = STATE_BODY;
  71. this._parseBody(line);
  72. }
  73. break;
  74. case STATE_FOOTER:
  75. break;
  76. default:
  77. throw new Error(`unknown state ${this._state}`);
  78. }
  79. done(null);
  80. }
  81. _flush(done) {
  82. this._setBodyCategory('Polynomials and Power Series');
  83. done(null);
  84. }
  85. }
  86. function docParser() {
  87. return pumpify.obj(
  88. split2(),
  89. new DocLineParser()
  90. );
  91. }
  92. module.exports = docParser;