site/node_modules/speech-rule-engine/js/semantic_tree/semantic_skeleton.js

230 lines
7.8 KiB
JavaScript
Raw Permalink Normal View History

2024-10-14 06:09:33 +00:00
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SemanticSkeleton = void 0;
const BaseUtil = require("../common/base_util");
const XpathUtil = require("../common/xpath_util");
const enrich_attr_1 = require("../enrich_mathml/enrich_attr");
class SemanticSkeleton {
constructor(skeleton) {
this.parents = null;
this.levelsMap = null;
skeleton = skeleton === 0 ? skeleton : skeleton || [];
this.array = skeleton;
}
static fromTree(tree) {
return SemanticSkeleton.fromNode(tree.root);
}
static fromNode(node) {
return new SemanticSkeleton(SemanticSkeleton.fromNode_(node));
}
static fromString(skel) {
return new SemanticSkeleton(SemanticSkeleton.fromString_(skel));
}
static simpleCollapseStructure(strct) {
return typeof strct === 'number';
}
static contentCollapseStructure(strct) {
return (!!strct &&
!SemanticSkeleton.simpleCollapseStructure(strct) &&
strct[0] === 'c');
}
static interleaveIds(first, second) {
return BaseUtil.interleaveLists(SemanticSkeleton.collapsedLeafs(first), SemanticSkeleton.collapsedLeafs(second));
}
static collapsedLeafs(...args) {
const collapseStructure = (coll) => {
if (SemanticSkeleton.simpleCollapseStructure(coll)) {
return [coll];
}
coll = coll;
return SemanticSkeleton.contentCollapseStructure(coll[1])
? coll.slice(2)
: coll.slice(1);
};
return args.reduce((x, y) => x.concat(collapseStructure(y)), []);
}
static fromStructure(mml, tree) {
return new SemanticSkeleton(SemanticSkeleton.tree_(mml, tree.root));
}
static combineContentChildren(semantic, content, children) {
switch (semantic.type) {
case "relseq":
case "infixop":
case "multirel":
return BaseUtil.interleaveLists(children, content);
case "prefixop":
return content.concat(children);
case "postfixop":
return children.concat(content);
case "fenced":
children.unshift(content[0]);
children.push(content[1]);
return children;
case "appl":
return [children[0], content[0], children[1]];
case "root":
return [children[1], children[0]];
case "row":
case "line":
if (content.length) {
children.unshift(content[0]);
}
return children;
default:
return children;
}
}
static makeSexp_(struct) {
if (SemanticSkeleton.simpleCollapseStructure(struct)) {
return struct.toString();
}
if (SemanticSkeleton.contentCollapseStructure(struct)) {
return ('(' +
'c ' +
struct.slice(1).map(SemanticSkeleton.makeSexp_).join(' ') +
')');
}
return ('(' + struct.map(SemanticSkeleton.makeSexp_).join(' ') + ')');
}
static fromString_(skeleton) {
let str = skeleton.replace(/\(/g, '[');
str = str.replace(/\)/g, ']');
str = str.replace(/ /g, ',');
str = str.replace(/c/g, '"c"');
return JSON.parse(str);
}
static fromNode_(node) {
if (!node) {
return [];
}
const content = node.contentNodes;
let contentStructure;
if (content.length) {
contentStructure = content.map(SemanticSkeleton.fromNode_);
contentStructure.unshift('c');
}
const children = node.childNodes;
if (!children.length) {
return content.length ? [node.id, contentStructure] : node.id;
}
const structure = children.map(SemanticSkeleton.fromNode_);
if (content.length) {
structure.unshift(contentStructure);
}
structure.unshift(node.id);
return structure;
}
static tree_(mml, node) {
if (!node) {
return [];
}
if (!node.childNodes.length) {
return node.id;
}
const id = node.id;
const skeleton = [id];
const mmlChild = XpathUtil.evalXPath(`.//self::*[@${enrich_attr_1.Attribute.ID}=${id}]`, mml)[0];
const children = SemanticSkeleton.combineContentChildren(node, node.contentNodes.map(function (x) {
return x;
}), node.childNodes.map(function (x) {
return x;
}));
if (mmlChild) {
SemanticSkeleton.addOwns_(mmlChild, children);
}
for (let i = 0, child; (child = children[i]); i++) {
skeleton.push(SemanticSkeleton.tree_(mml, child));
}
return skeleton;
}
static addOwns_(node, children) {
const collapsed = node.getAttribute(enrich_attr_1.Attribute.COLLAPSED);
const leafs = collapsed
? SemanticSkeleton.realLeafs_(SemanticSkeleton.fromString(collapsed).array)
: children.map((x) => x.id);
node.setAttribute(enrich_attr_1.Attribute.OWNS, leafs.join(' '));
}
static realLeafs_(sexp) {
if (SemanticSkeleton.simpleCollapseStructure(sexp)) {
return [sexp];
}
if (SemanticSkeleton.contentCollapseStructure(sexp)) {
return [];
}
sexp = sexp;
let result = [];
for (let i = 1; i < sexp.length; i++) {
result = result.concat(SemanticSkeleton.realLeafs_(sexp[i]));
}
return result;
}
populate() {
if (this.parents && this.levelsMap) {
return;
}
this.parents = {};
this.levelsMap = {};
this.populate_(this.array, this.array, []);
}
toString() {
return SemanticSkeleton.makeSexp_(this.array);
}
populate_(element, layer, parents) {
if (SemanticSkeleton.simpleCollapseStructure(element)) {
element = element;
this.levelsMap[element] = layer;
this.parents[element] =
element === parents[0] ? parents.slice(1) : parents;
return;
}
const newElement = SemanticSkeleton.contentCollapseStructure(element)
? element.slice(1)
: element;
const newParents = [newElement[0]].concat(parents);
for (let i = 0, l = newElement.length; i < l; i++) {
const current = newElement[i];
this.populate_(current, element, newParents);
}
}
isRoot(id) {
const level = this.levelsMap[id];
return id === level[0];
}
directChildren(id) {
if (!this.isRoot(id)) {
return [];
}
const level = this.levelsMap[id];
return level.slice(1).map((child) => {
if (SemanticSkeleton.simpleCollapseStructure(child)) {
return child;
}
if (SemanticSkeleton.contentCollapseStructure(child)) {
return child[1];
}
return child[0];
});
}
subtreeNodes(id) {
if (!this.isRoot(id)) {
return [];
}
const subtreeNodes_ = (tree, nodes) => {
if (SemanticSkeleton.simpleCollapseStructure(tree)) {
nodes.push(tree);
return;
}
tree = tree;
if (SemanticSkeleton.contentCollapseStructure(tree)) {
tree = tree.slice(1);
}
tree.forEach((x) => subtreeNodes_(x, nodes));
};
const level = this.levelsMap[id];
const subtree = [];
subtreeNodes_(level.slice(1), subtree);
return subtree;
}
}
exports.SemanticSkeleton = SemanticSkeleton;