Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1005)

Side by Side Diff: chrome/browser/resources/chromeos/chromevox/common/math_semantic_tree.js

Issue 924083004: Shorten Closure template notation from Array.<*> to Array<*> in cvox. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @fileoverview A semantic tree for MathML expressions. 6 * @fileoverview A semantic tree for MathML expressions.
7 * 7 *
8 * This file contains functionality to compute a semantic interpretation from a 8 * This file contains functionality to compute a semantic interpretation from a
9 * given MathML expression. This is a very heuristic approach that assumes a 9 * given MathML expression. This is a very heuristic approach that assumes a
10 * fairly simple default semantic which is suitable for K-12 and simple UG 10 * fairly simple default semantic which is suitable for K-12 and simple UG
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 43
44 44
45 /** 45 /**
46 * @param {number} id Node id. 46 * @param {number} id Node id.
47 * @constructor 47 * @constructor
48 */ 48 */
49 cvox.SemanticTree.Node = function(id) { 49 cvox.SemanticTree.Node = function(id) {
50 /** @type {number} */ 50 /** @type {number} */
51 this.id = id; 51 this.id = id;
52 52
53 /** @type {Array.<Element>} */ 53 /** @type {Array<Element>} */
54 this.mathml = []; 54 this.mathml = [];
55 55
56 /** @type {cvox.SemanticTree.Node} */ 56 /** @type {cvox.SemanticTree.Node} */
57 this.parent = null; 57 this.parent = null;
58 58
59 /** @type {cvox.SemanticAttr.Type} */ 59 /** @type {cvox.SemanticAttr.Type} */
60 this.type = cvox.SemanticAttr.Type.UNKNOWN; 60 this.type = cvox.SemanticAttr.Type.UNKNOWN;
61 61
62 /** @type {cvox.SemanticAttr.Role} */ 62 /** @type {cvox.SemanticAttr.Role} */
63 this.role = cvox.SemanticAttr.Role.UNKNOWN; 63 this.role = cvox.SemanticAttr.Role.UNKNOWN;
64 64
65 /** @type {cvox.SemanticAttr.Font} */ 65 /** @type {cvox.SemanticAttr.Font} */
66 this.font = cvox.SemanticAttr.Font.UNKNOWN; 66 this.font = cvox.SemanticAttr.Font.UNKNOWN;
67 67
68 /** @type {!Array.<cvox.SemanticTree.Node>} */ 68 /** @type {!Array<cvox.SemanticTree.Node>} */
69 this.childNodes = []; 69 this.childNodes = [];
70 70
71 /** @type {string} */ 71 /** @type {string} */
72 this.textContent = ''; 72 this.textContent = '';
73 73
74 /** Branch nodes can store additional nodes that can be useful. 74 /** Branch nodes can store additional nodes that can be useful.
75 * E.g. a node of type FENCED can have the opening and closing fences here. 75 * E.g. a node of type FENCED can have the opening and closing fences here.
76 * @type {!Array.<cvox.SemanticTree.Node>} 76 * @type {!Array<cvox.SemanticTree.Node>}
77 */ 77 */
78 this.contentNodes = []; 78 this.contentNodes = [];
79 }; 79 };
80 80
81 81
82 /** 82 /**
83 * Retrieve all subnodes (including the node itself) that satisfy a given 83 * Retrieve all subnodes (including the node itself) that satisfy a given
84 * predicate. 84 * predicate.
85 * @param {function(cvox.SemanticTree.Node): boolean} pred The predicate. 85 * @param {function(cvox.SemanticTree.Node): boolean} pred The predicate.
86 * @return {!Array.<cvox.SemanticTree.Node>} The nodes in the tree for which the 86 * @return {!Array<cvox.SemanticTree.Node>} The nodes in the tree for which the
87 * predicate holds. 87 * predicate holds.
88 */ 88 */
89 cvox.SemanticTree.Node.prototype.querySelectorAll = function(pred) { 89 cvox.SemanticTree.Node.prototype.querySelectorAll = function(pred) {
90 var result = []; 90 var result = [];
91 for (var i = 0, child; child = this.childNodes[i]; i++) { 91 for (var i = 0, child; child = this.childNodes[i]; i++) {
92 result = result.concat(child.querySelectorAll(pred)); 92 result = result.concat(child.querySelectorAll(pred));
93 } 93 }
94 if (pred(this)) { 94 if (pred(this)) {
95 result.unshift(this); 95 result.unshift(this);
96 } 96 }
(...skipping 20 matching lines...) Expand all
117 /** 117 /**
118 * An XML tree representation of the current node. 118 * An XML tree representation of the current node.
119 * @param {Document} xml The XML document. 119 * @param {Document} xml The XML document.
120 * @param {boolean=} brief If set attributes are omitted. 120 * @param {boolean=} brief If set attributes are omitted.
121 * @return {Node} The XML representation of the node. 121 * @return {Node} The XML representation of the node.
122 */ 122 */
123 cvox.SemanticTree.Node.prototype.xml = function(xml, brief) { 123 cvox.SemanticTree.Node.prototype.xml = function(xml, brief) {
124 /** 124 /**
125 * Translates a list of nodes into XML representation. 125 * Translates a list of nodes into XML representation.
126 * @param {string} tag Name of the enclosing tag. 126 * @param {string} tag Name of the enclosing tag.
127 * @param {!Array.<!cvox.SemanticTree.Node>} nodes A list of nodes. 127 * @param {!Array<!cvox.SemanticTree.Node>} nodes A list of nodes.
128 * @return {Node} An XML representation of the node list. 128 * @return {Node} An XML representation of the node list.
129 */ 129 */
130 var xmlNodeList = function(tag, nodes) { 130 var xmlNodeList = function(tag, nodes) {
131 var xmlNodes = nodes.map(function(x) {return x.xml(xml, brief);}); 131 var xmlNodes = nodes.map(function(x) {return x.xml(xml, brief);});
132 var tagNode = xml.createElement(tag); 132 var tagNode = xml.createElement(tag);
133 for (var i = 0, child; child = xmlNodes[i]; i++) { 133 for (var i = 0, child; child = xmlNodes[i]; i++) {
134 tagNode.appendChild(child); 134 tagNode.appendChild(child);
135 } 135 }
136 return tagNode; 136 return tagNode;
137 }; 137 };
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 this.role = meaning.role; 276 this.role = meaning.role;
277 this.type = meaning.type; 277 this.type = meaning.type;
278 this.font = meaning.font; 278 this.font = meaning.font;
279 }; 279 };
280 280
281 281
282 /** 282 /**
283 * Adds MathML nodes to the node's store of MathML nodes if necessary only, as 283 * Adds MathML nodes to the node's store of MathML nodes if necessary only, as
284 * we can not necessarily assume that the MathML of the content nodes and 284 * we can not necessarily assume that the MathML of the content nodes and
285 * children are all disjoint. 285 * children are all disjoint.
286 * @param {Array.<Node>} mmlNodes List of MathML nodes. 286 * @param {Array<Node>} mmlNodes List of MathML nodes.
287 * @private 287 * @private
288 */ 288 */
289 cvox.SemanticTree.Node.prototype.addMathmlNodes_ = function(mmlNodes) { 289 cvox.SemanticTree.Node.prototype.addMathmlNodes_ = function(mmlNodes) {
290 for (var i = 0, mml; mml = mmlNodes[i]; i++) { 290 for (var i = 0, mml; mml = mmlNodes[i]; i++) {
291 if (this.mathml.indexOf(mml) == -1) { 291 if (this.mathml.indexOf(mml) == -1) {
292 this.mathml.push(mml); 292 this.mathml.push(mml);
293 } 293 }
294 } 294 }
295 }; 295 };
296 296
297 297
298 /** 298 /**
299 * Removes MathML nodes from the node's store of MathML nodes. 299 * Removes MathML nodes from the node's store of MathML nodes.
300 * @param {Array.<Node>} mmlNodes List of MathML nodes. 300 * @param {Array<Node>} mmlNodes List of MathML nodes.
301 * @private 301 * @private
302 */ 302 */
303 cvox.SemanticTree.Node.prototype.removeMathmlNodes_ = function(mmlNodes) { 303 cvox.SemanticTree.Node.prototype.removeMathmlNodes_ = function(mmlNodes) {
304 var mmlList = this.mathml; 304 var mmlList = this.mathml;
305 for (var i = 0, mml; mml = mmlNodes[i]; i++) { 305 for (var i = 0, mml; mml = mmlNodes[i]; i++) {
306 var index = mmlList.indexOf(mml); 306 var index = mmlList.indexOf(mml);
307 if (index != -1) { 307 if (index != -1) {
308 mmlList.splice(index, 1); 308 mmlList.splice(index, 1);
309 } 309 }
310 } 310 }
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 // TODO (sorge) Do something useful with error and phantom symbols. 486 // TODO (sorge) Do something useful with error and phantom symbols.
487 default: 487 default:
488 // Ordinarilly at this point we should not get any other tag. 488 // Ordinarilly at this point we should not get any other tag.
489 return this.makeUnprocessed_(mml); 489 return this.makeUnprocessed_(mml);
490 } 490 }
491 }; 491 };
492 492
493 493
494 /** 494 /**
495 * Parse a list of MathML nodes into the semantic tree. 495 * Parse a list of MathML nodes into the semantic tree.
496 * @param {Array.<Element>} mmls A list of MathML nodes. 496 * @param {Array<Element>} mmls A list of MathML nodes.
497 * @return {!Array.<cvox.SemanticTree.Node>} The list of resulting semantic 497 * @return {!Array<cvox.SemanticTree.Node>} The list of resulting semantic
498 * node. 498 * node.
499 * @private 499 * @private
500 */ 500 */
501 cvox.SemanticTree.prototype.parseMathmlChildren_ = function(mmls) { 501 cvox.SemanticTree.prototype.parseMathmlChildren_ = function(mmls) {
502 var result = []; 502 var result = [];
503 for (var i = 0, mml; mml = mmls[i]; i++) { 503 for (var i = 0, mml; mml = mmls[i]; i++) {
504 result.push(this.parseMathml_(mml)); 504 result.push(this.parseMathml_(mml));
505 } 505 }
506 return result; 506 return result;
507 }; 507 };
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 node.mathml = [mml]; 542 node.mathml = [mml];
543 node.updateContent_(mml.textContent); 543 node.updateContent_(mml.textContent);
544 node.font = mml.getAttribute('mathvariant') || node.font; 544 node.font = mml.getAttribute('mathvariant') || node.font;
545 return node; 545 return node;
546 }; 546 };
547 547
548 548
549 /** 549 /**
550 * Create a branching node. 550 * Create a branching node.
551 * @param {!cvox.SemanticAttr.Type} type The type of the node. 551 * @param {!cvox.SemanticAttr.Type} type The type of the node.
552 * @param {!Array.<cvox.SemanticTree.Node>} children The child nodes. 552 * @param {!Array<cvox.SemanticTree.Node>} children The child nodes.
553 * @param {!Array.<cvox.SemanticTree.Node>} contentNodes The content Nodes. 553 * @param {!Array<cvox.SemanticTree.Node>} contentNodes The content Nodes.
554 * @param {string=} content Content string if there is any. 554 * @param {string=} content Content string if there is any.
555 * @return {!cvox.SemanticTree.Node} The new node. 555 * @return {!cvox.SemanticTree.Node} The new node.
556 * @private 556 * @private
557 */ 557 */
558 cvox.SemanticTree.prototype.makeBranchNode_ = function( 558 cvox.SemanticTree.prototype.makeBranchNode_ = function(
559 type, children, contentNodes, content) { 559 type, children, contentNodes, content) {
560 var node = this.createNode_(); 560 var node = this.createNode_();
561 if (content) { 561 if (content) {
562 node.updateContent_(content); 562 node.updateContent_(content);
563 } 563 }
564 node.type = type; 564 node.type = type;
565 node.childNodes = children; 565 node.childNodes = children;
566 node.contentNodes = contentNodes; 566 node.contentNodes = contentNodes;
567 children.concat(contentNodes) 567 children.concat(contentNodes)
568 .forEach( 568 .forEach(
569 function(x) { 569 function(x) {
570 x.parent = node; 570 x.parent = node;
571 node.addMathmlNodes_(x.mathml); 571 node.addMathmlNodes_(x.mathml);
572 }); 572 });
573 return node; 573 return node;
574 }; 574 };
575 575
576 576
577 /** 577 /**
578 * Create a branching node for an implicit operation, currently assumed to 578 * Create a branching node for an implicit operation, currently assumed to
579 * be of multiplicative type. 579 * be of multiplicative type.
580 * @param {!Array.<!cvox.SemanticTree.Node>} nodes The operands. 580 * @param {!Array<!cvox.SemanticTree.Node>} nodes The operands.
581 * @return {!cvox.SemanticTree.Node} The new branch node. 581 * @return {!cvox.SemanticTree.Node} The new branch node.
582 * @private 582 * @private
583 */ 583 */
584 cvox.SemanticTree.prototype.makeImplicitNode_ = function(nodes) { 584 cvox.SemanticTree.prototype.makeImplicitNode_ = function(nodes) {
585 if (nodes.length == 1) { 585 if (nodes.length == 1) {
586 return nodes[0]; 586 return nodes[0];
587 } 587 }
588 var operator = this.createNode_(); 588 var operator = this.createNode_();
589 // For now we assume this is a multiplication using invisible times. 589 // For now we assume this is a multiplication using invisible times.
590 operator.updateContent_(cvox.SemanticAttr.invisibleTimes()); 590 operator.updateContent_(cvox.SemanticAttr.invisibleTimes());
591 var newNode = this.makeInfixNode_(nodes, operator); 591 var newNode = this.makeInfixNode_(nodes, operator);
592 newNode.role = cvox.SemanticAttr.Role.IMPLICIT; 592 newNode.role = cvox.SemanticAttr.Role.IMPLICIT;
593 return newNode; 593 return newNode;
594 }; 594 };
595 595
596 596
597 /** 597 /**
598 * Create a branching node for an infix operation. 598 * Create a branching node for an infix operation.
599 * @param {!Array.<cvox.SemanticTree.Node>} children The operands. 599 * @param {!Array<cvox.SemanticTree.Node>} children The operands.
600 * @param {!cvox.SemanticTree.Node} opNode The operator. 600 * @param {!cvox.SemanticTree.Node} opNode The operator.
601 * @return {!cvox.SemanticTree.Node} The new branch node. 601 * @return {!cvox.SemanticTree.Node} The new branch node.
602 * @private 602 * @private
603 */ 603 */
604 cvox.SemanticTree.prototype.makeInfixNode_ = function(children, opNode) { 604 cvox.SemanticTree.prototype.makeInfixNode_ = function(children, opNode) {
605 return this.makeBranchNode_( 605 return this.makeBranchNode_(
606 cvox.SemanticAttr.Type.INFIXOP, children, [opNode], opNode.textContent); 606 cvox.SemanticAttr.Type.INFIXOP, children, [opNode], opNode.textContent);
607 }; 607 };
608 608
609 609
610 /** 610 /**
611 * Creates a node of the specified type by collapsing the given node list into 611 * Creates a node of the specified type by collapsing the given node list into
612 * one content (thereby concatenating the content of each node into a single 612 * one content (thereby concatenating the content of each node into a single
613 * content string) with the inner node as a child. 613 * content string) with the inner node as a child.
614 * @param {!cvox.SemanticTree.Node} inner The inner node. 614 * @param {!cvox.SemanticTree.Node} inner The inner node.
615 * @param {!Array.<cvox.SemanticTree.Node>} nodeList List of nodes. 615 * @param {!Array<cvox.SemanticTree.Node>} nodeList List of nodes.
616 * @param {!cvox.SemanticAttr.Type} type The new type of the node. 616 * @param {!cvox.SemanticAttr.Type} type The new type of the node.
617 * @return {!cvox.SemanticTree.Node} The new branch node. 617 * @return {!cvox.SemanticTree.Node} The new branch node.
618 * @private 618 * @private
619 */ 619 */
620 cvox.SemanticTree.prototype.makeConcatNode_ = function(inner, nodeList, type) { 620 cvox.SemanticTree.prototype.makeConcatNode_ = function(inner, nodeList, type) {
621 if (nodeList.length == 0) { 621 if (nodeList.length == 0) {
622 return inner; 622 return inner;
623 } 623 }
624 var content = nodeList.map(function(x) {return x.textContent;}).join(' '); 624 var content = nodeList.map(function(x) {return x.textContent;}).join(' ');
625 var newNode = this.makeBranchNode_(type, [inner], nodeList, content); 625 var newNode = this.makeBranchNode_(type, [inner], nodeList, content);
626 if (nodeList.length > 0) { 626 if (nodeList.length > 0) {
627 newNode.role = cvox.SemanticAttr.Role.MULTIOP; 627 newNode.role = cvox.SemanticAttr.Role.MULTIOP;
628 } 628 }
629 return newNode; 629 return newNode;
630 }; 630 };
631 631
632 632
633 /** 633 /**
634 * Wraps a node into prefix operators. 634 * Wraps a node into prefix operators.
635 * Example: + - a becomes (+ (- (a))) 635 * Example: + - a becomes (+ (- (a)))
636 * Input: a [+, -] -> Output: content: '+ -', child: a 636 * Input: a [+, -] -> Output: content: '+ -', child: a
637 * @param {!cvox.SemanticTree.Node} node The inner node. 637 * @param {!cvox.SemanticTree.Node} node The inner node.
638 * @param {!Array.<cvox.SemanticTree.Node>} prefixes Prefix operators 638 * @param {!Array<cvox.SemanticTree.Node>} prefixes Prefix operators
639 * from the outermost to the innermost. 639 * from the outermost to the innermost.
640 * @return {!cvox.SemanticTree.Node} The new branch node. 640 * @return {!cvox.SemanticTree.Node} The new branch node.
641 * @private 641 * @private
642 */ 642 */
643 cvox.SemanticTree.prototype.makePrefixNode_ = function(node, prefixes) { 643 cvox.SemanticTree.prototype.makePrefixNode_ = function(node, prefixes) {
644 var negatives = cvox.SemanticTree.partitionNodes_( 644 var negatives = cvox.SemanticTree.partitionNodes_(
645 prefixes, cvox.SemanticTree.attrPred_('role', 'SUBTRACTION')); 645 prefixes, cvox.SemanticTree.attrPred_('role', 'SUBTRACTION'));
646 var newNode = this.makeConcatNode_( 646 var newNode = this.makeConcatNode_(
647 node, negatives.comp.pop(), cvox.SemanticAttr.Type.PREFIXOP); 647 node, negatives.comp.pop(), cvox.SemanticAttr.Type.PREFIXOP);
648 648
649 while (negatives.rel.length > 0) { 649 while (negatives.rel.length > 0) {
650 newNode = this.makeConcatNode_( 650 newNode = this.makeConcatNode_(
651 newNode, [negatives.rel.pop()], cvox.SemanticAttr.Type.PREFIXOP); 651 newNode, [negatives.rel.pop()], cvox.SemanticAttr.Type.PREFIXOP);
652 newNode.role = cvox.SemanticAttr.Role.NEGATIVE; 652 newNode.role = cvox.SemanticAttr.Role.NEGATIVE;
653 newNode = this.makeConcatNode_( 653 newNode = this.makeConcatNode_(
654 newNode, negatives.comp.pop(), cvox.SemanticAttr.Type.PREFIXOP); 654 newNode, negatives.comp.pop(), cvox.SemanticAttr.Type.PREFIXOP);
655 } 655 }
656 return newNode; 656 return newNode;
657 }; 657 };
658 658
659 659
660 /** 660 /**
661 * Wraps a node into postfix operators. 661 * Wraps a node into postfix operators.
662 * Example: a - + becomes (((a) -) +) 662 * Example: a - + becomes (((a) -) +)
663 * Input: a [-, +] -> Output: content: '- +', child: a 663 * Input: a [-, +] -> Output: content: '- +', child: a
664 * @param {!cvox.SemanticTree.Node} node The inner node. 664 * @param {!cvox.SemanticTree.Node} node The inner node.
665 * @param {!Array.<cvox.SemanticTree.Node>} postfixes Postfix operators from 665 * @param {!Array<cvox.SemanticTree.Node>} postfixes Postfix operators from
666 * innermost to outermost. 666 * innermost to outermost.
667 * @return {!cvox.SemanticTree.Node} The new branch node. 667 * @return {!cvox.SemanticTree.Node} The new branch node.
668 * @private 668 * @private
669 */ 669 */
670 cvox.SemanticTree.prototype.makePostfixNode_ = function(node, postfixes) { 670 cvox.SemanticTree.prototype.makePostfixNode_ = function(node, postfixes) {
671 return this.makeConcatNode_( 671 return this.makeConcatNode_(
672 node, postfixes, cvox.SemanticAttr.Type.POSTFIXOP); 672 node, postfixes, cvox.SemanticAttr.Type.POSTFIXOP);
673 }; 673 };
674 674
675 675
676 // TODO (sorge) Separate out interspersed text before the relations in row 676 // TODO (sorge) Separate out interspersed text before the relations in row
677 // heuristic otherwise we get them as implicit operations! 677 // heuristic otherwise we get them as implicit operations!
678 // Currently we handle that later in the rules, which is rather messy. 678 // Currently we handle that later in the rules, which is rather messy.
679 /** 679 /**
680 * Processes a list of nodes, combining expressions by delimiters, tables, 680 * Processes a list of nodes, combining expressions by delimiters, tables,
681 * punctuation sequences, function/big operator/integral applications to 681 * punctuation sequences, function/big operator/integral applications to
682 * generate a syntax tree with relation and operator precedence. 682 * generate a syntax tree with relation and operator precedence.
683 * 683 *
684 * This is the main heuristic to rewrite a flat row of terms into a meaningful 684 * This is the main heuristic to rewrite a flat row of terms into a meaningful
685 * term tree. 685 * term tree.
686 * @param {!Array.<cvox.SemanticTree.Node>} nodes The list of nodes. 686 * @param {!Array<cvox.SemanticTree.Node>} nodes The list of nodes.
687 * @return {!cvox.SemanticTree.Node} The root node of the syntax tree. 687 * @return {!cvox.SemanticTree.Node} The root node of the syntax tree.
688 * @private 688 * @private
689 */ 689 */
690 cvox.SemanticTree.prototype.processRow_ = function(nodes) { 690 cvox.SemanticTree.prototype.processRow_ = function(nodes) {
691 if (nodes.length == 0) { 691 if (nodes.length == 0) {
692 return this.makeEmptyNode_(); 692 return this.makeEmptyNode_();
693 } 693 }
694 nodes = this.getFencesInRow_(nodes); 694 nodes = this.getFencesInRow_(nodes);
695 nodes = this.processTablesInRow_(nodes); 695 nodes = this.processTablesInRow_(nodes);
696 nodes = this.getPunctuationInRow_(nodes); 696 nodes = this.getPunctuationInRow_(nodes);
697 nodes = this.getFunctionsInRow_(nodes); 697 nodes = this.getFunctionsInRow_(nodes);
698 return this.processRelationsInRow_(nodes); 698 return this.processRelationsInRow_(nodes);
699 }; 699 };
700 700
701 701
702 /** 702 /**
703 * Constructs a syntax tree with relation and operator precedence from a list 703 * Constructs a syntax tree with relation and operator precedence from a list
704 * of nodes. 704 * of nodes.
705 * @param {!Array.<!cvox.SemanticTree.Node>} nodes The list of nodes. 705 * @param {!Array<!cvox.SemanticTree.Node>} nodes The list of nodes.
706 * @return {!cvox.SemanticTree.Node} The root node of the syntax tree. 706 * @return {!cvox.SemanticTree.Node} The root node of the syntax tree.
707 * @private 707 * @private
708 */ 708 */
709 cvox.SemanticTree.prototype.processRelationsInRow_ = function(nodes) { 709 cvox.SemanticTree.prototype.processRelationsInRow_ = function(nodes) {
710 var partition = cvox.SemanticTree.partitionNodes_( 710 var partition = cvox.SemanticTree.partitionNodes_(
711 nodes, cvox.SemanticTree.attrPred_('type', 'RELATION')); 711 nodes, cvox.SemanticTree.attrPred_('type', 'RELATION'));
712 var firstRel = partition.rel[0]; 712 var firstRel = partition.rel[0];
713 713
714 if (!firstRel) { 714 if (!firstRel) {
715 return this.processOperationsInRow_(nodes); 715 return this.processOperationsInRow_(nodes);
716 } 716 }
717 if (nodes.length == 1) { 717 if (nodes.length == 1) {
718 return nodes[0]; 718 return nodes[0];
719 } 719 }
720 var children = partition.comp.map( 720 var children = partition.comp.map(
721 goog.bind(this.processOperationsInRow_, this)); 721 goog.bind(this.processOperationsInRow_, this));
722 if (partition.rel.every( 722 if (partition.rel.every(
723 function(x) {return x.textContent == firstRel.textContent;})) { 723 function(x) {return x.textContent == firstRel.textContent;})) {
724 return this.makeBranchNode_( 724 return this.makeBranchNode_(
725 cvox.SemanticAttr.Type.RELSEQ, children, partition.rel, 725 cvox.SemanticAttr.Type.RELSEQ, children, partition.rel,
726 firstRel.textContent); 726 firstRel.textContent);
727 } 727 }
728 return this.makeBranchNode_( 728 return this.makeBranchNode_(
729 cvox.SemanticAttr.Type.MULTIREL, children, partition.rel); 729 cvox.SemanticAttr.Type.MULTIREL, children, partition.rel);
730 }; 730 };
731 731
732 732
733 /** 733 /**
734 * Constructs a syntax tree with operator precedence from a list nodes. 734 * Constructs a syntax tree with operator precedence from a list nodes.
735 * @param {!Array.<!cvox.SemanticTree.Node>} nodes The list of nodes. 735 * @param {!Array<!cvox.SemanticTree.Node>} nodes The list of nodes.
736 * @return {!cvox.SemanticTree.Node} The root node of the syntax tree. 736 * @return {!cvox.SemanticTree.Node} The root node of the syntax tree.
737 * @private 737 * @private
738 */ 738 */
739 cvox.SemanticTree.prototype.processOperationsInRow_ = function(nodes) { 739 cvox.SemanticTree.prototype.processOperationsInRow_ = function(nodes) {
740 if (nodes.length == 0) { 740 if (nodes.length == 0) {
741 return this.makeEmptyNode_(); 741 return this.makeEmptyNode_();
742 } 742 }
743 if (nodes.length == 1) { 743 if (nodes.length == 1) {
744 return nodes[0]; 744 return nodes[0];
745 } 745 }
746 746
747 var prefix = []; 747 var prefix = [];
748 while (nodes.length > 0 && 748 while (nodes.length > 0 &&
749 nodes[0].type == cvox.SemanticAttr.Type.OPERATOR) { 749 nodes[0].type == cvox.SemanticAttr.Type.OPERATOR) {
750 prefix.push(nodes.shift()); 750 prefix.push(nodes.shift());
751 } 751 }
752 // Pathological case: only operators in row. 752 // Pathological case: only operators in row.
753 if (nodes.length == 0) { 753 if (nodes.length == 0) {
754 return this.makePrefixNode_(prefix.pop(), prefix); 754 return this.makePrefixNode_(prefix.pop(), prefix);
755 } 755 }
756 if (nodes.length == 1) { 756 if (nodes.length == 1) {
757 return this.makePrefixNode_(nodes[0], prefix); 757 return this.makePrefixNode_(nodes[0], prefix);
758 } 758 }
759 759
760 var split = cvox.SemanticTree.sliceNodes_( 760 var split = cvox.SemanticTree.sliceNodes_(
761 nodes, cvox.SemanticTree.attrPred_('type', 'OPERATOR')); 761 nodes, cvox.SemanticTree.attrPred_('type', 'OPERATOR'));
762 // At this point, we know that split.head is not empty! 762 // At this point, we know that split.head is not empty!
763 var node = this.makePrefixNode_( 763 var node = this.makePrefixNode_(
764 this.makeImplicitNode_( 764 this.makeImplicitNode_(
765 /** @type {!Array.<!cvox.SemanticTree.Node>} */ (split.head)), 765 /** @type {!Array<!cvox.SemanticTree.Node>} */ (split.head)),
766 prefix); 766 prefix);
767 if (!split.div) { 767 if (!split.div) {
768 return node; 768 return node;
769 } 769 }
770 return this.makeOperationsTree_(split.tail, node, split.div); 770 return this.makeOperationsTree_(split.tail, node, split.div);
771 }; 771 };
772 772
773 773
774 /** 774 /**
775 * Recursively constructs syntax tree with operator precedence from a list nodes 775 * Recursively constructs syntax tree with operator precedence from a list nodes
776 * given a initial root node. 776 * given a initial root node.
777 * @param {!Array.<cvox.SemanticTree.Node>} nodes The list of nodes. 777 * @param {!Array<cvox.SemanticTree.Node>} nodes The list of nodes.
778 * @param {!cvox.SemanticTree.Node} root Initial tree. 778 * @param {!cvox.SemanticTree.Node} root Initial tree.
779 * @param {!cvox.SemanticTree.Node} lastop Last operator that has not been 779 * @param {!cvox.SemanticTree.Node} lastop Last operator that has not been
780 * processed yet. 780 * processed yet.
781 * @param {Array.<cvox.SemanticTree.Node>=} prefixes Operator nodes that will 781 * @param {Array<cvox.SemanticTree.Node>=} prefixes Operator nodes that will
782 * become prefix operation (or postfix in case they come after last operand). 782 * become prefix operation (or postfix in case they come after last operand).
783 * @return {!cvox.SemanticTree.Node} The root node of the syntax tree. 783 * @return {!cvox.SemanticTree.Node} The root node of the syntax tree.
784 * @private 784 * @private
785 */ 785 */
786 cvox.SemanticTree.prototype.makeOperationsTree_ = function( 786 cvox.SemanticTree.prototype.makeOperationsTree_ = function(
787 nodes, root, lastop, prefixes) { 787 nodes, root, lastop, prefixes) {
788 prefixes = prefixes || []; 788 prefixes = prefixes || [];
789 789
790 if (nodes.length == 0) { 790 if (nodes.length == 0) {
791 // Left over prefixes become postfixes. 791 // Left over prefixes become postfixes.
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
911 * Combines delimited expressions in a list of nodes. 911 * Combines delimited expressions in a list of nodes.
912 * 912 *
913 * The basic idea of the heuristic is as follows: 913 * The basic idea of the heuristic is as follows:
914 * 1. Opening and closing delimiters are matched regardless of the actual shape 914 * 1. Opening and closing delimiters are matched regardless of the actual shape
915 * of the fence. These are turned into fenced nodes. 915 * of the fence. These are turned into fenced nodes.
916 * 2. Neutral fences are matched only with neutral fences of the same shape. 916 * 2. Neutral fences are matched only with neutral fences of the same shape.
917 * 3. For a collection of unmatched neutral fences we try to get a maximum 917 * 3. For a collection of unmatched neutral fences we try to get a maximum
918 * number of matching fences. E.g. || a|b || would be turned into a fenced 918 * number of matching fences. E.g. || a|b || would be turned into a fenced
919 * node with fences || and content a|b. 919 * node with fences || and content a|b.
920 * 4. Any remaining unmatched delimiters are turned into punctuation nodes. 920 * 4. Any remaining unmatched delimiters are turned into punctuation nodes.
921 * @param {!Array.<!cvox.SemanticTree.Node>} nodes The list of nodes. 921 * @param {!Array<!cvox.SemanticTree.Node>} nodes The list of nodes.
922 * @return {!Array.<!cvox.SemanticTree.Node>} The new list of nodes. 922 * @return {!Array<!cvox.SemanticTree.Node>} The new list of nodes.
923 * @private 923 * @private
924 */ 924 */
925 cvox.SemanticTree.prototype.getFencesInRow_ = function(nodes) { 925 cvox.SemanticTree.prototype.getFencesInRow_ = function(nodes) {
926 var partition = cvox.SemanticTree.partitionNodes_( 926 var partition = cvox.SemanticTree.partitionNodes_(
927 nodes, cvox.SemanticTree.attrPred_('type', 'FENCE')); 927 nodes, cvox.SemanticTree.attrPred_('type', 'FENCE'));
928 var felem = partition.comp.shift(); 928 var felem = partition.comp.shift();
929 return this.processFences_(partition.rel, partition.comp, [], [felem]); 929 return this.processFences_(partition.rel, partition.comp, [], [felem]);
930 }; 930 };
931 931
932 932
933 /** 933 /**
934 * Recursively processes a list of nodes and combines all the fenced expressions 934 * Recursively processes a list of nodes and combines all the fenced expressions
935 * into single nodes. It also processes singular fences, building expressions 935 * into single nodes. It also processes singular fences, building expressions
936 * that are only fenced left or right. 936 * that are only fenced left or right.
937 * @param {!Array.<cvox.SemanticTree.Node>} fences FIFO queue of fence nodes. 937 * @param {!Array<cvox.SemanticTree.Node>} fences FIFO queue of fence nodes.
938 * @param {!Array.<Array.<cvox.SemanticTree.Node>>} content FIFO queue content 938 * @param {!Array<Array<cvox.SemanticTree.Node>>} content FIFO queue content
939 * between fences. 939 * between fences.
940 * @param {!Array.<cvox.SemanticTree.Node>} openStack LIFO stack of open fences. 940 * @param {!Array<cvox.SemanticTree.Node>} openStack LIFO stack of open fences.
941 * @param {!Array.<!Array.<cvox.SemanticTree.Node>>} contentStack LIFO stack of 941 * @param {!Array<!Array<cvox.SemanticTree.Node>>} contentStack LIFO stack of
942 * content between fences yet to be processed. 942 * content between fences yet to be processed.
943 * @return {!Array.<cvox.SemanticTree.Node>} A list of nodes with all fenced 943 * @return {!Array<cvox.SemanticTree.Node>} A list of nodes with all fenced
944 * expressions processed. 944 * expressions processed.
945 * @private 945 * @private
946 */ 946 */
947 cvox.SemanticTree.prototype.processFences_ = function( 947 cvox.SemanticTree.prototype.processFences_ = function(
948 fences, content, openStack, contentStack) { 948 fences, content, openStack, contentStack) {
949 // Base case 1: Everything is used up. 949 // Base case 1: Everything is used up.
950 if (fences.length == 0 && openStack.length == 0) { 950 if (fences.length == 0 && openStack.length == 0) {
951 return contentStack[0]; 951 return contentStack[0];
952 } 952 }
953 var openPred = cvox.SemanticTree.attrPred_('role', 'OPEN'); 953 var openPred = cvox.SemanticTree.attrPred_('role', 'OPEN');
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 var fenced = fences.shift(); 1050 var fenced = fences.shift();
1051 cvox.SemanticTree.fenceToPunct_(fenced); 1051 cvox.SemanticTree.fenceToPunct_(fenced);
1052 contentStack.push(contentStack.pop().concat([fenced], content.shift())); 1052 contentStack.push(contentStack.pop().concat([fenced], content.shift()));
1053 return this.processFences_(fences, content, openStack, contentStack); 1053 return this.processFences_(fences, content, openStack, contentStack);
1054 }; 1054 };
1055 1055
1056 1056
1057 // TODO (sorge) The following could be done with linear programming. 1057 // TODO (sorge) The following could be done with linear programming.
1058 /** 1058 /**
1059 * Trys to combine neutral fences as much as possible. 1059 * Trys to combine neutral fences as much as possible.
1060 * @param {!Array.<!cvox.SemanticTree.Node>} fences A list of neutral fences. 1060 * @param {!Array<!cvox.SemanticTree.Node>} fences A list of neutral fences.
1061 * @param {!Array.<!Array.<cvox.SemanticTree.Node>>} content Intermediate 1061 * @param {!Array<!Array<cvox.SemanticTree.Node>>} content Intermediate
1062 * content. Observe that |content| = |fences| - 1 1062 * content. Observe that |content| = |fences| - 1
1063 * @return {!Array.<cvox.SemanticTree.Node>} List of node with fully fenced 1063 * @return {!Array<cvox.SemanticTree.Node>} List of node with fully fenced
1064 * nodes. 1064 * nodes.
1065 * @private 1065 * @private
1066 */ 1066 */
1067 cvox.SemanticTree.prototype.processNeutralFences_ = function(fences, content) { 1067 cvox.SemanticTree.prototype.processNeutralFences_ = function(fences, content) {
1068 if (fences.length == 0) { 1068 if (fences.length == 0) {
1069 return fences; 1069 return fences;
1070 } 1070 }
1071 if (fences.length == 1) { 1071 if (fences.length == 1) {
1072 cvox.SemanticTree.fenceToPunct_(fences[0]); 1072 cvox.SemanticTree.fenceToPunct_(fences[0]);
1073 return fences; 1073 return fences;
(...skipping 18 matching lines...) Expand all
1092 }; 1092 };
1093 1093
1094 1094
1095 /** 1095 /**
1096 * Combines nodes framed by two matching fences using the given content. 1096 * Combines nodes framed by two matching fences using the given content.
1097 * Example: leftFence: [, rightFence: ], midFences: |, | 1097 * Example: leftFence: [, rightFence: ], midFences: |, |
1098 * content: c1, c2, c3, c4, ... cn 1098 * content: c1, c2, c3, c4, ... cn
1099 * return: [c1 | c2 | c3 ], c4, ... cn 1099 * return: [c1 | c2 | c3 ], c4, ... cn
1100 * @param {!cvox.SemanticTree.Node} leftFence The left fence. 1100 * @param {!cvox.SemanticTree.Node} leftFence The left fence.
1101 * @param {!cvox.SemanticTree.Node} rightFence The right fence. 1101 * @param {!cvox.SemanticTree.Node} rightFence The right fence.
1102 * @param {!Array.<cvox.SemanticTree.Node>} midFences A list of intermediate 1102 * @param {!Array<cvox.SemanticTree.Node>} midFences A list of intermediate
1103 * fences. 1103 * fences.
1104 * @param {!Array.<!Array.<cvox.SemanticTree.Node>>} content Intermediate 1104 * @param {!Array<!Array<cvox.SemanticTree.Node>>} content Intermediate
1105 * content. Observe that |content| = |fences| - 1 + k where k >= 0 is the 1105 * content. Observe that |content| = |fences| - 1 + k where k >= 0 is the
1106 * remainder. 1106 * remainder.
1107 * @return {!Array.<!Array.<cvox.SemanticTree.Node>>} List of content nodes 1107 * @return {!Array<!Array<cvox.SemanticTree.Node>>} List of content nodes
1108 * where the first is the fully fenced node wrt. the given left and right 1108 * where the first is the fully fenced node wrt. the given left and right
1109 * fence. 1109 * fence.
1110 * @private 1110 * @private
1111 */ 1111 */
1112 cvox.SemanticTree.prototype.combineFencedContent_ = function( 1112 cvox.SemanticTree.prototype.combineFencedContent_ = function(
1113 leftFence, rightFence, midFences, content) { 1113 leftFence, rightFence, midFences, content) {
1114 1114
1115 if (midFences.length == 0) { 1115 if (midFences.length == 0) {
1116 var fenced = this.makeHorizontalFencedNode_( 1116 var fenced = this.makeHorizontalFencedNode_(
1117 leftFence, rightFence, content.shift()); 1117 leftFence, rightFence, content.shift());
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1156 fence.role = cvox.SemanticAttr.Role.CLOSEFENCE; 1156 fence.role = cvox.SemanticAttr.Role.CLOSEFENCE;
1157 break; 1157 break;
1158 } 1158 }
1159 }; 1159 };
1160 1160
1161 1161
1162 /** 1162 /**
1163 * Create a fenced node. 1163 * Create a fenced node.
1164 * @param {cvox.SemanticTree.Node} ofence Opening fence. 1164 * @param {cvox.SemanticTree.Node} ofence Opening fence.
1165 * @param {cvox.SemanticTree.Node} cfence Closing fence. 1165 * @param {cvox.SemanticTree.Node} cfence Closing fence.
1166 * @param {!Array.<cvox.SemanticTree.Node>} content The content 1166 * @param {!Array<cvox.SemanticTree.Node>} content The content
1167 * between the fences. 1167 * between the fences.
1168 * @return {!cvox.SemanticTree.Node} The new node. 1168 * @return {!cvox.SemanticTree.Node} The new node.
1169 * @private 1169 * @private
1170 */ 1170 */
1171 cvox.SemanticTree.prototype.makeHorizontalFencedNode_ = function( 1171 cvox.SemanticTree.prototype.makeHorizontalFencedNode_ = function(
1172 ofence, cfence, content) { 1172 ofence, cfence, content) {
1173 var childNode = this.processRow_(content); 1173 var childNode = this.processRow_(content);
1174 var newNode = this.makeBranchNode_( 1174 var newNode = this.makeBranchNode_(
1175 cvox.SemanticAttr.Type.FENCED, [childNode], [ofence, cfence]); 1175 cvox.SemanticAttr.Type.FENCED, [childNode], [ofence, cfence]);
1176 if (ofence.role == cvox.SemanticAttr.Role.OPEN) { 1176 if (ofence.role == cvox.SemanticAttr.Role.OPEN) {
1177 newNode.role = cvox.SemanticAttr.Role.LEFTRIGHT; 1177 newNode.role = cvox.SemanticAttr.Role.LEFTRIGHT;
1178 } else { 1178 } else {
1179 newNode.role = ofence.role; 1179 newNode.role = ofence.role;
1180 } 1180 }
1181 return newNode; 1181 return newNode;
1182 }; 1182 };
1183 1183
1184 1184
1185 /** 1185 /**
1186 * Combines sequences of punctuated expressions in a list of nodes. 1186 * Combines sequences of punctuated expressions in a list of nodes.
1187 * @param {!Array.<cvox.SemanticTree.Node>} nodes The list of nodes. 1187 * @param {!Array<cvox.SemanticTree.Node>} nodes The list of nodes.
1188 * @return {!Array.<cvox.SemanticTree.Node>} The new list of nodes. 1188 * @return {!Array<cvox.SemanticTree.Node>} The new list of nodes.
1189 * @private 1189 * @private
1190 */ 1190 */
1191 cvox.SemanticTree.prototype.getPunctuationInRow_ = function(nodes) { 1191 cvox.SemanticTree.prototype.getPunctuationInRow_ = function(nodes) {
1192 // For now we just make a punctuation node with a particular role. This is 1192 // For now we just make a punctuation node with a particular role. This is
1193 // similar to an mrow. The only exception are ellipses, which we assume to be 1193 // similar to an mrow. The only exception are ellipses, which we assume to be
1194 // in lieu of identifiers. 1194 // in lieu of identifiers.
1195 // In addition we keep the single punctuation nodes as content. 1195 // In addition we keep the single punctuation nodes as content.
1196 var partition = cvox.SemanticTree.partitionNodes_( 1196 var partition = cvox.SemanticTree.partitionNodes_(
1197 nodes, function(x) { 1197 nodes, function(x) {
1198 return cvox.SemanticTree.attrPred_('type', 'PUNCTUATION')(x) && 1198 return cvox.SemanticTree.attrPred_('type', 'PUNCTUATION')(x) &&
(...skipping 13 matching lines...) Expand all
1212 if (firstComp.length > 0) { 1212 if (firstComp.length > 0) {
1213 newNodes.push(this.processRow_(firstComp)); 1213 newNodes.push(this.processRow_(firstComp));
1214 } 1214 }
1215 } 1215 }
1216 return [this.makePunctuatedNode_(newNodes, partition.rel)]; 1216 return [this.makePunctuatedNode_(newNodes, partition.rel)];
1217 }; 1217 };
1218 1218
1219 1219
1220 /** 1220 /**
1221 * Create a punctuated node. 1221 * Create a punctuated node.
1222 * @param {!Array.<!cvox.SemanticTree.Node>} nodes List of all nodes separated 1222 * @param {!Array<!cvox.SemanticTree.Node>} nodes List of all nodes separated
1223 * by punctuations. 1223 * by punctuations.
1224 * @param {!Array.<!cvox.SemanticTree.Node>} punctuations List of all separating 1224 * @param {!Array<!cvox.SemanticTree.Node>} punctuations List of all separating
1225 * punctations. Observe that punctations is a subset of nodes. 1225 * punctations. Observe that punctations is a subset of nodes.
1226 * @return {!cvox.SemanticTree.Node} 1226 * @return {!cvox.SemanticTree.Node}
1227 * @private 1227 * @private
1228 */ 1228 */
1229 cvox.SemanticTree.prototype.makePunctuatedNode_ = function( 1229 cvox.SemanticTree.prototype.makePunctuatedNode_ = function(
1230 nodes, punctuations) { 1230 nodes, punctuations) {
1231 var newNode = this.makeBranchNode_( 1231 var newNode = this.makeBranchNode_(
1232 cvox.SemanticAttr.Type.PUNCTUATED, nodes, punctuations); 1232 cvox.SemanticAttr.Type.PUNCTUATED, nodes, punctuations);
1233 1233
1234 if (punctuations.length == 1 && 1234 if (punctuations.length == 1 &&
1235 nodes[0].type == cvox.SemanticAttr.Type.PUNCTUATION) { 1235 nodes[0].type == cvox.SemanticAttr.Type.PUNCTUATION) {
1236 newNode.role = cvox.SemanticAttr.Role.STARTPUNCT; 1236 newNode.role = cvox.SemanticAttr.Role.STARTPUNCT;
1237 } else if (punctuations.length == 1 && 1237 } else if (punctuations.length == 1 &&
1238 nodes[nodes.length - 1].type == cvox.SemanticAttr.Type.PUNCTUATION) { 1238 nodes[nodes.length - 1].type == cvox.SemanticAttr.Type.PUNCTUATION) {
1239 newNode.role = cvox.SemanticAttr.Role.ENDPUNCT; 1239 newNode.role = cvox.SemanticAttr.Role.ENDPUNCT;
1240 } else { 1240 } else {
1241 newNode.role = cvox.SemanticAttr.Role.SEQUENCE; 1241 newNode.role = cvox.SemanticAttr.Role.SEQUENCE;
1242 } 1242 }
1243 return newNode; 1243 return newNode;
1244 }; 1244 };
1245 1245
1246 1246
1247 /** 1247 /**
1248 * Creates a limit node from a sub/superscript or over/under node if the central 1248 * Creates a limit node from a sub/superscript or over/under node if the central
1249 * element is a big operator. Otherwise it creates the standard elements. 1249 * element is a big operator. Otherwise it creates the standard elements.
1250 * @param {string} mmlTag The tag name of the original node. 1250 * @param {string} mmlTag The tag name of the original node.
1251 * @param {!Array.<!cvox.SemanticTree.Node>} children The children of the 1251 * @param {!Array<!cvox.SemanticTree.Node>} children The children of the
1252 * original node. 1252 * original node.
1253 * @return {!cvox.SemanticTree.Node} The newly created limit node. 1253 * @return {!cvox.SemanticTree.Node} The newly created limit node.
1254 * @private 1254 * @private
1255 */ 1255 */
1256 cvox.SemanticTree.prototype.makeLimitNode_ = function(mmlTag, children) { 1256 cvox.SemanticTree.prototype.makeLimitNode_ = function(mmlTag, children) {
1257 var center = children[0]; 1257 var center = children[0];
1258 var isFunction = cvox.SemanticTree.attrPred_('type', 'FUNCTION')(center); 1258 var isFunction = cvox.SemanticTree.attrPred_('type', 'FUNCTION')(center);
1259 // TODO (sorge) Put this into a single function. 1259 // TODO (sorge) Put this into a single function.
1260 var isLimit = cvox.SemanticTree.attrPred_('type', 'LARGEOP')(center) || 1260 var isLimit = cvox.SemanticTree.attrPred_('type', 'LARGEOP')(center) ||
1261 cvox.SemanticTree.attrPred_('type', 'LIMBOTH')(center) || 1261 cvox.SemanticTree.attrPred_('type', 'LIMBOTH')(center) ||
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1324 * as a functional expressions that consists of a prefix and some arguments. 1324 * as a functional expressions that consists of a prefix and some arguments.
1325 * In particular we distinguish four types of functional expressions: 1325 * In particular we distinguish four types of functional expressions:
1326 * - integral: Integral expression. 1326 * - integral: Integral expression.
1327 * - bigop: A big operator expression like a sum. 1327 * - bigop: A big operator expression like a sum.
1328 * - prefix: A well defined prefix function such as sin, cos or a limit 1328 * - prefix: A well defined prefix function such as sin, cos or a limit
1329 * functions like lim, max. 1329 * functions like lim, max.
1330 * - simple: An expression consisting of letters that are potentially a function 1330 * - simple: An expression consisting of letters that are potentially a function
1331 * symbol. If we have an explicit function application symbol 1331 * symbol. If we have an explicit function application symbol
1332 * following the expression we turn into a prefix function. Otherwise 1332 * following the expression we turn into a prefix function. Otherwise
1333 * we decide heuristically if we could have a function application. 1333 * we decide heuristically if we could have a function application.
1334 * @param {!Array.<cvox.SemanticTree.Node>} restNodes The remainder list of 1334 * @param {!Array<cvox.SemanticTree.Node>} restNodes The remainder list of
1335 * nodes. 1335 * nodes.
1336 * @param {!Array.<cvox.SemanticTree.Node>=} result The result node list. 1336 * @param {!Array<cvox.SemanticTree.Node>=} result The result node list.
1337 * @return {!Array.<!cvox.SemanticTree.Node>} The fully processed list. 1337 * @return {!Array<!cvox.SemanticTree.Node>} The fully processed list.
1338 * @private 1338 * @private
1339 */ 1339 */
1340 cvox.SemanticTree.prototype.getFunctionsInRow_ = function(restNodes, result) { 1340 cvox.SemanticTree.prototype.getFunctionsInRow_ = function(restNodes, result) {
1341 result = result || []; 1341 result = result || [];
1342 // Base case. 1342 // Base case.
1343 if (restNodes.length == 0) { 1343 if (restNodes.length == 0) {
1344 return result; 1344 return result;
1345 } 1345 }
1346 var firstNode = /** @type {!cvox.SemanticTree.Node} */ (restNodes.shift()); 1346 var firstNode = /** @type {!cvox.SemanticTree.Node} */ (restNodes.shift());
1347 var heuristic = cvox.SemanticTree.classifyFunction_(firstNode, restNodes); 1347 var heuristic = cvox.SemanticTree.classifyFunction_(firstNode, restNodes);
1348 // First node is not a function node. 1348 // First node is not a function node.
1349 if (!heuristic) { 1349 if (!heuristic) {
1350 result.push(firstNode); 1350 result.push(firstNode);
1351 return this.getFunctionsInRow_(restNodes, result); 1351 return this.getFunctionsInRow_(restNodes, result);
1352 } 1352 }
1353 // Combine functions in the rest of the row. 1353 // Combine functions in the rest of the row.
1354 var processedRest = this.getFunctionsInRow_(restNodes, []); 1354 var processedRest = this.getFunctionsInRow_(restNodes, []);
1355 var newRest = this.getFunctionArgs_(firstNode, processedRest, heuristic); 1355 var newRest = this.getFunctionArgs_(firstNode, processedRest, heuristic);
1356 return result.concat(newRest); 1356 return result.concat(newRest);
1357 }; 1357 };
1358 1358
1359 1359
1360 /** 1360 /**
1361 * Classifies a function wrt. the heuristic that should be applied. 1361 * Classifies a function wrt. the heuristic that should be applied.
1362 * @param {!cvox.SemanticTree.Node} funcNode The node to be classified. 1362 * @param {!cvox.SemanticTree.Node} funcNode The node to be classified.
1363 * @param {!Array.<cvox.SemanticTree.Node>} restNodes The remainder list of 1363 * @param {!Array<cvox.SemanticTree.Node>} restNodes The remainder list of
1364 * nodes. They can useful to look ahead if there is an explicit function 1364 * nodes. They can useful to look ahead if there is an explicit function
1365 * application. If there is one, it will be destructively removed! 1365 * application. If there is one, it will be destructively removed!
1366 * @return {!string} The string specifying the heuristic. 1366 * @return {!string} The string specifying the heuristic.
1367 * @private 1367 * @private
1368 */ 1368 */
1369 cvox.SemanticTree.classifyFunction_ = function(funcNode, restNodes) { 1369 cvox.SemanticTree.classifyFunction_ = function(funcNode, restNodes) {
1370 // We do not allow double function application. This is not lambda calculus! 1370 // We do not allow double function application. This is not lambda calculus!
1371 if (funcNode.type == cvox.SemanticAttr.Type.APPL || 1371 if (funcNode.type == cvox.SemanticAttr.Type.APPL ||
1372 funcNode.type == cvox.SemanticAttr.Type.BIGOP || 1372 funcNode.type == cvox.SemanticAttr.Type.BIGOP ||
1373 funcNode.type == cvox.SemanticAttr.Type.INTEGRAL) { 1373 funcNode.type == cvox.SemanticAttr.Type.INTEGRAL) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1415 funcNode.role = cvox.SemanticAttr.Role.PREFIXFUNC; 1415 funcNode.role = cvox.SemanticAttr.Role.PREFIXFUNC;
1416 cvox.SemanticTree.propagatePrefixFunc_(funcNode.childNodes[0]); 1416 cvox.SemanticTree.propagatePrefixFunc_(funcNode.childNodes[0]);
1417 } 1417 }
1418 }; 1418 };
1419 1419
1420 1420
1421 /** 1421 /**
1422 * Computes the arguments for a function from a list of nodes depending on the 1422 * Computes the arguments for a function from a list of nodes depending on the
1423 * given heuristic. 1423 * given heuristic.
1424 * @param {!cvox.SemanticTree.Node} func A function node. 1424 * @param {!cvox.SemanticTree.Node} func A function node.
1425 * @param {!Array.<cvox.SemanticTree.Node>} rest List of nodes to choose 1425 * @param {!Array<cvox.SemanticTree.Node>} rest List of nodes to choose
1426 * arguments from. 1426 * arguments from.
1427 * @param {string} heuristic The heuristic to follow. 1427 * @param {string} heuristic The heuristic to follow.
1428 * @return {!Array.<!cvox.SemanticTree.Node>} The function and the remainder of 1428 * @return {!Array<!cvox.SemanticTree.Node>} The function and the remainder of
1429 * the rest list. 1429 * the rest list.
1430 * @private 1430 * @private
1431 */ 1431 */
1432 cvox.SemanticTree.prototype.getFunctionArgs_ = function(func, rest, heuristic) { 1432 cvox.SemanticTree.prototype.getFunctionArgs_ = function(func, rest, heuristic) {
1433 switch (heuristic) { 1433 switch (heuristic) {
1434 case 'integral': 1434 case 'integral':
1435 var components = this.getIntegralArgs_(rest); 1435 var components = this.getIntegralArgs_(rest);
1436 var integrand = this.processRow_(components.integrand); 1436 var integrand = this.processRow_(components.integrand);
1437 var funcNode = this.makeIntegralNode_(func, integrand, components.intvar); 1437 var funcNode = this.makeIntegralNode_(func, integrand, components.intvar);
1438 components.rest.unshift(funcNode); 1438 components.rest.unshift(funcNode);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1475 } 1475 }
1476 rest.unshift(func); 1476 rest.unshift(func);
1477 return rest; 1477 return rest;
1478 break; 1478 break;
1479 } 1479 }
1480 }; 1480 };
1481 1481
1482 1482
1483 /** 1483 /**
1484 * Tail recursive function to obtain integral arguments. 1484 * Tail recursive function to obtain integral arguments.
1485 * @param {!Array.<cvox.SemanticTree.Node>} nodes List of nodes to take 1485 * @param {!Array<cvox.SemanticTree.Node>} nodes List of nodes to take
1486 * arguments from. 1486 * arguments from.
1487 * @param {Array.<cvox.SemanticTree.Node>=} args List of integral arguments. 1487 * @param {Array<cvox.SemanticTree.Node>=} args List of integral arguments.
1488 * @return {{integrand: !Array.<cvox.SemanticTree.Node>, 1488 * @return {{integrand: !Array<cvox.SemanticTree.Node>,
1489 * intvar: cvox.SemanticTree.Node, 1489 * intvar: cvox.SemanticTree.Node,
1490 * rest: !Array.<cvox.SemanticTree.Node>}} 1490 * rest: !Array<cvox.SemanticTree.Node>}}
1491 * Result split into integrand, integral variable and the remaining 1491 * Result split into integrand, integral variable and the remaining
1492 * elements. 1492 * elements.
1493 * @private 1493 * @private
1494 */ 1494 */
1495 cvox.SemanticTree.prototype.getIntegralArgs_ = function(nodes, args) { 1495 cvox.SemanticTree.prototype.getIntegralArgs_ = function(nodes, args) {
1496 args = args || []; 1496 args = args || [];
1497 if (nodes.length == 0) { 1497 if (nodes.length == 0) {
1498 return {integrand: args, intvar: null, rest: nodes}; 1498 return {integrand: args, intvar: null, rest: nodes};
1499 } 1499 }
1500 var firstNode = nodes[0]; 1500 var firstNode = nodes[0];
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
1657 * @private 1657 * @private
1658 */ 1658 */
1659 cvox.SemanticTree.generalFunctionBoundary_ = function(node) { 1659 cvox.SemanticTree.generalFunctionBoundary_ = function(node) {
1660 return cvox.SemanticTree.attrPred_('type', 'RELATION')(node) || 1660 return cvox.SemanticTree.attrPred_('type', 'RELATION')(node) ||
1661 cvox.SemanticTree.attrPred_('type', 'PUNCTUATION')(node); 1661 cvox.SemanticTree.attrPred_('type', 'PUNCTUATION')(node);
1662 }; 1662 };
1663 1663
1664 1664
1665 /** 1665 /**
1666 * Rewrites tables into matrices or case statements in a list of nodes. 1666 * Rewrites tables into matrices or case statements in a list of nodes.
1667 * @param {!Array.<cvox.SemanticTree.Node>} nodes List of nodes to rewrite. 1667 * @param {!Array<cvox.SemanticTree.Node>} nodes List of nodes to rewrite.
1668 * @return {!Array.<cvox.SemanticTree.Node>} The new list of nodes. 1668 * @return {!Array<cvox.SemanticTree.Node>} The new list of nodes.
1669 * @private 1669 * @private
1670 */ 1670 */
1671 cvox.SemanticTree.prototype.processTablesInRow_ = function(nodes) { 1671 cvox.SemanticTree.prototype.processTablesInRow_ = function(nodes) {
1672 // First we process all matrices: 1672 // First we process all matrices:
1673 var partition = cvox.SemanticTree.partitionNodes_( 1673 var partition = cvox.SemanticTree.partitionNodes_(
1674 nodes, cvox.SemanticTree.tableIsMatrixOrVector_); 1674 nodes, cvox.SemanticTree.tableIsMatrixOrVector_);
1675 var result = []; 1675 var result = [];
1676 for (var i = 0, matrix; matrix = partition.rel[i]; i++) { 1676 for (var i = 0, matrix; matrix = partition.rel[i]; i++) {
1677 result = result.concat(partition.comp.shift()); 1677 result = result.concat(partition.comp.shift());
1678 result.push(this.tableToMatrixOrVector_(matrix)); 1678 result.push(this.tableToMatrixOrVector_(matrix));
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1738 cvox.SemanticTree.assignRoleToRow_(row, cvox.SemanticAttr.Role[type]); 1738 cvox.SemanticTree.assignRoleToRow_(row, cvox.SemanticAttr.Role[type]);
1739 } 1739 }
1740 return matrix; 1740 return matrix;
1741 }; 1741 };
1742 1742
1743 1743
1744 /** 1744 /**
1745 * Heuristic to decide if we have a case statement: An expression with a 1745 * Heuristic to decide if we have a case statement: An expression with a
1746 * singular open fence before it. 1746 * singular open fence before it.
1747 * @param {!cvox.SemanticTree.Node} table A table node. 1747 * @param {!cvox.SemanticTree.Node} table A table node.
1748 * @param {!Array.<cvox.SemanticTree.Node>} prevNodes A list of previous nodes. 1748 * @param {!Array<cvox.SemanticTree.Node>} prevNodes A list of previous nodes.
1749 * @return {boolean} True if we believe we have a case statement. 1749 * @return {boolean} True if we believe we have a case statement.
1750 * @private 1750 * @private
1751 */ 1751 */
1752 cvox.SemanticTree.tableIsCases_ = function(table, prevNodes) { 1752 cvox.SemanticTree.tableIsCases_ = function(table, prevNodes) {
1753 return prevNodes.length > 0 && 1753 return prevNodes.length > 0 &&
1754 cvox.SemanticTree.attrPred_('role', 'OPENFENCE')( 1754 cvox.SemanticTree.attrPred_('role', 'OPENFENCE')(
1755 prevNodes[prevNodes.length - 1]); 1755 prevNodes[prevNodes.length - 1]);
1756 }; 1756 };
1757 1757
1758 1758
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1845 if (cellPred(cell)) { 1845 if (cellPred(cell)) {
1846 cell.role = role; 1846 cell.role = role;
1847 } 1847 }
1848 }); 1848 });
1849 } 1849 }
1850 }; 1850 };
1851 1851
1852 1852
1853 /** 1853 /**
1854 * Splits a list of nodes wrt. to a given predicate. 1854 * Splits a list of nodes wrt. to a given predicate.
1855 * @param {Array.<cvox.SemanticTree.Node>} nodes A list of nodes. 1855 * @param {Array<cvox.SemanticTree.Node>} nodes A list of nodes.
1856 * @param {!function(cvox.SemanticTree.Node): boolean} pred Predicate for the 1856 * @param {!function(cvox.SemanticTree.Node): boolean} pred Predicate for the
1857 * partitioning relation. 1857 * partitioning relation.
1858 * @param {boolean=} reverse If true slicing is done from the end. 1858 * @param {boolean=} reverse If true slicing is done from the end.
1859 * @return {{head: !Array.<cvox.SemanticTree.Node>, 1859 * @return {{head: !Array<cvox.SemanticTree.Node>,
1860 * div: cvox.SemanticTree.Node, 1860 * div: cvox.SemanticTree.Node,
1861 * tail: !Array.<cvox.SemanticTree.Node>}} The split list. 1861 * tail: !Array<cvox.SemanticTree.Node>}} The split list.
1862 * @private 1862 * @private
1863 */ 1863 */
1864 cvox.SemanticTree.sliceNodes_ = function(nodes, pred, reverse) { 1864 cvox.SemanticTree.sliceNodes_ = function(nodes, pred, reverse) {
1865 if (reverse) { 1865 if (reverse) {
1866 nodes.reverse(); 1866 nodes.reverse();
1867 } 1867 }
1868 var head = []; 1868 var head = [];
1869 for (var i = 0, node; node = nodes[i]; i++) { 1869 for (var i = 0, node; node = nodes[i]; i++) {
1870 if (pred(node)) { 1870 if (pred(node)) {
1871 if (reverse) { 1871 if (reverse) {
(...skipping 10 matching lines...) Expand all
1882 if (reverse) { 1882 if (reverse) {
1883 return {head: [], div: null, tail: head.reverse()}; 1883 return {head: [], div: null, tail: head.reverse()};
1884 } 1884 }
1885 return {head: head, div: null, tail: []}; 1885 return {head: head, div: null, tail: []};
1886 }; 1886 };
1887 1887
1888 1888
1889 /** 1889 /**
1890 * Partitions a list of nodes wrt. to a given predicate. Effectively works like 1890 * Partitions a list of nodes wrt. to a given predicate. Effectively works like
1891 * a PER on the ordered set of nodes. 1891 * a PER on the ordered set of nodes.
1892 * @param {!Array.<!cvox.SemanticTree.Node>} nodes A list of nodes. 1892 * @param {!Array<!cvox.SemanticTree.Node>} nodes A list of nodes.
1893 * @param {!function(cvox.SemanticTree.Node): boolean} pred Predicate for the 1893 * @param {!function(cvox.SemanticTree.Node): boolean} pred Predicate for the
1894 * partitioning relation. 1894 * partitioning relation.
1895 * @return {{rel: !Array.<cvox.SemanticTree.Node>, 1895 * @return {{rel: !Array<cvox.SemanticTree.Node>,
1896 * comp: !Array.<!Array.<cvox.SemanticTree.Node>>}} 1896 * comp: !Array<!Array<cvox.SemanticTree.Node>>}}
1897 * The partitioning given in terms of a collection of elements satisfying 1897 * The partitioning given in terms of a collection of elements satisfying
1898 * the predicate and a collection of complementary sets lying inbetween the 1898 * the predicate and a collection of complementary sets lying inbetween the
1899 * related elements. Observe that we always have |comp| = |rel| + 1. 1899 * related elements. Observe that we always have |comp| = |rel| + 1.
1900 * 1900 *
1901 * Example: On input [a, r_1, b, c, r_2, d, e, r_3] where P(r_i) holds, we 1901 * Example: On input [a, r_1, b, c, r_2, d, e, r_3] where P(r_i) holds, we
1902 * get as output: {rel: [r_1, r_2, r_3], comp: [[a], [b, c], [d, e], []]. 1902 * get as output: {rel: [r_1, r_2, r_3], comp: [[a], [b, c], [d, e], []].
1903 * @private 1903 * @private
1904 */ 1904 */
1905 cvox.SemanticTree.partitionNodes_ = function(nodes, pred) { 1905 cvox.SemanticTree.partitionNodes_ = function(nodes, pred) {
1906 var restNodes = nodes; 1906 var restNodes = nodes;
(...skipping 23 matching lines...) Expand all
1930 var getAttr = function(prop) { 1930 var getAttr = function(prop) {
1931 switch (prop) { 1931 switch (prop) {
1932 case 'type': return cvox.SemanticAttr.Type[attr]; 1932 case 'type': return cvox.SemanticAttr.Type[attr];
1933 case 'role': return cvox.SemanticAttr.Role[attr]; 1933 case 'role': return cvox.SemanticAttr.Role[attr];
1934 case 'font': return cvox.SemanticAttr.Font[attr]; 1934 case 'font': return cvox.SemanticAttr.Font[attr];
1935 } 1935 }
1936 }; 1936 };
1937 1937
1938 return function(node) {return node[prop] == getAttr(prop);}; 1938 return function(node) {return node[prop] == getAttr(prop);};
1939 }; 1939 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698