12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955 |
- import * as DomUtil from '../common/dom_util.js';
- import { NamedSymbol, SemanticMap } from './semantic_attr.js';
- import { SemanticFont, SemanticRole, SemanticType, SemanticSecondary } from './semantic_meaning.js';
- import { SemanticHeuristics } from './semantic_heuristic_factory.js';
- import { SemanticNodeFactory } from './semantic_node_factory.js';
- import * as SemanticPred from './semantic_pred.js';
- import * as SemanticUtil from './semantic_util.js';
- import { MMLTAGS } from '../semantic_tree/semantic_util.js';
- export class SemanticProcessor {
- static getInstance() {
- SemanticProcessor.instance =
- SemanticProcessor.instance || new SemanticProcessor();
- return SemanticProcessor.instance;
- }
- static tableToMultiline(table) {
- if (!SemanticPred.tableIsMultiline(table)) {
- return SemanticHeuristics.run('rewrite_subcases', table, SemanticProcessor.classifyTable);
- }
- table.type = SemanticType.MULTILINE;
- for (let i = 0, row; (row = table.childNodes[i]); i++) {
- SemanticProcessor.rowToLine_(row, SemanticRole.MULTILINE);
- }
- if (table.childNodes.length === 1 &&
- !SemanticPred.lineIsLabelled(table.childNodes[0]) &&
- SemanticPred.isFencedElement(table.childNodes[0].childNodes[0])) {
- SemanticProcessor.tableToMatrixOrVector_(SemanticProcessor.rewriteFencedLine_(table));
- }
- SemanticProcessor.binomialForm_(table);
- SemanticProcessor.classifyMultiline(table);
- return table;
- }
- static number(node) {
- if (node.type === SemanticType.UNKNOWN ||
- node.type === SemanticType.IDENTIFIER) {
- node.type = SemanticType.NUMBER;
- }
- SemanticProcessor.meaningFromContent(node, SemanticProcessor.numberRole_);
- SemanticProcessor.exprFont_(node);
- }
- static classifyMultiline(multiline) {
- let index = 0;
- const length = multiline.childNodes.length;
- let line;
- while (index < length &&
- (!(line = multiline.childNodes[index]) || !line.childNodes.length)) {
- index++;
- }
- if (index >= length) {
- return;
- }
- const firstRole = line.childNodes[0].role;
- if (firstRole !== SemanticRole.UNKNOWN &&
- multiline.childNodes.every(function (x) {
- const cell = x.childNodes[0];
- return (!cell ||
- (cell.role === firstRole &&
- (SemanticPred.isType(cell, SemanticType.RELATION) ||
- SemanticPred.isType(cell, SemanticType.RELSEQ))));
- })) {
- multiline.role = firstRole;
- }
- }
- static classifyTable(table) {
- const columns = SemanticProcessor.computeColumns_(table);
- SemanticProcessor.classifyByColumns_(table, columns, SemanticRole.EQUALITY) ||
- SemanticProcessor.classifyByColumns_(table, columns, SemanticRole.INEQUALITY, [SemanticRole.EQUALITY]) ||
- SemanticProcessor.classifyByColumns_(table, columns, SemanticRole.ARROW) ||
- SemanticProcessor.detectCaleyTable(table);
- return table;
- }
- static detectCaleyTable(table) {
- if (!table.mathmlTree) {
- return false;
- }
- const tree = table.mathmlTree;
- const cl = tree.getAttribute('columnlines');
- const rl = tree.getAttribute('rowlines');
- if (!cl || !rl) {
- return false;
- }
- if (SemanticProcessor.cayleySpacing(cl) &&
- SemanticProcessor.cayleySpacing(rl)) {
- table.role = SemanticRole.CAYLEY;
- return true;
- }
- return false;
- }
- static cayleySpacing(lines) {
- const list = lines.split(' ');
- return ((list[0] === 'solid' || list[0] === 'dashed') &&
- list.slice(1).every((x) => x === 'none'));
- }
- static proof(node, semantics, parse) {
- const attrs = SemanticProcessor.separateSemantics(semantics);
- return SemanticProcessor.getInstance().proof(node, attrs, parse);
- }
- static findSemantics(node, attr, opt_value) {
- const value = opt_value == null ? null : opt_value;
- const semantics = SemanticProcessor.getSemantics(node);
- if (!semantics) {
- return false;
- }
- if (!semantics[attr]) {
- return false;
- }
- return value == null ? true : semantics[attr] === value;
- }
- static getSemantics(node) {
- const semantics = node.getAttribute('semantics');
- if (!semantics) {
- return null;
- }
- return SemanticProcessor.separateSemantics(semantics);
- }
- static removePrefix(name) {
- const [, ...rest] = name.split('_');
- return rest.join('_');
- }
- static separateSemantics(attr) {
- const result = {};
- attr.split(';').forEach(function (x) {
- const [name, value] = x.split(':');
- result[SemanticProcessor.removePrefix(name)] = value;
- });
- return result;
- }
- static matchSpaces_(nodes, ops) {
- for (let i = 0, op; (op = ops[i]); i++) {
- const node = nodes[i];
- const mt1 = node.mathmlTree;
- const mt2 = nodes[i + 1].mathmlTree;
- if (!mt1 || !mt2) {
- continue;
- }
- const sibling = mt1.nextSibling;
- if (!sibling || sibling === mt2) {
- continue;
- }
- const spacer = SemanticProcessor.getSpacer_(sibling);
- if (spacer) {
- op.mathml.push(spacer);
- op.mathmlTree = spacer;
- op.role = SemanticRole.SPACE;
- }
- }
- }
- static getSpacer_(node) {
- if (DomUtil.tagName(node) === MMLTAGS.MSPACE) {
- return node;
- }
- while (SemanticUtil.hasEmptyTag(node) && node.childNodes.length === 1) {
- node = node.childNodes[0];
- if (DomUtil.tagName(node) === MMLTAGS.MSPACE) {
- return node;
- }
- }
- return null;
- }
- static fenceToPunct_(fence) {
- const newRole = SemanticProcessor.FENCE_TO_PUNCT_[fence.role];
- if (!newRole) {
- return;
- }
- while (fence.embellished) {
- fence.embellished = SemanticType.PUNCTUATION;
- if (!(SemanticPred.isRole(fence, SemanticRole.SUBSUP) ||
- SemanticPred.isRole(fence, SemanticRole.UNDEROVER))) {
- fence.role = newRole;
- }
- fence = fence.childNodes[0];
- }
- fence.type = SemanticType.PUNCTUATION;
- fence.role = newRole;
- }
- static classifyFunction_(funcNode, restNodes) {
- if (funcNode.type === SemanticType.APPL ||
- funcNode.type === SemanticType.BIGOP ||
- funcNode.type === SemanticType.INTEGRAL) {
- return '';
- }
- if (restNodes[0] &&
- restNodes[0].textContent === NamedSymbol.functionApplication) {
- SemanticProcessor.getInstance().funcAppls[funcNode.id] =
- restNodes.shift();
- let role = SemanticRole.SIMPLEFUNC;
- SemanticHeuristics.run('simple2prefix', funcNode);
- if (funcNode.role === SemanticRole.PREFIXFUNC ||
- funcNode.role === SemanticRole.LIMFUNC) {
- role = funcNode.role;
- }
- SemanticProcessor.propagateFunctionRole_(funcNode, role);
- return 'prefix';
- }
- const kind = SemanticProcessor.CLASSIFY_FUNCTION_[funcNode.role];
- return kind
- ? kind
- : SemanticPred.isSimpleFunctionHead(funcNode)
- ? 'simple'
- : '';
- }
- static propagateFunctionRole_(funcNode, tag) {
- if (funcNode) {
- if (funcNode.type === SemanticType.INFIXOP) {
- return;
- }
- if (!(SemanticPred.isRole(funcNode, SemanticRole.SUBSUP) ||
- SemanticPred.isRole(funcNode, SemanticRole.UNDEROVER))) {
- funcNode.role = tag;
- }
- SemanticProcessor.propagateFunctionRole_(funcNode.childNodes[0], tag);
- }
- }
- static getFunctionOp_(tree, pred) {
- if (pred(tree)) {
- return tree;
- }
- for (let i = 0, child; (child = tree.childNodes[i]); i++) {
- const op = SemanticProcessor.getFunctionOp_(child, pred);
- if (op) {
- return op;
- }
- }
- return null;
- }
- static tableToMatrixOrVector_(node) {
- const matrix = node.childNodes[0];
- SemanticPred.isType(matrix, SemanticType.MULTILINE)
- ? SemanticProcessor.tableToVector_(node)
- : SemanticProcessor.tableToMatrix_(node);
- node.contentNodes.forEach(matrix.appendContentNode.bind(matrix));
- for (let i = 0, row; (row = matrix.childNodes[i]); i++) {
- SemanticProcessor.assignRoleToRow_(row, SemanticProcessor.getComponentRoles_(matrix));
- }
- matrix.parent = null;
- return matrix;
- }
- static tableToVector_(node) {
- const vector = node.childNodes[0];
- vector.type = SemanticType.VECTOR;
- if (vector.childNodes.length === 1) {
- SemanticProcessor.tableToSquare_(node);
- return;
- }
- SemanticProcessor.binomialForm_(vector);
- }
- static binomialForm_(node) {
- if (!SemanticPred.isRole(node, SemanticRole.UNKNOWN)) {
- return;
- }
- if (SemanticPred.isBinomial(node)) {
- node.role = SemanticRole.BINOMIAL;
- node.childNodes[0].role = SemanticRole.BINOMIAL;
- node.childNodes[1].role = SemanticRole.BINOMIAL;
- }
- }
- static tableToMatrix_(node) {
- const matrix = node.childNodes[0];
- matrix.type = SemanticType.MATRIX;
- if (matrix.childNodes &&
- matrix.childNodes.length > 0 &&
- matrix.childNodes[0].childNodes &&
- matrix.childNodes.length === matrix.childNodes[0].childNodes.length) {
- SemanticProcessor.tableToSquare_(node);
- return;
- }
- if (matrix.childNodes && matrix.childNodes.length === 1) {
- matrix.role = SemanticRole.ROWVECTOR;
- }
- }
- static tableToSquare_(node) {
- const matrix = node.childNodes[0];
- if (!SemanticPred.isRole(matrix, SemanticRole.UNKNOWN)) {
- return;
- }
- if (SemanticPred.isNeutralFence(node)) {
- matrix.role = SemanticRole.DETERMINANT;
- return;
- }
- matrix.role = SemanticRole.SQUAREMATRIX;
- }
- static getComponentRoles_(node) {
- const role = node.role;
- if (role && role !== SemanticRole.UNKNOWN) {
- return role;
- }
- return node.type.toLowerCase() || SemanticRole.UNKNOWN;
- }
- static tableToCases_(table, openFence) {
- for (let i = 0, row; (row = table.childNodes[i]); i++) {
- SemanticProcessor.assignRoleToRow_(row, SemanticRole.CASES);
- }
- table.type = SemanticType.CASES;
- table.appendContentNode(openFence);
- if (SemanticPred.tableIsMultiline(table)) {
- SemanticProcessor.binomialForm_(table);
- }
- return table;
- }
- static rewriteFencedLine_(table) {
- const line = table.childNodes[0];
- const fenced = table.childNodes[0].childNodes[0];
- const element = table.childNodes[0].childNodes[0].childNodes[0];
- fenced.parent = table.parent;
- table.parent = fenced;
- element.parent = line;
- fenced.childNodes = [table];
- line.childNodes = [element];
- return fenced;
- }
- static rowToLine_(row, opt_role) {
- const role = opt_role || SemanticRole.UNKNOWN;
- if (SemanticPred.isType(row, SemanticType.ROW)) {
- row.type = SemanticType.LINE;
- row.role = role;
- if (row.childNodes.length === 1 &&
- SemanticPred.isType(row.childNodes[0], SemanticType.CELL)) {
- row.childNodes = row.childNodes[0].childNodes;
- row.childNodes.forEach(function (x) {
- x.parent = row;
- });
- }
- }
- }
- static assignRoleToRow_(row, role) {
- if (SemanticPred.isType(row, SemanticType.LINE)) {
- row.role = role;
- return;
- }
- if (SemanticPred.isType(row, SemanticType.ROW)) {
- row.role = role;
- row.childNodes.forEach(function (cell) {
- if (SemanticPred.isType(cell, SemanticType.CELL)) {
- cell.role = role;
- }
- });
- }
- }
- static nextSeparatorFunction_(separators) {
- let sepList;
- if (separators) {
- if (separators.match(/^\s+$/)) {
- return null;
- }
- else {
- sepList = separators
- .replace(/\s/g, '')
- .split('')
- .filter(function (x) {
- return x;
- });
- }
- }
- else {
- sepList = [','];
- }
- return function () {
- if (sepList.length > 1) {
- return sepList.shift();
- }
- return sepList[0];
- };
- }
- static meaningFromContent(node, func) {
- const content = [...node.textContent].filter((x) => x.match(/[^\s]/));
- const meaning = content.map((x) => SemanticMap.Meaning.get(x));
- func(node, content, meaning);
- }
- static numberRole_(node, content, meaning) {
- if (node.role !== SemanticRole.UNKNOWN) {
- return;
- }
- if (meaning.every(function (x) {
- return ((x.type === SemanticType.NUMBER && x.role === SemanticRole.INTEGER) ||
- (x.type === SemanticType.PUNCTUATION && x.role === SemanticRole.COMMA));
- })) {
- node.role = SemanticRole.INTEGER;
- if (content[0] === '0') {
- node.addAnnotation('general', 'basenumber');
- }
- return;
- }
- if (meaning.every(function (x) {
- return ((x.type === SemanticType.NUMBER && x.role === SemanticRole.INTEGER) ||
- x.type === SemanticType.PUNCTUATION);
- })) {
- node.role = SemanticRole.FLOAT;
- return;
- }
- node.role = SemanticRole.OTHERNUMBER;
- }
- static exprFont_(node) {
- if (node.font !== SemanticFont.UNKNOWN) {
- return;
- }
- SemanticProcessor.compSemantics(node, 'font', SemanticFont);
- }
- static compSemantics(node, field, sem) {
- const content = [...node.textContent];
- const meaning = content.map((x) => SemanticMap.Meaning.get(x));
- const single = meaning.reduce(function (prev, curr) {
- if (!prev ||
- !curr[field] ||
- curr[field] === sem.UNKNOWN ||
- curr[field] === prev) {
- return prev;
- }
- if (prev === sem.UNKNOWN) {
- return curr[field];
- }
- return null;
- }, sem.UNKNOWN);
- if (single) {
- node[field] = single;
- }
- }
- static purgeFences_(partition) {
- const rel = partition.rel;
- const comp = partition.comp;
- const newRel = [];
- const newComp = [];
- while (rel.length > 0) {
- const currentRel = rel.shift();
- let currentComp = comp.shift();
- if (SemanticPred.isElligibleEmbellishedFence(currentRel)) {
- newRel.push(currentRel);
- newComp.push(currentComp);
- continue;
- }
- SemanticProcessor.fenceToPunct_(currentRel);
- currentComp.push(currentRel);
- currentComp = currentComp.concat(comp.shift());
- comp.unshift(currentComp);
- }
- newComp.push(comp.shift());
- return { rel: newRel, comp: newComp };
- }
- static rewriteFencedNode_(fenced) {
- const ofence = fenced.contentNodes[0];
- const cfence = fenced.contentNodes[1];
- let rewritten = SemanticProcessor.rewriteFence_(fenced, ofence);
- fenced.contentNodes[0] = rewritten.fence;
- rewritten = SemanticProcessor.rewriteFence_(rewritten.node, cfence);
- fenced.contentNodes[1] = rewritten.fence;
- fenced.contentNodes[0].parent = fenced;
- fenced.contentNodes[1].parent = fenced;
- rewritten.node.parent = null;
- return rewritten.node;
- }
- static rewriteFence_(node, fence) {
- if (!fence.embellished) {
- return { node: node, fence: fence };
- }
- const newFence = fence.childNodes[0];
- const rewritten = SemanticProcessor.rewriteFence_(node, newFence);
- if (SemanticPred.isType(fence, SemanticType.SUPERSCRIPT) ||
- SemanticPred.isType(fence, SemanticType.SUBSCRIPT) ||
- SemanticPred.isType(fence, SemanticType.TENSOR)) {
- if (!SemanticPred.isRole(fence, SemanticRole.SUBSUP)) {
- fence.role = node.role;
- }
- if (newFence !== rewritten.node) {
- fence.replaceChild(newFence, rewritten.node);
- newFence.parent = node;
- }
- SemanticProcessor.propagateFencePointer_(fence, newFence);
- return { node: fence, fence: rewritten.fence };
- }
- fence.replaceChild(newFence, rewritten.fence);
- if (fence.mathmlTree && fence.mathml.indexOf(fence.mathmlTree) === -1) {
- fence.mathml.push(fence.mathmlTree);
- }
- return { node: rewritten.node, fence: fence };
- }
- static propagateFencePointer_(oldNode, newNode) {
- oldNode.fencePointer = newNode.fencePointer || newNode.id.toString();
- oldNode.embellished = null;
- }
- static classifyByColumns_(table, columns, relation, alternatives = []) {
- const relations = [relation].concat(alternatives);
- const test1 = (x) => SemanticProcessor.isPureRelation_(x, relations);
- const test2 = (x) => SemanticProcessor.isEndRelation_(x, relations) ||
- SemanticProcessor.isPureRelation_(x, relations);
- const test3 = (x) => SemanticProcessor.isEndRelation_(x, relations, true) ||
- SemanticProcessor.isPureRelation_(x, relations);
- if ((columns.length === 3 &&
- SemanticProcessor.testColumns_(columns, 1, test1)) ||
- (columns.length === 2 &&
- (SemanticProcessor.testColumns_(columns, 1, test2) ||
- SemanticProcessor.testColumns_(columns, 0, test3)))) {
- table.role = relation;
- return true;
- }
- return false;
- }
- static isEndRelation_(node, relations, opt_right) {
- const position = opt_right ? node.childNodes.length - 1 : 0;
- return (SemanticPred.isType(node, SemanticType.RELSEQ) &&
- relations.some((relation) => SemanticPred.isRole(node, relation)) &&
- SemanticPred.isType(node.childNodes[position], SemanticType.EMPTY));
- }
- static isPureRelation_(node, relations) {
- return (SemanticPred.isType(node, SemanticType.RELATION) &&
- relations.some((relation) => SemanticPred.isRole(node, relation)));
- }
- static computeColumns_(table) {
- const columns = [];
- for (let i = 0, row; (row = table.childNodes[i]); i++) {
- for (let j = 0, cell; (cell = row.childNodes[j]); j++) {
- const column = columns[j];
- column ? columns[j].push(cell) : (columns[j] = [cell]);
- }
- }
- return columns;
- }
- static testColumns_(columns, index, pred) {
- const column = columns[index];
- return column
- ? column.some(function (cell) {
- return (cell.childNodes.length && pred(cell.childNodes[0]));
- }) &&
- column.every(function (cell) {
- return (!cell.childNodes.length ||
- pred(cell.childNodes[0]));
- })
- : false;
- }
- setNodeFactory(factory) {
- SemanticProcessor.getInstance().factory_ = factory;
- SemanticHeuristics.updateFactory(SemanticProcessor.getInstance().factory_);
- }
- getNodeFactory() {
- return SemanticProcessor.getInstance().factory_;
- }
- identifierNode(leaf, font, unit) {
- if (unit === 'MathML-Unit') {
- leaf.type = SemanticType.IDENTIFIER;
- leaf.role = SemanticRole.UNIT;
- }
- else if (!font &&
- leaf.textContent.length === 1 &&
- (leaf.role === SemanticRole.INTEGER ||
- leaf.role === SemanticRole.LATINLETTER ||
- leaf.role === SemanticRole.GREEKLETTER) &&
- leaf.font === SemanticFont.NORMAL) {
- leaf.font = SemanticFont.ITALIC;
- return SemanticHeuristics.run('simpleNamedFunction', leaf);
- }
- if (leaf.type === SemanticType.UNKNOWN) {
- leaf.type = SemanticType.IDENTIFIER;
- }
- SemanticProcessor.exprFont_(leaf);
- return SemanticHeuristics.run('simpleNamedFunction', leaf);
- }
- implicitNode(nodes) {
- nodes = SemanticProcessor.getInstance().getMixedNumbers_(nodes);
- nodes = SemanticProcessor.getInstance().combineUnits_(nodes);
- if (nodes.length === 1) {
- return nodes[0];
- }
- const node = SemanticProcessor.getInstance().implicitNode_(nodes);
- return SemanticHeuristics.run('combine_juxtaposition', node);
- }
- text(leaf, type) {
- SemanticProcessor.exprFont_(leaf);
- leaf.type = SemanticType.TEXT;
- if (type === MMLTAGS.ANNOTATIONXML) {
- leaf.role = SemanticRole.ANNOTATION;
- return leaf;
- }
- if (type === MMLTAGS.MS) {
- leaf.role = SemanticRole.STRING;
- return leaf;
- }
- if (type === MMLTAGS.MSPACE || leaf.textContent.match(/^\s*$/)) {
- leaf.role = SemanticRole.SPACE;
- return leaf;
- }
- if (/\s/.exec(leaf.textContent)) {
- leaf.role = SemanticRole.TEXT;
- return leaf;
- }
- leaf.role = SemanticRole.UNKNOWN;
- return leaf;
- }
- row(nodes) {
- nodes = nodes.filter(function (x) {
- return !SemanticPred.isType(x, SemanticType.EMPTY);
- });
- if (nodes.length === 0) {
- return SemanticProcessor.getInstance().factory_.makeEmptyNode();
- }
- nodes = SemanticProcessor.getInstance().getFencesInRow_(nodes);
- nodes = SemanticProcessor.getInstance().tablesInRow(nodes);
- nodes = SemanticProcessor.getInstance().getPunctuationInRow_(nodes);
- nodes = SemanticProcessor.getInstance().getTextInRow_(nodes);
- nodes = SemanticProcessor.getInstance().getFunctionsInRow_(nodes);
- return SemanticProcessor.getInstance().relationsInRow_(nodes);
- }
- limitNode(mmlTag, children) {
- if (!children.length) {
- return SemanticProcessor.getInstance().factory_.makeEmptyNode();
- }
- let center = children[0];
- let type = SemanticType.UNKNOWN;
- if (!children[1]) {
- return center;
- }
- let result;
- SemanticHeuristics.run('op_with_limits', children);
- if (SemanticPred.isLimitBase(center)) {
- result = SemanticProcessor.MML_TO_LIMIT_[mmlTag];
- const length = result.length;
- type = result.type;
- children = children.slice(0, result.length + 1);
- if ((length === 1 && SemanticPred.isAccent(children[1])) ||
- (length === 2 &&
- SemanticPred.isAccent(children[1]) &&
- SemanticPred.isAccent(children[2]))) {
- result = SemanticProcessor.MML_TO_BOUNDS_[mmlTag];
- return SemanticProcessor.getInstance().accentNode_(center, children, result.type, result.length, result.accent);
- }
- if (length === 2) {
- if (SemanticPred.isAccent(children[1])) {
- center = SemanticProcessor.getInstance().accentNode_(center, [center, children[1]], {
- MSUBSUP: SemanticType.SUBSCRIPT,
- MUNDEROVER: SemanticType.UNDERSCORE
- }[mmlTag], 1, true);
- return !children[2]
- ? center
- : SemanticProcessor.getInstance().makeLimitNode_(center, [center, children[2]], null, SemanticType.LIMUPPER);
- }
- if (children[2] && SemanticPred.isAccent(children[2])) {
- center = SemanticProcessor.getInstance().accentNode_(center, [center, children[2]], {
- MSUBSUP: SemanticType.SUPERSCRIPT,
- MUNDEROVER: SemanticType.OVERSCORE
- }[mmlTag], 1, true);
- return SemanticProcessor.getInstance().makeLimitNode_(center, [center, children[1]], null, SemanticType.LIMLOWER);
- }
- if (!children[length]) {
- type = SemanticType.LIMLOWER;
- }
- }
- return SemanticProcessor.getInstance().makeLimitNode_(center, children, null, type);
- }
- result = SemanticProcessor.MML_TO_BOUNDS_[mmlTag];
- return SemanticProcessor.getInstance().accentNode_(center, children, result.type, result.length, result.accent);
- }
- tablesInRow(nodes) {
- let partition = SemanticUtil.partitionNodes(nodes, SemanticPred.tableIsMatrixOrVector);
- let result = [];
- for (let i = 0, matrix; (matrix = partition.rel[i]); i++) {
- result = result.concat(partition.comp.shift());
- result.push(SemanticProcessor.tableToMatrixOrVector_(matrix));
- }
- result = result.concat(partition.comp.shift());
- partition = SemanticUtil.partitionNodes(result, SemanticPred.isTableOrMultiline);
- result = [];
- for (let i = 0, table; (table = partition.rel[i]); i++) {
- const prevNodes = partition.comp.shift();
- if (SemanticPred.tableIsCases(table, prevNodes)) {
- SemanticProcessor.tableToCases_(table, prevNodes.pop());
- }
- result = result.concat(prevNodes);
- result.push(table);
- }
- return result.concat(partition.comp.shift());
- }
- mfenced(open, close, sepValue, children) {
- if (sepValue && children.length > 0) {
- const separators = SemanticProcessor.nextSeparatorFunction_(sepValue);
- const newChildren = [children.shift()];
- children.forEach((child) => {
- newChildren.push(SemanticProcessor.getInstance().factory_.makeContentNode(separators()));
- newChildren.push(child);
- });
- children = newChildren;
- }
- if (open && close) {
- return SemanticProcessor.getInstance().horizontalFencedNode_(SemanticProcessor.getInstance().factory_.makeContentNode(open), SemanticProcessor.getInstance().factory_.makeContentNode(close), children);
- }
- if (open) {
- children.unshift(SemanticProcessor.getInstance().factory_.makeContentNode(open));
- }
- if (close) {
- children.push(SemanticProcessor.getInstance().factory_.makeContentNode(close));
- }
- return SemanticProcessor.getInstance().row(children);
- }
- fractionLikeNode(denom, enume, linethickness, bevelled) {
- let node;
- if (!bevelled && SemanticUtil.isZeroLength(linethickness)) {
- const child0 = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.LINE, [denom], []);
- const child1 = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.LINE, [enume], []);
- node = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.MULTILINE, [child0, child1], []);
- SemanticProcessor.binomialForm_(node);
- SemanticProcessor.classifyMultiline(node);
- return node;
- }
- else {
- node = SemanticProcessor.getInstance().fractionNode_(denom, enume);
- if (bevelled) {
- node.addAnnotation('general', 'bevelled');
- }
- return node;
- }
- }
- tensor(base, lsub, lsup, rsub, rsup) {
- const newNode = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.TENSOR, [
- base,
- SemanticProcessor.getInstance().scriptNode_(lsub, SemanticRole.LEFTSUB),
- SemanticProcessor.getInstance().scriptNode_(lsup, SemanticRole.LEFTSUPER),
- SemanticProcessor.getInstance().scriptNode_(rsub, SemanticRole.RIGHTSUB),
- SemanticProcessor.getInstance().scriptNode_(rsup, SemanticRole.RIGHTSUPER)
- ], []);
- newNode.role = base.role;
- newNode.embellished = SemanticPred.isEmbellished(base);
- return newNode;
- }
- pseudoTensor(base, sub, sup) {
- const isEmpty = (x) => !SemanticPred.isType(x, SemanticType.EMPTY);
- const nonEmptySub = sub.filter(isEmpty).length;
- const nonEmptySup = sup.filter(isEmpty).length;
- if (!nonEmptySub && !nonEmptySup) {
- return base;
- }
- const mmlTag = nonEmptySub
- ? nonEmptySup
- ? MMLTAGS.MSUBSUP
- : MMLTAGS.MSUB
- : MMLTAGS.MSUP;
- const mmlchild = [base];
- if (nonEmptySub) {
- mmlchild.push(SemanticProcessor.getInstance().scriptNode_(sub, SemanticRole.RIGHTSUB, true));
- }
- if (nonEmptySup) {
- mmlchild.push(SemanticProcessor.getInstance().scriptNode_(sup, SemanticRole.RIGHTSUPER, true));
- }
- return SemanticProcessor.getInstance().limitNode(mmlTag, mmlchild);
- }
- font(font) {
- const mathjaxFont = SemanticProcessor.MATHJAX_FONTS[font];
- return mathjaxFont ? mathjaxFont : font;
- }
- proof(node, semantics, parse) {
- if (!semantics['inference'] && !semantics['axiom']) {
- console.log('Noise');
- }
- if (semantics['axiom']) {
- const cleaned = SemanticProcessor.getInstance().cleanInference(node.childNodes);
- const axiom = cleaned.length
- ? SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.INFERENCE, parse(cleaned), [])
- : SemanticProcessor.getInstance().factory_.makeEmptyNode();
- axiom.role = SemanticRole.AXIOM;
- axiom.mathmlTree = node;
- return axiom;
- }
- const inference = SemanticProcessor.getInstance().inference(node, semantics, parse);
- if (semantics['proof']) {
- inference.role = SemanticRole.PROOF;
- inference.childNodes[0].role = SemanticRole.FINAL;
- }
- return inference;
- }
- inference(node, semantics, parse) {
- if (semantics['inferenceRule']) {
- const formulas = SemanticProcessor.getInstance().getFormulas(node, [], parse);
- const inference = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.INFERENCE, [formulas.conclusion, formulas.premises], []);
- return inference;
- }
- const label = semantics['labelledRule'];
- const children = DomUtil.toArray(node.childNodes);
- const content = [];
- if (label === 'left' || label === 'both') {
- content.push(SemanticProcessor.getInstance().getLabel(node, children, parse, SemanticRole.LEFT));
- }
- if (label === 'right' || label === 'both') {
- content.push(SemanticProcessor.getInstance().getLabel(node, children, parse, SemanticRole.RIGHT));
- }
- const formulas = SemanticProcessor.getInstance().getFormulas(node, children, parse);
- const inference = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.INFERENCE, [formulas.conclusion, formulas.premises], content);
- inference.mathmlTree = node;
- return inference;
- }
- getLabel(_node, children, parse, side) {
- const label = SemanticProcessor.getInstance().findNestedRow(children, 'prooflabel', side);
- const sem = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.RULELABEL, parse(DomUtil.toArray(label.childNodes)), []);
- sem.role = side;
- sem.mathmlTree = label;
- return sem;
- }
- getFormulas(node, children, parse) {
- const inf = children.length
- ? SemanticProcessor.getInstance().findNestedRow(children, 'inferenceRule')
- : node;
- const up = SemanticProcessor.getSemantics(inf)['inferenceRule'] === 'up';
- const premRow = up ? inf.childNodes[1] : inf.childNodes[0];
- const concRow = up ? inf.childNodes[0] : inf.childNodes[1];
- const premTable = premRow.childNodes[0].childNodes[0];
- const topRow = DomUtil.toArray(premTable.childNodes[0].childNodes);
- const premNodes = [];
- let i = 1;
- for (const cell of topRow) {
- if (i % 2) {
- premNodes.push(cell.childNodes[0]);
- }
- i++;
- }
- const premises = parse(premNodes);
- const conclusion = parse(DomUtil.toArray(concRow.childNodes[0].childNodes))[0];
- const prem = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.PREMISES, premises, []);
- prem.mathmlTree = premTable;
- const conc = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.CONCLUSION, [conclusion], []);
- conc.mathmlTree = concRow.childNodes[0].childNodes[0];
- return { conclusion: conc, premises: prem };
- }
- findNestedRow(nodes, semantic, opt_value) {
- return SemanticProcessor.getInstance().findNestedRow_(nodes, semantic, 0, opt_value);
- }
- cleanInference(nodes) {
- return DomUtil.toArray(nodes).filter(function (x) {
- return DomUtil.tagName(x) !== 'MSPACE';
- });
- }
- operatorNode(node) {
- if (node.type === SemanticType.UNKNOWN) {
- node.type = SemanticType.OPERATOR;
- }
- return SemanticHeuristics.run('multioperator', node);
- }
- constructor() {
- this.funcAppls = {};
- this.splitRoles = new Map([
- [SemanticRole.SUBTRACTION, SemanticRole.NEGATIVE],
- [SemanticRole.ADDITION, SemanticRole.POSITIVE]
- ]);
- this.splitOps = ['−', '-', '‐', '‑', '+'];
- this.factory_ = new SemanticNodeFactory();
- SemanticHeuristics.updateFactory(this.factory_);
- }
- implicitNode_(nodes) {
- const operators = SemanticProcessor.getInstance().factory_.makeMultipleContentNodes(nodes.length - 1, NamedSymbol.invisibleTimes);
- SemanticProcessor.matchSpaces_(nodes, operators);
- const newNode = SemanticProcessor.getInstance().infixNode_(nodes, operators[0]);
- newNode.role = SemanticRole.IMPLICIT;
- operators.forEach(function (op) {
- op.parent = newNode;
- });
- newNode.contentNodes = operators;
- return newNode;
- }
- infixNode_(children, opNode) {
- const node = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.INFIXOP, children, [opNode], SemanticUtil.getEmbellishedInner(opNode).textContent);
- node.role = opNode.role;
- return SemanticHeuristics.run('propagateSimpleFunction', node);
- }
- explicitMixed_(nodes) {
- const partition = SemanticUtil.partitionNodes(nodes, function (x) {
- return x.textContent === NamedSymbol.invisiblePlus;
- });
- if (!partition.rel.length) {
- return nodes;
- }
- let result = [];
- for (let i = 0, rel; (rel = partition.rel[i]); i++) {
- const prev = partition.comp[i];
- const next = partition.comp[i + 1];
- const last = prev.length - 1;
- if (prev[last] &&
- next[0] &&
- SemanticPred.isType(prev[last], SemanticType.NUMBER) &&
- !SemanticPred.isRole(prev[last], SemanticRole.MIXED) &&
- SemanticPred.isType(next[0], SemanticType.FRACTION)) {
- const newNode = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.NUMBER, [prev[last], next[0]], []);
- newNode.role = SemanticRole.MIXED;
- result = result.concat(prev.slice(0, last));
- result.push(newNode);
- next.shift();
- }
- else {
- result = result.concat(prev);
- result.push(rel);
- }
- }
- return result.concat(partition.comp[partition.comp.length - 1]);
- }
- concatNode_(inner, nodeList, type) {
- if (nodeList.length === 0) {
- return inner;
- }
- const content = nodeList
- .map(function (x) {
- return SemanticUtil.getEmbellishedInner(x).textContent;
- })
- .join(' ');
- const newNode = SemanticProcessor.getInstance().factory_.makeBranchNode(type, [inner], nodeList, content);
- if (nodeList.length > 1) {
- newNode.role = SemanticRole.MULTIOP;
- }
- return newNode;
- }
- prefixNode_(node, prefixes) {
- const newPrefixes = this.splitSingles(prefixes);
- let newNode = node;
- while (newPrefixes.length > 0) {
- const op = newPrefixes.pop();
- newNode = SemanticProcessor.getInstance().concatNode_(newNode, op, SemanticType.PREFIXOP);
- if (op.length === 1 && this.splitOps.indexOf(op[0].textContent) !== -1) {
- newNode.role = this.splitRoles.get(op[0].role);
- }
- }
- return newNode;
- }
- splitSingles(prefixes) {
- let lastOp = 0;
- const result = [];
- let i = 0;
- while (i < prefixes.length) {
- const op = prefixes[i];
- if (this.splitRoles.has(op.role) &&
- (!prefixes[i - 1] || prefixes[i - 1].role !== op.role) &&
- (!prefixes[i + 1] || prefixes[i + 1].role !== op.role) &&
- this.splitOps.indexOf(op.textContent) !== -1) {
- result.push(prefixes.slice(lastOp, i));
- result.push(prefixes.slice(i, i + 1));
- lastOp = i + 1;
- }
- i++;
- }
- if (lastOp < i) {
- result.push(prefixes.slice(lastOp, i));
- }
- return result;
- }
- postfixNode_(node, postfixes) {
- if (!postfixes.length) {
- return node;
- }
- return SemanticProcessor.getInstance().concatNode_(node, postfixes, SemanticType.POSTFIXOP);
- }
- combineUnits_(nodes) {
- const partition = SemanticUtil.partitionNodes(nodes, function (x) {
- return !SemanticPred.isRole(x, SemanticRole.UNIT);
- });
- if (nodes.length === partition.rel.length) {
- return partition.rel;
- }
- const result = [];
- let rel;
- let last;
- do {
- const comp = partition.comp.shift();
- rel = partition.rel.shift();
- let unitNode = null;
- last = result.pop();
- if (last) {
- if (!comp.length || !SemanticPred.isUnitCounter(last)) {
- result.push(last);
- }
- else {
- comp.unshift(last);
- }
- }
- if (comp.length === 1) {
- unitNode = comp.pop();
- }
- if (comp.length > 1) {
- unitNode = SemanticProcessor.getInstance().implicitNode_(comp);
- unitNode.role = SemanticRole.UNIT;
- }
- if (unitNode) {
- result.push(unitNode);
- }
- if (rel) {
- result.push(rel);
- }
- } while (rel);
- return result;
- }
- getMixedNumbers_(nodes) {
- const partition = SemanticUtil.partitionNodes(nodes, function (x) {
- return (SemanticPred.isType(x, SemanticType.FRACTION) &&
- SemanticPred.isRole(x, SemanticRole.VULGAR));
- });
- if (!partition.rel.length) {
- return nodes;
- }
- let result = [];
- for (let i = 0, rel; (rel = partition.rel[i]); i++) {
- const comp = partition.comp[i];
- const last = comp.length - 1;
- if (comp[last] &&
- SemanticPred.isType(comp[last], SemanticType.NUMBER) &&
- (SemanticPred.isRole(comp[last], SemanticRole.INTEGER) ||
- SemanticPred.isRole(comp[last], SemanticRole.FLOAT))) {
- const newNode = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.NUMBER, [comp[last], rel], []);
- newNode.role = SemanticRole.MIXED;
- result = result.concat(comp.slice(0, last));
- result.push(newNode);
- }
- else {
- result = result.concat(comp);
- result.push(rel);
- }
- }
- return result.concat(partition.comp[partition.comp.length - 1]);
- }
- getTextInRow_(nodes) {
- if (nodes.length === 0) {
- return nodes;
- }
- if (nodes.length === 1) {
- if (nodes[0].type === SemanticType.TEXT &&
- nodes[0].role === SemanticRole.UNKNOWN) {
- nodes[0].role = SemanticRole.ANNOTATION;
- }
- return nodes;
- }
- const { rel: rel, comp: comp } = SemanticUtil.partitionNodes(nodes, (x) => SemanticPred.isType(x, SemanticType.TEXT));
- if (rel.length === 0) {
- return nodes;
- }
- const result = [];
- let prevComp = comp.shift();
- while (rel.length > 0) {
- let currentRel = rel.shift();
- let nextComp = comp.shift();
- const text = [];
- while (!nextComp.length &&
- rel.length &&
- currentRel.role !== SemanticRole.SPACE &&
- rel[0].role !== SemanticRole.SPACE) {
- text.push(currentRel);
- currentRel = rel.shift();
- nextComp = comp.shift();
- }
- if (text.length) {
- if (prevComp.length) {
- result.push(SemanticProcessor.getInstance().row(prevComp));
- }
- text.push(currentRel);
- const dummy = SemanticProcessor.getInstance().dummyNode_(text);
- result.push(dummy);
- prevComp = nextComp;
- continue;
- }
- if (currentRel.role !== SemanticRole.UNKNOWN) {
- if (prevComp.length) {
- result.push(SemanticProcessor.getInstance().row(prevComp));
- }
- result.push(currentRel);
- prevComp = nextComp;
- continue;
- }
- const meaning = SemanticMap.Meaning.get(currentRel.textContent);
- if (meaning.type === SemanticType.PUNCTUATION) {
- currentRel.role = meaning.role;
- currentRel.font = meaning.font;
- if (prevComp.length) {
- result.push(SemanticProcessor.getInstance().row(prevComp));
- }
- result.push(currentRel);
- prevComp = nextComp;
- continue;
- }
- if (meaning.type !== SemanticType.UNKNOWN) {
- currentRel.type = meaning.type;
- currentRel.role = meaning.role;
- currentRel.font = meaning.font;
- currentRel.addAnnotation('general', 'text');
- prevComp.push(currentRel);
- prevComp = prevComp.concat(nextComp);
- continue;
- }
- SemanticProcessor.meaningFromContent(currentRel, (n, c, m) => {
- if (n.role !== SemanticRole.UNKNOWN) {
- return;
- }
- SemanticProcessor.numberRole_(n, c, m);
- if (n.role !== SemanticRole.OTHERNUMBER) {
- n.type = SemanticType.NUMBER;
- return;
- }
- if (m.some((x) => x.type !== SemanticType.NUMBER &&
- x.type !== SemanticType.IDENTIFIER)) {
- n.type = SemanticType.TEXT;
- n.role = SemanticRole.ANNOTATION;
- return;
- }
- n.role = SemanticRole.UNKNOWN;
- });
- if (currentRel.type === SemanticType.TEXT &&
- currentRel.role !== SemanticRole.UNKNOWN) {
- if (prevComp.length) {
- result.push(SemanticProcessor.getInstance().row(prevComp));
- }
- result.push(currentRel);
- prevComp = nextComp;
- continue;
- }
- if (currentRel.role === SemanticRole.UNKNOWN) {
- if (rel.length || nextComp.length) {
- if (nextComp.length && nextComp[0].type === SemanticType.FENCED) {
- currentRel.type = SemanticType.FUNCTION;
- currentRel.role = SemanticRole.PREFIXFUNC;
- }
- else {
- currentRel.role = SemanticRole.TEXT;
- }
- }
- else {
- currentRel.type = SemanticType.IDENTIFIER;
- currentRel.role = SemanticRole.UNIT;
- }
- }
- prevComp.push(currentRel);
- prevComp = prevComp.concat(nextComp);
- }
- if (prevComp.length > 0) {
- result.push(SemanticProcessor.getInstance().row(prevComp));
- }
- return result.length > 1
- ? [SemanticProcessor.getInstance().dummyNode_(result)]
- : result;
- }
- relationsInRow_(nodes) {
- const partition = SemanticUtil.partitionNodes(nodes, SemanticPred.isRelation);
- const firstRel = partition.rel[0];
- if (!firstRel) {
- return SemanticProcessor.getInstance().operationsInRow_(nodes);
- }
- if (nodes.length === 1) {
- return nodes[0];
- }
- const children = partition.comp.map(SemanticProcessor.getInstance().operationsInRow_);
- let node;
- if (partition.rel.some(function (x) {
- return !x.equals(firstRel);
- })) {
- node = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.MULTIREL, children, partition.rel);
- if (partition.rel.every(function (x) {
- return x.role === firstRel.role;
- })) {
- node.role = firstRel.role;
- }
- return node;
- }
- node = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.RELSEQ, children, partition.rel, SemanticUtil.getEmbellishedInner(firstRel).textContent);
- node.role = firstRel.role;
- return node;
- }
- operationsInRow_(nodes) {
- if (nodes.length === 0) {
- return SemanticProcessor.getInstance().factory_.makeEmptyNode();
- }
- nodes = SemanticProcessor.getInstance().explicitMixed_(nodes);
- if (nodes.length === 1) {
- return nodes[0];
- }
- const prefix = [];
- while (nodes.length > 0 && SemanticPred.isOperator(nodes[0])) {
- prefix.push(nodes.shift());
- }
- if (nodes.length === 0) {
- return SemanticProcessor.getInstance().prefixNode_(prefix.pop(), prefix);
- }
- if (nodes.length === 1) {
- return SemanticProcessor.getInstance().prefixNode_(nodes[0], prefix);
- }
- nodes = SemanticHeuristics.run('convert_juxtaposition', nodes);
- const split = SemanticUtil.sliceNodes(nodes, SemanticPred.isOperator);
- const node = SemanticProcessor.getInstance().wrapFactor(prefix, split);
- return SemanticProcessor.getInstance().addFactor(node, split);
- }
- wrapPostfix(split) {
- var _a;
- if (((_a = split.div) === null || _a === void 0 ? void 0 : _a.role) === SemanticRole.POSTFIXOP) {
- if (!split.tail.length || split.tail[0].type === SemanticType.OPERATOR) {
- split.head = [
- SemanticProcessor.getInstance().postfixNode_(SemanticProcessor.getInstance().implicitNode(split.head), [split.div])
- ];
- split.div = split.tail.shift();
- SemanticProcessor.getInstance().wrapPostfix(split);
- }
- else {
- split.div.role = SemanticRole.DIVISION;
- }
- }
- }
- wrapFactor(prefix, split) {
- SemanticProcessor.getInstance().wrapPostfix(split);
- return SemanticProcessor.getInstance().prefixNode_(SemanticProcessor.getInstance().implicitNode(split.head), prefix);
- }
- addFactor(node, split) {
- if (!split.div) {
- if (SemanticPred.isUnitProduct(node)) {
- node.role = SemanticRole.UNIT;
- }
- return node;
- }
- return SemanticProcessor.getInstance().operationsTree_(split.tail, node, split.div);
- }
- operationsTree_(nodes, root, lastop, prefix = []) {
- if (nodes.length === 0) {
- prefix.unshift(lastop);
- if (root.type === SemanticType.INFIXOP) {
- const node = SemanticProcessor.getInstance().postfixNode_(root.childNodes.pop(), prefix);
- root.appendChild(node);
- return root;
- }
- return SemanticProcessor.getInstance().postfixNode_(root, prefix);
- }
- const split = SemanticUtil.sliceNodes(nodes, SemanticPred.isOperator);
- if (split.head.length === 0) {
- prefix.push(split.div);
- return SemanticProcessor.getInstance().operationsTree_(split.tail, root, lastop, prefix);
- }
- const node = SemanticProcessor.getInstance().wrapFactor(prefix, split);
- const newNode = SemanticProcessor.getInstance().appendOperand_(root, lastop, node);
- return SemanticProcessor.getInstance().addFactor(newNode, split);
- }
- appendOperand_(root, op, node) {
- if (root.type !== SemanticType.INFIXOP) {
- return SemanticProcessor.getInstance().infixNode_([root, node], op);
- }
- const division = SemanticProcessor.getInstance().appendDivisionOp_(root, op, node);
- if (division) {
- return division;
- }
- if (SemanticProcessor.getInstance().appendExistingOperator_(root, op, node)) {
- return root;
- }
- return op.role === SemanticRole.MULTIPLICATION
- ? SemanticProcessor.getInstance().appendMultiplicativeOp_(root, op, node)
- : SemanticProcessor.getInstance().appendAdditiveOp_(root, op, node);
- }
- appendDivisionOp_(root, op, node) {
- if (op.role === SemanticRole.DIVISION) {
- if (SemanticPred.isImplicit(root)) {
- return SemanticProcessor.getInstance().infixNode_([root, node], op);
- }
- return SemanticProcessor.getInstance().appendLastOperand_(root, op, node);
- }
- return root.role === SemanticRole.DIVISION
- ? SemanticProcessor.getInstance().infixNode_([root, node], op)
- : null;
- }
- appendLastOperand_(root, op, node) {
- let lastRoot = root;
- let lastChild = root.childNodes[root.childNodes.length - 1];
- while (lastChild &&
- lastChild.type === SemanticType.INFIXOP &&
- !SemanticPred.isImplicit(lastChild)) {
- lastRoot = lastChild;
- lastChild = lastRoot.childNodes[root.childNodes.length - 1];
- }
- const newNode = SemanticProcessor.getInstance().infixNode_([lastRoot.childNodes.pop(), node], op);
- lastRoot.appendChild(newNode);
- return root;
- }
- appendMultiplicativeOp_(root, op, node) {
- if (SemanticPred.isImplicit(root)) {
- return SemanticProcessor.getInstance().infixNode_([root, node], op);
- }
- let lastRoot = root;
- let lastChild = root.childNodes[root.childNodes.length - 1];
- while (lastChild &&
- lastChild.type === SemanticType.INFIXOP &&
- !SemanticPred.isImplicit(lastChild)) {
- lastRoot = lastChild;
- lastChild = lastRoot.childNodes[root.childNodes.length - 1];
- }
- const newNode = SemanticProcessor.getInstance().infixNode_([lastRoot.childNodes.pop(), node], op);
- lastRoot.appendChild(newNode);
- return root;
- }
- appendAdditiveOp_(root, op, node) {
- return SemanticProcessor.getInstance().infixNode_([root, node], op);
- }
- appendExistingOperator_(root, op, node) {
- if (!root ||
- root.type !== SemanticType.INFIXOP ||
- SemanticPred.isImplicit(root)) {
- return false;
- }
- if (root.contentNodes[0].equals(op)) {
- root.appendContentNode(op);
- root.appendChild(node);
- return true;
- }
- return SemanticProcessor.getInstance().appendExistingOperator_(root.childNodes[root.childNodes.length - 1], op, node);
- }
- getFencesInRow_(nodes) {
- let partition = SemanticUtil.partitionNodes(nodes, SemanticPred.isFence);
- partition = SemanticProcessor.purgeFences_(partition);
- const felem = partition.comp.shift();
- return SemanticProcessor.getInstance().fences_(partition.rel, partition.comp, [], [felem]);
- }
- fences_(fences, content, openStack, contentStack) {
- if (fences.length === 0 && openStack.length === 0) {
- return contentStack[0];
- }
- const interval = SemanticHeuristics.run('bracketed_interval', [fences[0], fences[1], ...(content[0] || [])], () => null);
- if (interval) {
- fences.shift();
- fences.shift();
- content.shift();
- const stack = contentStack.pop() || [];
- contentStack.push([...stack, interval, ...content.shift()]);
- return SemanticProcessor.getInstance().fences_(fences, content, openStack, contentStack);
- }
- const openPred = (x) => SemanticPred.isRole(x, SemanticRole.OPEN);
- if (fences.length === 0) {
- const result = contentStack.shift();
- while (openStack.length > 0) {
- if (openPred(openStack[0])) {
- const firstOpen = openStack.shift();
- SemanticProcessor.fenceToPunct_(firstOpen);
- result.push(firstOpen);
- }
- else {
- const split = SemanticUtil.sliceNodes(openStack, openPred);
- const cutLength = split.head.length - 1;
- const innerNodes = SemanticProcessor.getInstance().neutralFences_(split.head, contentStack.slice(0, cutLength));
- contentStack = contentStack.slice(cutLength);
- result.push(...innerNodes);
- if (split.div) {
- split.tail.unshift(split.div);
- }
- openStack = split.tail;
- }
- result.push(...contentStack.shift());
- }
- return result;
- }
- const lastOpen = openStack[openStack.length - 1];
- const firstRole = fences[0].role;
- if (firstRole === SemanticRole.OPEN ||
- (SemanticPred.isNeutralFence(fences[0]) &&
- !(lastOpen && SemanticPred.compareNeutralFences(fences[0], lastOpen)))) {
- openStack.push(fences.shift());
- const cont = content.shift();
- if (cont) {
- contentStack.push(cont);
- }
- return SemanticProcessor.getInstance().fences_(fences, content, openStack, contentStack);
- }
- if (lastOpen &&
- firstRole === SemanticRole.CLOSE &&
- lastOpen.role === SemanticRole.OPEN) {
- const fenced = SemanticProcessor.getInstance().horizontalFencedNode_(openStack.pop(), fences.shift(), contentStack.pop());
- contentStack.push(contentStack.pop().concat([fenced], content.shift()));
- return SemanticProcessor.getInstance().fences_(fences, content, openStack, contentStack);
- }
- if (lastOpen &&
- SemanticPred.compareNeutralFences(fences[0], lastOpen)) {
- if (!SemanticPred.elligibleLeftNeutral(lastOpen) ||
- !SemanticPred.elligibleRightNeutral(fences[0])) {
- openStack.push(fences.shift());
- const cont = content.shift();
- if (cont) {
- contentStack.push(cont);
- }
- return SemanticProcessor.getInstance().fences_(fences, content, openStack, contentStack);
- }
- const fenced = SemanticProcessor.getInstance().horizontalFencedNode_(openStack.pop(), fences.shift(), contentStack.pop());
- contentStack.push(contentStack.pop().concat([fenced], content.shift()));
- return SemanticProcessor.getInstance().fences_(fences, content, openStack, contentStack);
- }
- if (lastOpen &&
- firstRole === SemanticRole.CLOSE &&
- SemanticPred.isNeutralFence(lastOpen) &&
- openStack.some(openPred)) {
- const split = SemanticUtil.sliceNodes(openStack, openPred, true);
- const rightContent = contentStack.pop();
- const cutLength = contentStack.length - split.tail.length + 1;
- const innerNodes = SemanticProcessor.getInstance().neutralFences_(split.tail, contentStack.slice(cutLength));
- contentStack = contentStack.slice(0, cutLength);
- const fenced = SemanticProcessor.getInstance().horizontalFencedNode_(split.div, fences.shift(), contentStack.pop().concat(innerNodes, rightContent));
- contentStack.push(contentStack.pop().concat([fenced], content.shift()));
- return SemanticProcessor.getInstance().fences_(fences, content, split.head, contentStack);
- }
- const fenced = fences.shift();
- SemanticProcessor.fenceToPunct_(fenced);
- contentStack.push(contentStack.pop().concat([fenced], content.shift()));
- return SemanticProcessor.getInstance().fences_(fences, content, openStack, contentStack);
- }
- neutralFences_(fences, content) {
- if (fences.length === 0) {
- return fences;
- }
- if (fences.length === 1) {
- SemanticProcessor.fenceToPunct_(fences[0]);
- return fences;
- }
- const firstFence = fences.shift();
- if (!SemanticPred.elligibleLeftNeutral(firstFence)) {
- SemanticProcessor.fenceToPunct_(firstFence);
- const restContent = content.shift();
- restContent.unshift(firstFence);
- return restContent.concat(SemanticProcessor.getInstance().neutralFences_(fences, content));
- }
- const split = SemanticUtil.sliceNodes(fences, function (x) {
- return SemanticPred.compareNeutralFences(x, firstFence);
- });
- if (!split.div) {
- SemanticProcessor.fenceToPunct_(firstFence);
- const restContent = content.shift();
- restContent.unshift(firstFence);
- return restContent.concat(SemanticProcessor.getInstance().neutralFences_(fences, content));
- }
- if (!SemanticPred.elligibleRightNeutral(split.div)) {
- SemanticProcessor.fenceToPunct_(split.div);
- fences.unshift(firstFence);
- return SemanticProcessor.getInstance().neutralFences_(fences, content);
- }
- const newContent = SemanticProcessor.getInstance().combineFencedContent_(firstFence, split.div, split.head, content);
- if (split.tail.length > 0) {
- const leftContent = newContent.shift();
- const result = SemanticProcessor.getInstance().neutralFences_(split.tail, newContent);
- return leftContent.concat(result);
- }
- return newContent[0];
- }
- combineFencedContent_(leftFence, rightFence, midFences, content) {
- if (midFences.length === 0) {
- const fenced = SemanticProcessor.getInstance().horizontalFencedNode_(leftFence, rightFence, content.shift());
- if (content.length > 0) {
- content[0].unshift(fenced);
- }
- else {
- content = [[fenced]];
- }
- return content;
- }
- const leftContent = content.shift();
- const cutLength = midFences.length - 1;
- const midContent = content.slice(0, cutLength);
- content = content.slice(cutLength);
- const rightContent = content.shift();
- const innerNodes = SemanticProcessor.getInstance().neutralFences_(midFences, midContent);
- leftContent.push(...innerNodes);
- leftContent.push(...rightContent);
- const fenced = SemanticProcessor.getInstance().horizontalFencedNode_(leftFence, rightFence, leftContent);
- if (content.length > 0) {
- content[0].unshift(fenced);
- }
- else {
- content = [[fenced]];
- }
- return content;
- }
- horizontalFencedNode_(ofence, cfence, content) {
- const childNode = SemanticProcessor.getInstance().row(content);
- let newNode = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.FENCED, [childNode], [ofence, cfence]);
- if (ofence.role === SemanticRole.OPEN) {
- SemanticProcessor.getInstance().classifyHorizontalFence_(newNode);
- newNode = SemanticHeuristics.run('propagateComposedFunction', newNode);
- }
- else {
- newNode.role = ofence.role;
- }
- newNode = SemanticHeuristics.run('detect_cycle', newNode);
- return SemanticProcessor.rewriteFencedNode_(newNode);
- }
- classifyHorizontalFence_(node) {
- node.role = SemanticRole.LEFTRIGHT;
- const children = node.childNodes;
- if (!SemanticPred.isSetNode(node) || children.length > 1) {
- return;
- }
- if (children.length === 0 || children[0].type === SemanticType.EMPTY) {
- node.role = SemanticRole.SETEMPTY;
- return;
- }
- const type = children[0].type;
- if (children.length === 1 &&
- SemanticPred.isSingletonSetContent(children[0])) {
- node.role = SemanticRole.SETSINGLE;
- return;
- }
- const role = children[0].role;
- if (type !== SemanticType.PUNCTUATED || role !== SemanticRole.SEQUENCE) {
- return;
- }
- if (children[0].contentNodes[0].role === SemanticRole.COMMA) {
- node.role = SemanticRole.SETCOLLECT;
- return;
- }
- if (children[0].contentNodes.length === 1 &&
- (children[0].contentNodes[0].role === SemanticRole.VBAR ||
- children[0].contentNodes[0].role === SemanticRole.COLON)) {
- node.role = SemanticRole.SETEXT;
- SemanticProcessor.getInstance().setExtension_(node);
- return;
- }
- }
- setExtension_(set) {
- const extender = set.childNodes[0].childNodes[0];
- if (extender &&
- extender.type === SemanticType.INFIXOP &&
- extender.contentNodes.length === 1 &&
- SemanticPred.isMembership(extender.contentNodes[0])) {
- extender.addAnnotation('set', 'intensional');
- extender.contentNodes[0].addAnnotation('set', 'intensional');
- }
- }
- getPunctuationInRow_(nodes) {
- if (nodes.length <= 1) {
- return nodes;
- }
- const allowedType = (x) => {
- const type = x.type;
- return (type === 'punctuation' ||
- type === 'text' ||
- type === 'operator' ||
- type === 'relation');
- };
- const partition = SemanticUtil.partitionNodes(nodes, function (x) {
- if (!SemanticPred.isPunctuation(x)) {
- return false;
- }
- if (SemanticPred.isPunctuation(x) &&
- !SemanticPred.isRole(x, SemanticRole.ELLIPSIS)) {
- return true;
- }
- const index = nodes.indexOf(x);
- if (index === 0) {
- if (nodes[1] && allowedType(nodes[1])) {
- return false;
- }
- return true;
- }
- const prev = nodes[index - 1];
- if (index === nodes.length - 1) {
- if (allowedType(prev)) {
- return false;
- }
- return true;
- }
- const next = nodes[index + 1];
- if (allowedType(prev) && allowedType(next)) {
- return false;
- }
- return true;
- });
- if (partition.rel.length === 0) {
- return nodes;
- }
- let newNodes = [];
- let firstComp = partition.comp.shift();
- if (firstComp.length > 0) {
- newNodes.push(SemanticProcessor.getInstance().row(firstComp));
- }
- let relCounter = 0;
- while (partition.comp.length > 0) {
- let puncts = [];
- const saveCount = relCounter;
- do {
- puncts.push(partition.rel[relCounter++]);
- firstComp = partition.comp.shift();
- } while (partition.rel[relCounter] &&
- firstComp &&
- firstComp.length === 0);
- puncts = SemanticHeuristics.run('ellipses', puncts);
- partition.rel.splice(saveCount, relCounter - saveCount, ...puncts);
- relCounter = saveCount + puncts.length;
- newNodes = newNodes.concat(puncts);
- if (firstComp && firstComp.length > 0) {
- newNodes.push(SemanticProcessor.getInstance().row(firstComp));
- }
- }
- return newNodes.length === 1 && partition.rel.length === 1
- ? newNodes
- : [
- SemanticProcessor.getInstance().punctuatedNode_(newNodes, partition.rel)
- ];
- }
- punctuatedNode_(nodes, punctuations) {
- const newNode = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.PUNCTUATED, nodes, punctuations);
- if (punctuations.length === nodes.length) {
- const firstRole = punctuations[0].role;
- if (firstRole !== SemanticRole.UNKNOWN &&
- punctuations.every(function (punct) {
- return punct.role === firstRole;
- })) {
- newNode.role = firstRole;
- return newNode;
- }
- }
- const fpunct = punctuations[0];
- if (SemanticPred.singlePunctAtPosition(nodes, punctuations, 0)) {
- newNode.role =
- fpunct.childNodes.length && !fpunct.embellished
- ? fpunct.role
- : SemanticRole.STARTPUNCT;
- }
- else if (SemanticPred.singlePunctAtPosition(nodes, punctuations, nodes.length - 1)) {
- newNode.role =
- fpunct.childNodes.length && !fpunct.embellished
- ? fpunct.role
- : SemanticRole.ENDPUNCT;
- }
- else if (punctuations.every((x) => SemanticPred.isRole(x, SemanticRole.DUMMY))) {
- newNode.role = SemanticRole.TEXT;
- }
- else if (punctuations.every((x) => SemanticPred.isRole(x, SemanticRole.SPACE))) {
- newNode.role = SemanticRole.SPACE;
- }
- else {
- newNode.role = SemanticRole.SEQUENCE;
- }
- return newNode;
- }
- dummyNode_(children) {
- const commata = SemanticProcessor.getInstance().factory_.makeMultipleContentNodes(children.length - 1, NamedSymbol.invisibleComma);
- commata.forEach(function (comma) {
- comma.role = SemanticRole.DUMMY;
- });
- return SemanticProcessor.getInstance().punctuatedNode_(children, commata);
- }
- accentRole_(node, type) {
- if (!SemanticPred.isAccent(node)) {
- return false;
- }
- const content = node.textContent;
- const role = SemanticMap.Secondary.get(content, SemanticSecondary.BAR) ||
- SemanticMap.Secondary.get(content, SemanticSecondary.TILDE) ||
- node.role;
- node.role =
- type === SemanticType.UNDERSCORE
- ? SemanticRole.UNDERACCENT
- : SemanticRole.OVERACCENT;
- node.addAnnotation('accent', role);
- return true;
- }
- accentNode_(center, children, type, length, accent) {
- children = children.slice(0, length + 1);
- const child1 = children[1];
- const child2 = children[2];
- let innerNode;
- if (!accent && child2) {
- innerNode = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.SUBSCRIPT, [center, child1], []);
- innerNode.role = SemanticRole.SUBSUP;
- children = [innerNode, child2];
- type = SemanticType.SUPERSCRIPT;
- }
- if (accent) {
- const underAccent = SemanticProcessor.getInstance().accentRole_(child1, type);
- if (child2) {
- const overAccent = SemanticProcessor.getInstance().accentRole_(child2, SemanticType.OVERSCORE);
- if (overAccent && !underAccent) {
- innerNode = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.OVERSCORE, [center, child2], []);
- children = [innerNode, child1];
- type = SemanticType.UNDERSCORE;
- }
- else {
- innerNode = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.UNDERSCORE, [center, child1], []);
- children = [innerNode, child2];
- type = SemanticType.OVERSCORE;
- }
- innerNode.role = SemanticRole.UNDEROVER;
- }
- }
- return SemanticProcessor.getInstance().makeLimitNode_(center, children, innerNode, type);
- }
- makeLimitNode_(center, children, innerNode, type) {
- if (type === SemanticType.LIMUPPER &&
- center.type === SemanticType.LIMLOWER) {
- center.childNodes.push(children[1]);
- children[1].parent = center;
- center.type = SemanticType.LIMBOTH;
- return center;
- }
- if (type === SemanticType.LIMLOWER &&
- center.type === SemanticType.LIMUPPER) {
- center.childNodes.splice(1, -1, children[1]);
- children[1].parent = center;
- center.type = SemanticType.LIMBOTH;
- return center;
- }
- const newNode = SemanticProcessor.getInstance().factory_.makeBranchNode(type, children, []);
- const embellished = SemanticPred.isEmbellished(center);
- if (innerNode) {
- innerNode.embellished = embellished;
- }
- newNode.embellished = embellished;
- newNode.role = center.role;
- return newNode;
- }
- getFunctionsInRow_(restNodes, opt_result) {
- const result = opt_result || [];
- if (restNodes.length === 0) {
- return result;
- }
- const firstNode = restNodes.shift();
- const heuristic = SemanticProcessor.classifyFunction_(firstNode, restNodes);
- if (!heuristic) {
- result.push(firstNode);
- return SemanticProcessor.getInstance().getFunctionsInRow_(restNodes, result);
- }
- const processedRest = SemanticProcessor.getInstance().getFunctionsInRow_(restNodes, []);
- const newRest = SemanticProcessor.getInstance().getFunctionArgs_(firstNode, processedRest, heuristic);
- return result.concat(newRest);
- }
- getFunctionArgs_(func, rest, heuristic) {
- let partition, arg, funcNode;
- switch (heuristic) {
- case 'integral': {
- const components = SemanticProcessor.getInstance().getIntegralArgs_(rest);
- if (!components.intvar && !components.integrand.length) {
- components.rest.unshift(func);
- return components.rest;
- }
- const integrand = SemanticProcessor.getInstance().row(components.integrand);
- funcNode = SemanticProcessor.getInstance().integralNode_(func, integrand, components.intvar);
- SemanticHeuristics.run('intvar_from_fraction', funcNode);
- components.rest.unshift(funcNode);
- return components.rest;
- }
- case 'prefix': {
- if (rest[0] && rest[0].type === SemanticType.FENCED) {
- const arg = rest.shift();
- if (!SemanticPred.isNeutralFence(arg)) {
- arg.role = SemanticRole.LEFTRIGHT;
- }
- funcNode = SemanticProcessor.getInstance().functionNode_(func, arg);
- rest.unshift(funcNode);
- return rest;
- }
- partition = SemanticUtil.sliceNodes(rest, SemanticPred.isPrefixFunctionBoundary);
- if (!partition.head.length) {
- if (!partition.div ||
- !SemanticPred.isType(partition.div, SemanticType.APPL)) {
- rest.unshift(func);
- return rest;
- }
- arg = partition.div;
- }
- else {
- arg = SemanticProcessor.getInstance().row(partition.head);
- if (partition.div) {
- partition.tail.unshift(partition.div);
- }
- }
- funcNode = SemanticProcessor.getInstance().functionNode_(func, arg);
- partition.tail.unshift(funcNode);
- return partition.tail;
- }
- case 'bigop': {
- partition = SemanticUtil.sliceNodes(rest, SemanticPred.isBigOpBoundary);
- if (!partition.head.length) {
- rest.unshift(func);
- return rest;
- }
- arg = SemanticProcessor.getInstance().row(partition.head);
- funcNode = SemanticProcessor.getInstance().bigOpNode_(func, arg);
- if (partition.div) {
- partition.tail.unshift(partition.div);
- }
- partition.tail.unshift(funcNode);
- return partition.tail;
- }
- case 'simple':
- default: {
- if (rest.length === 0) {
- return [func];
- }
- const firstArg = rest[0];
- if (firstArg.type === SemanticType.FENCED &&
- !SemanticPred.isNeutralFence(firstArg) &&
- SemanticPred.isSimpleFunctionScope(firstArg)) {
- firstArg.role = SemanticRole.LEFTRIGHT;
- SemanticProcessor.propagateFunctionRole_(func, SemanticRole.SIMPLEFUNC);
- funcNode = SemanticProcessor.getInstance().functionNode_(func, rest.shift());
- rest.unshift(funcNode);
- return rest;
- }
- rest.unshift(func);
- return rest;
- }
- }
- }
- getIntegralArgs_(nodes, args = []) {
- if (nodes.length === 0) {
- const partition = SemanticUtil.sliceNodes(args, SemanticPred.isBigOpBoundary);
- if (partition.div) {
- partition.tail.unshift(partition.div);
- }
- return { integrand: partition.head, intvar: null, rest: partition.tail };
- }
- SemanticHeuristics.run('intvar_from_implicit', nodes);
- const firstNode = nodes[0];
- if (SemanticPred.isGeneralFunctionBoundary(firstNode)) {
- const { integrand: args2, rest: rest2 } = SemanticProcessor.getInstance().getIntegralArgs_(args);
- return { integrand: args2, intvar: null, rest: rest2.concat(nodes) };
- }
- if (SemanticPred.isIntegralDxBoundarySingle(firstNode)) {
- firstNode.role = SemanticRole.INTEGRAL;
- return { integrand: args, intvar: firstNode, rest: nodes.slice(1) };
- }
- if (nodes[1] && SemanticPred.isIntegralDxBoundary(firstNode, nodes[1])) {
- const intvar = SemanticProcessor.getInstance().prefixNode_(nodes[1], [firstNode]);
- intvar.role = SemanticRole.INTEGRAL;
- return { integrand: args, intvar: intvar, rest: nodes.slice(2) };
- }
- args.push(nodes.shift());
- return SemanticProcessor.getInstance().getIntegralArgs_(nodes, args);
- }
- functionNode_(func, arg) {
- const applNode = SemanticProcessor.getInstance().factory_.makeContentNode(NamedSymbol.functionApplication);
- const appl = SemanticProcessor.getInstance().funcAppls[func.id];
- if (appl) {
- applNode.mathmlTree = appl.mathmlTree;
- applNode.mathml = appl.mathml;
- applNode.annotation = appl.annotation;
- applNode.attributes = appl.attributes;
- delete SemanticProcessor.getInstance().funcAppls[func.id];
- }
- applNode.type = SemanticType.PUNCTUATION;
- applNode.role = SemanticRole.APPLICATION;
- const funcop = SemanticProcessor.getFunctionOp_(func, function (node) {
- return (SemanticPred.isType(node, SemanticType.FUNCTION) ||
- (SemanticPred.isType(node, SemanticType.IDENTIFIER) &&
- SemanticPred.isRole(node, SemanticRole.SIMPLEFUNC)));
- });
- return SemanticProcessor.getInstance().functionalNode_(SemanticType.APPL, [func, arg], funcop, [applNode]);
- }
- bigOpNode_(bigOp, arg) {
- const largeop = SemanticProcessor.getFunctionOp_(bigOp, (x) => SemanticPred.isType(x, SemanticType.LARGEOP));
- return SemanticProcessor.getInstance().functionalNode_(SemanticType.BIGOP, [bigOp, arg], largeop, []);
- }
- integralNode_(integral, integrand, intvar) {
- integrand =
- integrand || SemanticProcessor.getInstance().factory_.makeEmptyNode();
- intvar = intvar || SemanticProcessor.getInstance().factory_.makeEmptyNode();
- const largeop = SemanticProcessor.getFunctionOp_(integral, (x) => SemanticPred.isType(x, SemanticType.LARGEOP));
- return SemanticProcessor.getInstance().functionalNode_(SemanticType.INTEGRAL, [integral, integrand, intvar], largeop, []);
- }
- functionalNode_(type, children, operator, content) {
- const funcop = children[0];
- let oldParent;
- if (operator) {
- oldParent = operator.parent;
- content.push(operator);
- }
- const newNode = SemanticProcessor.getInstance().factory_.makeBranchNode(type, children, content);
- newNode.role = funcop.role;
- if (oldParent) {
- operator.parent = oldParent;
- }
- return newNode;
- }
- fractionNode_(denom, enume) {
- const newNode = SemanticProcessor.getInstance().factory_.makeBranchNode(SemanticType.FRACTION, [denom, enume], []);
- newNode.role = newNode.childNodes.every(function (x) {
- return (SemanticPred.isType(x, SemanticType.NUMBER) &&
- SemanticPred.isRole(x, SemanticRole.INTEGER));
- })
- ? SemanticRole.VULGAR
- : newNode.childNodes.every(SemanticPred.isPureUnit)
- ? SemanticRole.UNIT
- : SemanticRole.DIVISION;
- return SemanticHeuristics.run('propagateSimpleFunction', newNode);
- }
- scriptNode_(nodes, role, opt_noSingle) {
- let newNode;
- switch (nodes.length) {
- case 0:
- newNode = SemanticProcessor.getInstance().factory_.makeEmptyNode();
- break;
- case 1:
- newNode = nodes[0];
- if (opt_noSingle) {
- return newNode;
- }
- break;
- default:
- newNode = SemanticProcessor.getInstance().dummyNode_(nodes);
- }
- newNode.role = role;
- return newNode;
- }
- findNestedRow_(nodes, semantic, level, value) {
- if (level > 3) {
- return null;
- }
- for (let i = 0, node; (node = nodes[i]); i++) {
- const tag = DomUtil.tagName(node);
- if (tag !== MMLTAGS.MSPACE) {
- if (tag === MMLTAGS.MROW) {
- return SemanticProcessor.getInstance().findNestedRow_(DomUtil.toArray(node.childNodes), semantic, level + 1, value);
- }
- if (SemanticProcessor.findSemantics(node, semantic, value)) {
- return node;
- }
- }
- }
- return null;
- }
- }
- SemanticProcessor.FENCE_TO_PUNCT_ = {
- [SemanticRole.METRIC]: SemanticRole.METRIC,
- [SemanticRole.NEUTRAL]: SemanticRole.VBAR,
- [SemanticRole.OPEN]: SemanticRole.OPENFENCE,
- [SemanticRole.CLOSE]: SemanticRole.CLOSEFENCE
- };
- SemanticProcessor.MML_TO_LIMIT_ = {
- [MMLTAGS.MSUB]: { type: SemanticType.LIMLOWER, length: 1 },
- [MMLTAGS.MUNDER]: { type: SemanticType.LIMLOWER, length: 1 },
- [MMLTAGS.MSUP]: { type: SemanticType.LIMUPPER, length: 1 },
- [MMLTAGS.MOVER]: { type: SemanticType.LIMUPPER, length: 1 },
- [MMLTAGS.MSUBSUP]: { type: SemanticType.LIMBOTH, length: 2 },
- [MMLTAGS.MUNDEROVER]: { type: SemanticType.LIMBOTH, length: 2 }
- };
- SemanticProcessor.MML_TO_BOUNDS_ = {
- [MMLTAGS.MSUB]: { type: SemanticType.SUBSCRIPT, length: 1, accent: false },
- [MMLTAGS.MSUP]: {
- type: SemanticType.SUPERSCRIPT,
- length: 1,
- accent: false
- },
- [MMLTAGS.MSUBSUP]: {
- type: SemanticType.SUBSCRIPT,
- length: 2,
- accent: false
- },
- [MMLTAGS.MUNDER]: {
- type: SemanticType.UNDERSCORE,
- length: 1,
- accent: true
- },
- [MMLTAGS.MOVER]: { type: SemanticType.OVERSCORE, length: 1, accent: true },
- [MMLTAGS.MUNDEROVER]: {
- type: SemanticType.UNDERSCORE,
- length: 2,
- accent: true
- }
- };
- SemanticProcessor.CLASSIFY_FUNCTION_ = {
- [SemanticRole.INTEGRAL]: 'integral',
- [SemanticRole.SUM]: 'bigop',
- [SemanticRole.PREFIXFUNC]: 'prefix',
- [SemanticRole.LIMFUNC]: 'prefix',
- [SemanticRole.SIMPLEFUNC]: 'prefix',
- [SemanticRole.COMPFUNC]: 'prefix'
- };
- SemanticProcessor.MATHJAX_FONTS = {
- '-tex-caligraphic': SemanticFont.CALIGRAPHIC,
- '-tex-caligraphic-bold': SemanticFont.CALIGRAPHICBOLD,
- '-tex-calligraphic': SemanticFont.CALIGRAPHIC,
- '-tex-calligraphic-bold': SemanticFont.CALIGRAPHICBOLD,
- '-tex-oldstyle': SemanticFont.OLDSTYLE,
- '-tex-oldstyle-bold': SemanticFont.OLDSTYLEBOLD,
- '-tex-mathit': SemanticFont.ITALIC
- };
|