semantic_walker.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import { SemanticRole, SemanticType } from '../semantic_tree/semantic_meaning.js';
  2. import { AbstractWalker } from './abstract_walker.js';
  3. import { Levels } from './levels.js';
  4. export class SemanticWalker extends AbstractWalker {
  5. constructor(node, generator, highlighter, xml) {
  6. super(node, generator, highlighter, xml);
  7. this.node = node;
  8. this.generator = generator;
  9. this.highlighter = highlighter;
  10. this.levels = null;
  11. this.restoreState();
  12. }
  13. initLevels() {
  14. const levels = new Levels();
  15. levels.push([this.getFocus()]);
  16. return levels;
  17. }
  18. up() {
  19. super.up();
  20. const parent = this.previousLevel();
  21. if (!parent) {
  22. return null;
  23. }
  24. this.levels.pop();
  25. const found = this.levels.find(function (focus) {
  26. return focus.getSemanticNodes().some(function (node) {
  27. return node.id.toString() === parent;
  28. });
  29. });
  30. return found;
  31. }
  32. down() {
  33. super.down();
  34. const children = this.nextLevel();
  35. if (children.length === 0) {
  36. return null;
  37. }
  38. this.levels.push(children);
  39. return children[0];
  40. }
  41. combineContentChildren(type, role, content, children) {
  42. switch (type) {
  43. case SemanticType.RELSEQ:
  44. case SemanticType.INFIXOP:
  45. case SemanticType.MULTIREL:
  46. return this.makePairList(children, content);
  47. case SemanticType.PREFIXOP:
  48. return [this.focusFromId(children[0], content.concat(children))];
  49. case SemanticType.POSTFIXOP:
  50. return [this.focusFromId(children[0], children.concat(content))];
  51. case SemanticType.MATRIX:
  52. case SemanticType.VECTOR:
  53. case SemanticType.FENCED:
  54. return [
  55. this.focusFromId(children[0], [content[0], children[0], content[1]])
  56. ];
  57. case SemanticType.CASES:
  58. return [this.focusFromId(children[0], [content[0], children[0]])];
  59. case SemanticType.PUNCTUATED:
  60. if (role === SemanticRole.TEXT) {
  61. return children.map(this.singletonFocus.bind(this));
  62. }
  63. if (children.length === content.length) {
  64. return content.map(this.singletonFocus.bind(this));
  65. }
  66. return this.combinePunctuations(children, content, [], []);
  67. case SemanticType.APPL:
  68. return [
  69. this.focusFromId(children[0], [children[0], content[0]]),
  70. this.singletonFocus(children[1])
  71. ];
  72. case SemanticType.ROOT:
  73. return [
  74. this.singletonFocus(children[0]),
  75. this.singletonFocus(children[1])
  76. ];
  77. default:
  78. return children.map(this.singletonFocus.bind(this));
  79. }
  80. }
  81. combinePunctuations(children, content, prepunct, acc) {
  82. if (children.length === 0) {
  83. return acc;
  84. }
  85. const child = children.shift();
  86. const cont = content.shift();
  87. if (child === cont) {
  88. prepunct.push(cont);
  89. return this.combinePunctuations(children, content, prepunct, acc);
  90. }
  91. else {
  92. content.unshift(cont);
  93. prepunct.push(child);
  94. if (children.length === content.length) {
  95. acc.push(this.focusFromId(child, prepunct.concat(content)));
  96. return acc;
  97. }
  98. else {
  99. acc.push(this.focusFromId(child, prepunct));
  100. return this.combinePunctuations(children, content, [], acc);
  101. }
  102. }
  103. }
  104. makePairList(children, content) {
  105. if (children.length === 0) {
  106. return [];
  107. }
  108. if (children.length === 1) {
  109. return [this.singletonFocus(children[0])];
  110. }
  111. const result = [this.singletonFocus(children.shift())];
  112. for (let i = 0, l = children.length; i < l; i++) {
  113. result.push(this.focusFromId(children[i], [content[i], children[i]]));
  114. }
  115. return result;
  116. }
  117. left() {
  118. super.left();
  119. const index = this.levels.indexOf(this.getFocus());
  120. if (index === null) {
  121. return null;
  122. }
  123. const ids = this.levels.get(index - 1);
  124. return ids ? ids : null;
  125. }
  126. right() {
  127. super.right();
  128. const index = this.levels.indexOf(this.getFocus());
  129. if (index === null) {
  130. return null;
  131. }
  132. const ids = this.levels.get(index + 1);
  133. return ids ? ids : null;
  134. }
  135. findFocusOnLevel(id) {
  136. const focus = this.levels.find((x) => {
  137. const pid = x.getSemanticPrimary().id;
  138. return pid === id;
  139. });
  140. return focus;
  141. }
  142. }