rebuild_stree.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.RebuildStree = void 0;
  4. const enrich_attr_js_1 = require("../enrich_mathml/enrich_attr.js");
  5. const semantic_attr_js_1 = require("../semantic_tree/semantic_attr.js");
  6. const semantic_meaning_js_1 = require("../semantic_tree/semantic_meaning.js");
  7. const semantic_node_factory_js_1 = require("../semantic_tree/semantic_node_factory.js");
  8. const semantic_skeleton_js_1 = require("../semantic_tree/semantic_skeleton.js");
  9. const semantic_tree_js_1 = require("../semantic_tree/semantic_tree.js");
  10. const WalkerUtil = require("./walker_util.js");
  11. class RebuildStree {
  12. static textContent(snode, node, ignore) {
  13. if (!ignore && node.textContent) {
  14. snode.textContent = node.textContent;
  15. return;
  16. }
  17. const operator = WalkerUtil.splitAttribute(WalkerUtil.getAttribute(node, enrich_attr_js_1.Attribute.OPERATOR));
  18. if (operator.length > 1) {
  19. snode.textContent = operator[1];
  20. }
  21. }
  22. static isPunctuated(collapsed) {
  23. return (!semantic_skeleton_js_1.SemanticSkeleton.simpleCollapseStructure(collapsed) &&
  24. collapsed[1] &&
  25. semantic_skeleton_js_1.SemanticSkeleton.contentCollapseStructure(collapsed[1]));
  26. }
  27. constructor(mathml) {
  28. this.mathml = mathml;
  29. this.factory = new semantic_node_factory_js_1.SemanticNodeFactory();
  30. this.nodeDict = {};
  31. this.mmlRoot = WalkerUtil.getSemanticRoot(mathml);
  32. this.streeRoot = this.assembleTree(this.mmlRoot);
  33. this.stree = semantic_tree_js_1.SemanticTree.fromNode(this.streeRoot, this.mathml);
  34. this.xml = this.stree.xml();
  35. }
  36. getTree() {
  37. return this.stree;
  38. }
  39. assembleTree(node) {
  40. const snode = this.makeNode(node);
  41. const children = WalkerUtil.splitAttribute(WalkerUtil.getAttribute(node, enrich_attr_js_1.Attribute.CHILDREN));
  42. const content = WalkerUtil.splitAttribute(WalkerUtil.getAttribute(node, enrich_attr_js_1.Attribute.CONTENT));
  43. if (content.length === 0 && children.length === 0) {
  44. RebuildStree.textContent(snode, node);
  45. return snode;
  46. }
  47. if (content.length > 0) {
  48. const fcontent = WalkerUtil.getBySemanticId(this.mathml, content[0]);
  49. if (fcontent) {
  50. RebuildStree.textContent(snode, fcontent, true);
  51. }
  52. }
  53. snode.contentNodes = content.map((id) => this.setParent(id, snode));
  54. snode.childNodes = children.map((id) => this.setParent(id, snode));
  55. const collapsed = WalkerUtil.getAttribute(node, enrich_attr_js_1.Attribute.COLLAPSED);
  56. return collapsed ? this.postProcess(snode, collapsed) : snode;
  57. }
  58. makeNode(node) {
  59. const type = WalkerUtil.getAttribute(node, enrich_attr_js_1.Attribute.TYPE);
  60. const role = WalkerUtil.getAttribute(node, enrich_attr_js_1.Attribute.ROLE);
  61. const font = WalkerUtil.getAttribute(node, enrich_attr_js_1.Attribute.FONT);
  62. const annotation = WalkerUtil.getAttribute(node, enrich_attr_js_1.Attribute.ANNOTATION) || '';
  63. const attributes = WalkerUtil.getAttribute(node, enrich_attr_js_1.Attribute.ATTRIBUTES) || '';
  64. const id = WalkerUtil.getAttribute(node, enrich_attr_js_1.Attribute.ID);
  65. const embellished = WalkerUtil.getAttribute(node, enrich_attr_js_1.Attribute.EMBELLISHED);
  66. const fencepointer = WalkerUtil.getAttribute(node, enrich_attr_js_1.Attribute.FENCEPOINTER);
  67. const snode = this.createNode(parseInt(id, 10));
  68. snode.type = type;
  69. snode.role = role;
  70. snode.font = font ? font : semantic_meaning_js_1.SemanticFont.UNKNOWN;
  71. snode.parseAnnotation(annotation);
  72. snode.parseAttributes(attributes);
  73. if (fencepointer) {
  74. snode.fencePointer = fencepointer;
  75. }
  76. if (embellished) {
  77. snode.embellished = embellished;
  78. }
  79. return snode;
  80. }
  81. makePunctuation(id) {
  82. const node = this.createNode(id);
  83. node.updateContent(semantic_attr_js_1.NamedSymbol.invisibleComma);
  84. node.role = semantic_meaning_js_1.SemanticRole.DUMMY;
  85. return node;
  86. }
  87. makePunctuated(snode, collapsed, role) {
  88. const punctuated = this.createNode(collapsed[0]);
  89. punctuated.type = semantic_meaning_js_1.SemanticType.PUNCTUATED;
  90. punctuated.embellished = snode.embellished;
  91. punctuated.fencePointer = snode.fencePointer;
  92. punctuated.role = role;
  93. const cont = collapsed.splice(1, 1)[0].slice(1);
  94. punctuated.contentNodes = cont.map(this.makePunctuation.bind(this));
  95. this.collapsedChildren_(collapsed);
  96. }
  97. makeEmpty(snode, collapsed, role) {
  98. const empty = this.createNode(collapsed);
  99. empty.type = semantic_meaning_js_1.SemanticType.EMPTY;
  100. empty.embellished = snode.embellished;
  101. empty.fencePointer = snode.fencePointer;
  102. empty.role = role;
  103. }
  104. makeIndex(snode, collapsed, role) {
  105. if (RebuildStree.isPunctuated(collapsed)) {
  106. this.makePunctuated(snode, collapsed, role);
  107. collapsed = collapsed[0];
  108. return;
  109. }
  110. if (semantic_skeleton_js_1.SemanticSkeleton.simpleCollapseStructure(collapsed) &&
  111. !this.nodeDict[collapsed.toString()]) {
  112. this.makeEmpty(snode, collapsed, role);
  113. }
  114. }
  115. postProcess(snode, collapsed) {
  116. const array = semantic_skeleton_js_1.SemanticSkeleton.fromString(collapsed).array;
  117. if (snode.type === semantic_meaning_js_1.SemanticRole.SUBSUP) {
  118. const subscript = this.createNode(array[1][0]);
  119. subscript.type = semantic_meaning_js_1.SemanticType.SUBSCRIPT;
  120. subscript.role = semantic_meaning_js_1.SemanticRole.SUBSUP;
  121. snode.type = semantic_meaning_js_1.SemanticType.SUPERSCRIPT;
  122. subscript.embellished = snode.embellished;
  123. subscript.fencePointer = snode.fencePointer;
  124. this.makeIndex(snode, array[1][2], semantic_meaning_js_1.SemanticRole.RIGHTSUB);
  125. this.makeIndex(snode, array[2], semantic_meaning_js_1.SemanticRole.RIGHTSUPER);
  126. this.collapsedChildren_(array);
  127. return snode;
  128. }
  129. if (snode.type === semantic_meaning_js_1.SemanticType.SUBSCRIPT) {
  130. this.makeIndex(snode, array[2], semantic_meaning_js_1.SemanticRole.RIGHTSUB);
  131. this.collapsedChildren_(array);
  132. return snode;
  133. }
  134. if (snode.type === semantic_meaning_js_1.SemanticType.SUPERSCRIPT) {
  135. this.makeIndex(snode, array[2], semantic_meaning_js_1.SemanticRole.RIGHTSUPER);
  136. this.collapsedChildren_(array);
  137. return snode;
  138. }
  139. if (snode.type === semantic_meaning_js_1.SemanticType.TENSOR) {
  140. this.makeIndex(snode, array[2], semantic_meaning_js_1.SemanticRole.LEFTSUB);
  141. this.makeIndex(snode, array[3], semantic_meaning_js_1.SemanticRole.LEFTSUPER);
  142. this.makeIndex(snode, array[4], semantic_meaning_js_1.SemanticRole.RIGHTSUB);
  143. this.makeIndex(snode, array[5], semantic_meaning_js_1.SemanticRole.RIGHTSUPER);
  144. this.collapsedChildren_(array);
  145. return snode;
  146. }
  147. if (snode.type === semantic_meaning_js_1.SemanticType.PUNCTUATED) {
  148. if (RebuildStree.isPunctuated(array)) {
  149. const cont = array.splice(1, 1)[0].slice(1);
  150. snode.contentNodes = cont.map(this.makePunctuation.bind(this));
  151. }
  152. return snode;
  153. }
  154. if (snode.type === semantic_meaning_js_1.SemanticRole.UNDEROVER) {
  155. const score = this.createNode(array[1][0]);
  156. if (snode.childNodes[1].role === semantic_meaning_js_1.SemanticRole.OVERACCENT) {
  157. score.type = semantic_meaning_js_1.SemanticType.OVERSCORE;
  158. snode.type = semantic_meaning_js_1.SemanticType.UNDERSCORE;
  159. }
  160. else {
  161. score.type = semantic_meaning_js_1.SemanticType.UNDERSCORE;
  162. snode.type = semantic_meaning_js_1.SemanticType.OVERSCORE;
  163. }
  164. score.role = semantic_meaning_js_1.SemanticRole.UNDEROVER;
  165. score.embellished = snode.embellished;
  166. score.fencePointer = snode.fencePointer;
  167. this.collapsedChildren_(array);
  168. return snode;
  169. }
  170. return snode;
  171. }
  172. createNode(id) {
  173. const node = this.factory.makeNode(id);
  174. this.nodeDict[id.toString()] = node;
  175. return node;
  176. }
  177. collapsedChildren_(collapsed) {
  178. const recurseCollapsed = (coll) => {
  179. const parent = this.nodeDict[coll[0]];
  180. parent.childNodes = [];
  181. for (let j = 1, l = coll.length; j < l; j++) {
  182. const id = coll[j];
  183. parent.childNodes.push(semantic_skeleton_js_1.SemanticSkeleton.simpleCollapseStructure(id)
  184. ? this.nodeDict[id]
  185. : recurseCollapsed(id));
  186. }
  187. return parent;
  188. };
  189. recurseCollapsed(collapsed);
  190. }
  191. setParent(id, snode) {
  192. const mml = WalkerUtil.getBySemanticId(this.mathml, id);
  193. const sn = this.assembleTree(mml);
  194. sn.parent = snode;
  195. return sn;
  196. }
  197. }
  198. exports.RebuildStree = RebuildStree;