Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / resources / chromeos / chromevox / speech_rules / mathml_store_rules.js
blobec16ce9a7c86279a4f7b4882201a41996ede00be
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
3 // found in the LICENSE file.
5 /**
6  * @fileoverview Speech rules for mathml and mathjax nodes.
7  */
9 goog.provide('cvox.MathmlStoreRules');
11 goog.require('cvox.MathStore');
12 goog.require('cvox.MathmlStore');
13 goog.require('cvox.MathmlStoreUtil');
14 goog.require('cvox.StoreUtil');
17 /**
18  * Rule initialization.
19  * @constructor
20  */
21 cvox.MathmlStoreRules = function() {
22   // Custom functions used in the rules.
23   cvox.MathmlStoreRules.initCustomFunctions_();
24   cvox.MathmlStoreRules.initDefaultRules_(); // MathML rules.
25   cvox.MathmlStoreRules.initMathjaxRules_(); // MathJax Rules
26   cvox.MathmlStoreRules.initAliases_(); // MathJax Aliases for MathML rules.
27   cvox.MathmlStoreRules.initSpecializationRules_(); // Square, cube, etc.
28   cvox.MathmlStoreRules.initSemanticRules_();
30 goog.addSingletonGetter(cvox.MathmlStoreRules);
33 /**
34  * @type {cvox.MathStore}
35  */
36 cvox.MathmlStoreRules.mathStore = cvox.MathmlStore.getInstance();
37 /**
38  * @override
39  */
40 cvox.MathmlStoreRules.mathStore.initialize = cvox.MathmlStoreRules.getInstance;
42 // These are used to work around Closure's rules for aliasing.
43 /** @private */
44 cvox.MathmlStoreRules.defineDefaultMathmlRule_ = goog.bind(
45     cvox.MathmlStoreRules.mathStore.defineDefaultMathmlRule,
46     cvox.MathmlStoreRules.mathStore);
47 /** @private */
48 cvox.MathmlStoreRules.defineRule_ = goog.bind(
49     cvox.MathmlStoreRules.mathStore.defineRule,
50     cvox.MathmlStoreRules.mathStore);
51 /** @private */
52 cvox.MathmlStoreRules.defineRuleAlias_ = goog.bind(
53     cvox.MathmlStoreRules.mathStore.defineRuleAlias,
54     cvox.MathmlStoreRules.mathStore);
55 /** @private */
56 cvox.MathmlStoreRules.addContextFunction_ = goog.bind(
57     cvox.MathmlStoreRules.mathStore.contextFunctions.add,
58     cvox.MathmlStoreRules.mathStore.contextFunctions);
59 /** @private */
60 cvox.MathmlStoreRules.addCustomQuery_ = goog.bind(
61     cvox.MathmlStoreRules.mathStore.customQueries.add,
62     cvox.MathmlStoreRules.mathStore.customQueries);
64 goog.scope(function() {
65 var defineDefaultMathmlRule = cvox.MathmlStoreRules.defineDefaultMathmlRule_;
66 var defineRule = cvox.MathmlStoreRules.defineRule_;
67 var defineRuleAlias = cvox.MathmlStoreRules.defineRuleAlias_;
69 var addCTXF = cvox.MathmlStoreRules.addContextFunction_;
70 var addCQF = cvox.MathmlStoreRules.addCustomQuery_;
72 /**
73  * Initialize the custom functions.
74  * @private
75  */
76 cvox.MathmlStoreRules.initCustomFunctions_ = function() {
77   addCTXF('CTXFnodeCounter', cvox.StoreUtil.nodeCounter);
78   addCTXF('CTXFmfSeparators', cvox.MathmlStoreUtil.mfencedSeparators);
79   addCTXF('CTXFcontentIterator', cvox.MathmlStoreUtil.contentIterator);
81   addCQF('CQFextender', cvox.MathmlStoreUtil.retrieveMathjaxExtender);
82   addCQF('CQFmathmlmunder', cvox.MathmlStoreUtil.checkMathjaxMunder);
83   addCQF('CQFmathmlmover', cvox.MathmlStoreUtil.checkMathjaxMover);
84   addCQF('CQFmathmlmsub', cvox.MathmlStoreUtil.checkMathjaxMsub);
85   addCQF('CQFmathmlmsup', cvox.MathmlStoreUtil.checkMathjaxMsup);
86   addCQF('CQFlookupleaf', cvox.MathmlStoreUtil.retrieveMathjaxLeaf);
91 /**
92  * Initialize the default mathrules.
93  * @private
94  */
95 cvox.MathmlStoreRules.initDefaultRules_ = function() {
96   // Initial rule
97   defineDefaultMathmlRule('math', '[m] ./*');
98   defineDefaultMathmlRule('semantics', '[n] ./*[1]');
100   // Space elements
101   defineDefaultMathmlRule('mspace', '[p] (pause:250)');
102   defineDefaultMathmlRule('mstyle', '[m] ./*');
103   defineDefaultMathmlRule('mpadded', '[m] ./*');
104   defineDefaultMathmlRule('merror', '[t] ""');
105   defineDefaultMathmlRule('mphantom', '[t] ""');
107   // Token elements.
108   defineDefaultMathmlRule('mtext', '[t] text(); [p] (pause:200)');
109   defineDefaultMathmlRule('mi', '[n] text()');
110   defineDefaultMathmlRule('mo', '[n] text() (rate:-0.1)');
111   defineDefaultMathmlRule('mn', '[n] text()');
113   // Dealing with fonts.
114   defineRule('mtext-variant', 'default.default',
115       '[t] "begin"; [t] @mathvariant (pause:150);' +
116           '[t] text() (pause:150); [t] "end"; ' +
117           '[t] @mathvariant (pause:200)',
118       'self::mathml:mtext', '@mathvariant', '@mathvariant!="normal"');
120   defineRule('mi-variant', 'default.default',
121       '[t] @mathvariant; [n] text()',
122       'self::mathml:mi', '@mathvariant', '@mathvariant!="normal"');
124   defineRuleAlias('mi-variant', 'self::mathml:mn',  // mn
125       '@mathvariant', '@mathvariant!="normal"');
127   defineRule('mo-variant', 'default.default',
128       '[t] @mathvariant; [n] text() (rate:-0.1)',
129       'self::mathml:mo', '@mathvariant', '@mathvariant!="normal"');
131   defineDefaultMathmlRule(
132       'ms',
133       '[t] "string" (pitch:0.5, rate:0.5); [t] text()');
135   // Script elements.
136   defineDefaultMathmlRule(
137       'msup', '[n] ./*[1]; [t] "super";' +
138           '[n] ./*[2] (pitch:0.35); [p] (pause:300)');
139   defineDefaultMathmlRule(
140       'msubsup',
141       '[n] ./*[1]; [t] "sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);' +
142           '[t] "super"; [n] ./*[3] (pitch:0.35); [p] (pause:300)'
143       );
144   defineDefaultMathmlRule(
145       'msub',
146       '[n] ./*[1]; [t] "sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:300)');
147   defineDefaultMathmlRule(
148       'mover', '[n] ./*[2] (pitch:0.35); [p] (pause:200);' +
149           ' [t] "over"; [n] ./*[1]; [p] (pause:400)');
150   defineDefaultMathmlRule(
151       'munder',
152       '[n] ./*[2] (pitch:-0.35); [t] "under"; [n] ./*[1]; [p] (pause:400)');
153   defineDefaultMathmlRule(
154       'munderover',
155       '[n] ./*[2] (pitch:-0.35); [t] "under and"; [n] ./*[3] (pitch:0.35);' +
156           ' [t] "over"; [n] ./*[1]; [p] (pause:400)');
158   // Layout elements.
159   defineDefaultMathmlRule('mrow', '[m] ./*');
160   defineDefaultMathmlRule(
161       'msqrt', '[t] "Square root of"; [m] ./* (rate:0.2); [p] (pause:400)');
162   defineDefaultMathmlRule(
163       'mroot', '[t] "root of order"; [n] ./*[2]; [t] "of";' +
164           '[n] ./*[1] (rate:0.2); [p] (pause:400)');
165   defineDefaultMathmlRule(
166       'mfrac', ' [p] (pause:400); [n] ./*[1] (pitch:0.3);' +
167           ' [t] "divided by"; [n] ./*[2] (pitch:-0.3); [p] (pause:400)');
168   defineRule(
169       'mfrac', 'default.short', '[p] (pause:200); [t] "start frac";' +
170           '[n] ./*[1] (pitch:0.3); [t] "over"; ' +
171           '[n] ./*[2] (pitch:-0.3); [p] (pause:400); [t] "end frac"',
172       'self::mathml:mfrac');
175   defineRule(
176       'mfenced-single', 'default.default',
177       '[t] concat(substring(@open, 0 div boolean(@open)), ' +
178           'substring("(", 0 div not(boolean(@open)))) (context:"opening"); ' +
179           '[m] ./* (separator:@separators); ' +
180           '[t] concat(substring(@close, 0 div boolean(@close)), ' +
181           'substring(")", 0 div not(boolean(@close)))) (context:"closing")',
182       'self::mathml:mfenced', 'string-length(string(@separators))=1');
184   defineRule(
185       'mfenced-omit', 'default.default',
186       '[t] concat(substring(@open, 0 div boolean(@open)), ' +
187           'substring("(", 0 div not(boolean(@open)))) (context:"opening"); ' +
188           '[m] ./*; ' +
189           '[t] concat(substring(@close, 0 div boolean(@close)), ' +
190           'substring(")", 0 div not(boolean(@close)))) (context:"closing")',
191       'self::mathml:mfenced', '@separators',
192       'string-length(string(@separators))=0', 'string(@separators)=""');
194   defineRule(
195       'mfenced-empty', 'default.default',
196       '[t] concat(substring(@open, 0 div boolean(@open)), ' +
197           'substring("(", 0 div not(boolean(@open)))) (context:"opening"); ' +
198           '[m] ./*;' +
199           '[t] concat(substring(@close, 0 div boolean(@close)), ' +
200           'substring(")", 0 div not(boolean(@close)))) (context:"closing")',
201       'self::mathml:mfenced', 'string-length(string(@separators))=1',
202       'string(@separators)=" "');
204   defineRule(
205       'mfenced-comma', 'default.default',
206       '[t] concat(substring(@open, 0 div boolean(@open)), ' +
207           'substring("(", 0 div not(boolean(@open)))) (context:"opening"); ' +
208           '[m] ./* (separator:"comma");' +
209           '[t] concat(substring(@close, 0 div boolean(@close)), ' +
210           'substring(")", 0 div not(boolean(@close)))) (context:"closing")',
211       'self::mathml:mfenced');
213   defineRule(
214       'mfenced-multi', 'default.default',
215       '[t] concat(substring(@open, 0 div boolean(@open)), ' +
216           'substring("(", 0 div not(boolean(@open)))) (context:"opening"); ' +
217           '[m] ./* (sepFunc:CTXFmfSeparators, separator:@separators); ' +
218           '[t] concat(substring(@close, 0 div boolean(@close)), ' +
219           'substring(")", 0 div not(boolean(@close)))) (context:"closing")',
220       'self::mathml:mfenced', 'string-length(string(@separators))>1');
222   // Mtable rules.
223   defineRule(
224       'mtable', 'default.default',
225       '[t] "matrix"; [m] ./* (ctxtFunc:CTXFnodeCounter,' +
226           'context:"row",pause:100)',
227       'self::mathml:mtable');
229   defineRule(
230       'mtr', 'default.default',
231       '[m] ./* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)',
232       'self::mathml:mtr');
234   defineRule(
235       'mtd', 'default.default',
236       '[m] ./*', 'self::mathml:mtd');
238   // Mtable superbrief rules.
239   defineRule(
240       'mtable', 'default.superbrief',
241       '[t] count(child::mathml:mtr);  [t] "by";' +
242           '[t] count(child::mathml:mtr[1]/mathml:mtd); [t] "matrix";',
243       'self::mathml:mtable');
245   // Mtable short rules.
246   defineRule(
247       'mtable', 'default.short',
248       '[t] "matrix"; [m] ./*',
249       'self::mathml:mtable');
251   defineRule(
252       'mtr', 'default.short',
253       '[m] ./*', 'self::mathml:mtr');
255   defineRule(
256       'mtd', 'default.short',
257       '[t] "Element"; [t] count(./preceding-sibling::mathml:mtd)+1;' +
258           '[t] count(./parent::mathml:mtr/preceding-sibling::mathml:mtr)+1;' +
259               '[p] (pause:500); [m] ./*',
260       'self::mathml:mtd');
262   // Mmultiscripts rules.
263   defineRule(
264       'mmultiscripts-4', 'default.default',
265       '[n] ./*[1]; [p] (pause:200);' +
266       '[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);' +
267       '[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:200);' +
268       '[t] "right sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);' +
269       '[t] "right super"; [n] ./*[3] (pitch:0.35); [p] (pause:300);',
270       'self::mathml:mmultiscripts');
271   defineRule(
272       'mmultiscripts-3-1', 'default.default',
273       '[n] ./*[1]; [p] (pause:200);' +
274       '[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);' +
275       '[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:200);' +
276       '[t] "right super"; [n] ./*[3] (pitch:0.35); [p] (pause:300);',
277       'self::mathml:mmultiscripts', './mathml:none=./*[2]',
278       './mathml:mprescripts=./*[4]');
279   defineRule(
280       'mmultiscripts-3-2', 'default.default',
281       '[n] ./*[1]; [p] (pause:200);' +
282       '[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);' +
283       '[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:200);' +
284       '[t] "right sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);',
285       'self::mathml:mmultiscripts', './mathml:none=./*[3]',
286       './mathml:mprescripts=./*[4]');
287   defineRule(
288       'mmultiscripts-3-3', 'default.default',
289       '[n] ./*[1]; [p] (pause:200);' +
290       '[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:200);' +
291       '[t] "right sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);' +
292       '[t] "right super"; [n] ./*[3] (pitch:0.35); [p] (pause:300);',
293       'self::mathml:mmultiscripts', './mathml:none=./*[5]',
294       './mathml:mprescripts=./*[4]');
295   defineRule(
296       'mmultiscripts-3-4', 'default.default',
297       '[n] ./*[1]; [p] (pause:200);' +
298       '[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);' +
299       '[t] "right sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);' +
300       '[t] "right super"; [n] ./*[3] (pitch:0.35); [p] (pause:300);',
301       'self::mathml:mmultiscripts', './mathml:none=./*[6]',
302       './mathml:mprescripts=./*[4]');
303   defineRule(
304       'mmultiscripts-2-1', 'default.default',
305       '[n] ./*[1]; [p] (pause:200);' +
306       '[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);' +
307       '[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:300);',
308       'self::mathml:mmultiscripts', './mathml:none=./*[2]',
309       './mathml:none=./*[3]', './mathml:mprescripts=./*[4]');
310   defineRule(
311       'mmultiscripts-1-1', 'default.default',
312       '[n] ./*[1]; [p] (pause:200);' +
313       '[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:300);',
314       'self::mathml:mmultiscripts', './mathml:none=./*[2]',
315       './mathml:none=./*[3]', './mathml:mprescripts=./*[4]',
316       './mathml:none=./*[5]');
317   defineRule(
318       'mmultiscripts-1-2', 'default.default',
319       '[n] ./*[1]; [p] (pause:200);' +
320       '[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);',
321       'self::mathml:mmultiscripts', './mathml:none=./*[2]',
322       './mathml:none=./*[3]', './mathml:mprescripts=./*[4]',
323       './mathml:none=./*[6]');
328  * Initialize mathJax Rules
329  * @private
330  */
331 cvox.MathmlStoreRules.initMathjaxRules_ = function() {
332   // Initial rule
333   defineRule('mj-math', 'default.default',
334              '[n] ./*[1]/*[1]/*[1]', 'self::span[@class="math"]');
336   // Token Elements
337   defineRule(
338       'mj-leaf', 'default.default',
339       '[n] CQFlookupleaf', 'self::span[@class="mi"]');
340   defineRuleAlias('mj-leaf', 'self::span[@class="mo"]');
341   defineRuleAlias('mj-leaf', 'self::span[@class="mn"]');
342   defineRuleAlias('mj-leaf', 'self::span[@class="mtext"]');
343   defineRule(
344       'mj-mo-ext', 'default.default',
345       '[n] CQFextender', 'self::span[@class="mo"]',
346       './*[1]/*[1]/text()', './*[1]/*[2]/text()');
347   defineRule(
348       'mj-texatom', 'default.default',
349       '[n] ./*[1]', 'self::span[@class="texatom"]');
351   // Script elements.
352   defineRule(
353       'mj-msubsup', 'default.default',
354       '[n] ./*[1]/*[1]/*[1]; [t] "sub"; [n] ./*[1]/*[3]/*[1] (pitch:-0.35);' +
355       '[p] (pause:200); [t] "super"; [n] ./*[1]/*[2]/*[1] (pitch:0.35);' +
356       '[p] (pause:300)',
357       'self::span[@class="msubsup"]');
358   defineRule(
359       'mj-msub', 'default.default',
360       '[n] ./*[1]/*[1]/*[1]; [t] "sub";' +
361           '[n] ./*[1]/*[2]/*[1] (pitch:-0.35); [p] (pause:300)',
362       'self::span[@class="msub"]');
363   defineRule(
364       'mj-msup', 'default.default',
365       '[n] ./*[1]/*[1]/*[1]; [t] "super";' +
366           '[n] ./*[1]/*[2]/*[1] (pitch:0.35); [p] (pause:300)',
367       'self::span[@class="msup"]');
368   defineRule(
369       'mj-munderover', 'default.default',
370       '[n] ./*[1]/*[2]/*[1] (pitch:0.35); [t] "under and";' +
371           '[n] ./*[1]/*[3]/*[1] (pitch:-0.35); [t] "over";' +
372               '[n] ./*[1]/*[1]/*[1]; [p] (pause:400)',
373       'self::span[@class="munderover"]');
374   defineRule(
375       'mj-munder', 'default.default',
376       '[n] ./*[1]/*[2]/*[1] (pitch:0.35); [t] "under";' +
377           '[n] ./*[1]/*[1]/*[1]; [p] (pause:400)',
378       'self::span[@class="munder"]');
379   defineRule(
380       'mj-mover', 'default.default',
381       '[n] ./*[1]/*[2]/*[1] (pitch:0.35); [t] "over";' +
382           '[n] ./*[1]/*[1]/*[1]; [p] (pause:400)',
383       'self::span[@class="mover"]');
386   // Layout elements.
387   defineRule(
388       'mj-mfrac', 'default.default',
389       '[p] (pause:250); [n] ./*[1]/*[1]/*[1] (pitch:0.3); [p] (pause:250);' +
390           ' [t] "divided by"; [n] ./*[1]/*[2]/*[1] (pitch:-0.3);' +
391               '[p] (pause:400)',
392       'self::span[@class="mfrac"]');
393   defineRule(
394       'mj-msqrt', 'default.default',
395       '[t] "Square root of";' +
396           '[n] ./*[1]/*[1]/*[1] (rate:0.2); [p] (pause:400)',
397       'self::span[@class="msqrt"]');
398   defineRule(
399       'mj-mroot', 'default.default',
400       '[t] "root of order"; [n] ./*[1]/*[4]/*[1]; [t] "of";' +
401           '[n] ./*[1]/*[1]/*[1] (rate:0.2); [p] (pause:400)',
402       'self::span[@class="mroot"]');
404   defineRule(
405       'mj-mfenced', 'default.default',
406       '[t] "opening"; [n] ./*[1]; ' +
407           '[m] ./*[position()>1 and position()<last()];' +
408               ' [t] "closing"; [n] ./*[last()]',
409       'self::span[@class="mfenced"]');
411   // Mtable short rules.
412   defineRuleAlias('mj-leaf', 'self::span[@class="mtable"]');
413   // Mmultiscripts rules.
414   defineRuleAlias('mj-leaf', 'self::span[@class="mmultiscripts"]');
419  * Initialize mathJax Aliases
420  * @private
421  */
422 cvox.MathmlStoreRules.initAliases_ = function() {
423   // Space elements
424   defineRuleAlias('mspace', 'self::span[@class="mspace"]');
425   defineRuleAlias('mstyle', 'self::span[@class="mstyle"]');
426   defineRuleAlias('mpadded', 'self::span[@class="mpadded"]');
427   defineRuleAlias('merror', 'self::span[@class="merror"]');
428   defineRuleAlias('mphantom', 'self::span[@class="mphantom"]');
430   // Token elements.
431   defineRuleAlias('ms', 'self::span[@class="ms"]');
433   // Layout elements.
434   defineRuleAlias('mrow', 'self::span[@class="mrow"]');
436   // The following rules fix bugs in MathJax's LaTeX translation.
437   defineRuleAlias(
438       'mj-msub', 'self::span[@class="msubsup"]', 'CQFmathmlmsub');
440   defineRuleAlias(
441       'mj-msup', 'self::span[@class="msubsup"]', 'CQFmathmlmsup');
443   defineRuleAlias(
444       'mj-munder', 'self::span[@class="munderover"]', 'CQFmathmlmunder');
446   defineRuleAlias(
447       'mj-mover', 'self::span[@class="munderover"]', 'CQFmathmlmover');
452  * Initialize specializations wrt. content of nodes.
453  * @private
454  */
455 cvox.MathmlStoreRules.initSpecializationRules_ = function() {
456   // Some special nodes for square and cube.
457   // MathML
458   defineRule(
459       'square', 'default.default',
460       '[n] ./*[1]; [t] "square" (pitch:0.35); [p] (pause:300)',
461       'self::mathml:msup', './*[2][text()=2]');
462   defineRuleAlias(
463       'square', 'self::mathml:msup',
464       './mathml:mrow=./*[2]', 'count(./*[2]/*)=1', './*[2]/*[1][text()=2]');
466   defineRule(
467       'cube', 'default.default',
468       '[n] ./*[1]; [t] "cube" (pitch:0.35); [p] (pause:300)',
469       'self::mathml:msup', './*[2][text()=3]');
470   defineRuleAlias(
471       'cube', 'self::mathml:msup',
472       './mathml:mrow=./*[2]', 'count(./*[2]/*)=1', './*[2]/*[1][text()=3]');
474   defineRule(
475       'square-sub', 'default.default',
476       '[n] ./*[1]; [t] "sub"; [n] ./*[2] (pitch:-0.35);' +
477           '[p] (pause:300); [t] "square" (pitch:0.35); [p] (pause:400)',
478       'self::mathml:msubsup', './*[3][text()=2]');
479   defineRuleAlias(
480       'square-sub', 'self::mathml:msubsup',
481       './mathml:mrow=./*[3]', 'count(./*[3]/*)=1', './*[3]/*[1][text()=2]');
483   defineRule(
484       'cube-sub', 'default.default',
485       '[n] ./*[1]; [t] "sub"; [n] ./*[2] (pitch:-0.35);' +
486           '[p] (pause:300); [t] "cube" (pitch:0.35); [p] (pause:400)',
487       'self::mathml:msubsup', './*[3][text()=3]');
488   defineRuleAlias(
489       'cube-sub', 'self::mathml:msubsup',
490       './mathml:mrow=./*[3]', 'count(./*[3]/*)=1', './*[3]/*[1][text()=3]');
492   // MathJax
493   defineRule(
494       'mj-square', 'default.default',
495       '[n] ./*[1]/*[1]/*[1]; [t] "square" (pitch:0.35); [p] (pause:300)',
496       'self::span[@class="msup"]', './*[1]/*[2]/*[1][text()=2]');
497   defineRuleAlias(
498       'mj-square', 'self::span[@class="msup"]',
499       './*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]',
500       'count(./*[1]/*[2]/*[1]/*)=1', './*[1]/*[2]/*[1]/*[1][text()=2]');
501   defineRuleAlias(
502       'mj-square', 'self::span[@class="msubsup"]', 'CQFmathmlmsup',
503       './*[1]/*[2]/*[1][text()=2]');
504   defineRuleAlias(
505       'mj-square', 'self::span[@class="msubsup"]', 'CQFmathmlmsup',
506       './*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]',
507       'count(./*[1]/*[2]/*[1]/*)=1', './*[1]/*[2]/*[1]/*[1][text()=2]');
509   defineRule(
510       'mj-cube', 'default.default',
511       '[n] ./*[1]/*[1]/*[1]; [t] "cube" (pitch:0.35); [p] (pause:300)',
512       'self::span[@class="msup"]', './*[1]/*[2]/*[1][text()=3]');
513   defineRuleAlias(
514       'mj-cube', 'self::span[@class="msup"]',
515       './*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]',
516       'count(./*[1]/*[2]/*[1]/*)=1', './*[1]/*[2]/*[1]/*[1][text()=3]');
517   defineRuleAlias(
518       'mj-cube', 'self::span[@class="msubsup"]', 'CQFmathmlmsup',
519       './*[1]/*[2]/*[1][text()=3]');
520   defineRuleAlias(
521       'mj-cube', 'self::span[@class="msubsup"]', 'CQFmathmlmsup',
522       './*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]',
523       'count(./*[1]/*[2]/*[1]/*)=1', './*[1]/*[2]/*[1]/*[1][text()=3]');
525   defineRule(
526       'mj-square-sub', 'default.default',
527       '[n] ./*[1]/*[1]/*[1]; [t] "sub"; [n] ./*[1]/*[3]/*[1] (pitch:-0.35); ' +
528           '[p] (pause:300); [t] "square" (pitch:0.35); [p] (pause:400)',
529       'self::span[@class="msubsup"]', './*[1]/*[2]/*[1][text()=2]');
530   defineRuleAlias(
531       'mj-square-sub', 'self::span[@class="msubsup"]',
532       './*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]',
533       'count(./*[1]/*[2]/*[1]/*)=1', './*[1]/*[2]/*[1]/*[1][text()=2]');
535   defineRule(
536       'mj-cube-sub', 'default.default',
537       '[n] ./*[1]/*[1]/*[1]; [t] "sub"; [n] ./*[1]/*[3]/*[1] (pitch:-0.35); ' +
538           '[p] (pause:300); [t] "cube" (pitch:0.35); [p] (pause:400)',
539       'self::span[@class="msubsup"]', './*[1]/*[2]/*[1][text()=3]');
540   defineRuleAlias(
541       'mj-cube-sub', 'self::span[@class="msubsup"]',
542       './*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]',
543       'count(./*[1]/*[2]/*[1]/*)=1', './*[1]/*[2]/*[1]/*[1][text()=3]');
548  * Initialize mathJax Aliases
549  * @private
550  */
551 cvox.MathmlStoreRules.initSemanticRules_ = function() {
552   // Initial rule
553   defineRule(
554       'stree', 'default.default',
555       '[n] ./*[1]', 'self::stree');
557   defineRule(
558       'multrel', 'default.default',
559       '[t] "multirelation"; [m] children/* (sepFunc:CTXFcontentIterator)',
560       'self::multirel');
562   defineRule(
563       'variable-equality', 'default.default',
564       '[t] "equation sequence"; [m] ./children/* ' +
565           '(context:"part",ctxtFunc:CTXFnodeCounter,separator:./text())',
566       'self::relseq[@role="equality"]', 'count(./children/*)>2',
567       './children/punct[@role="ellipsis"]');// Make that better!
569   defineRule(
570       'multi-equality', 'default.default',
571       '[t] "equation sequence"; [m] ./children/* ' +
572           '(context:"part",ctxtFunc:CTXFnodeCounter,separator:./text())',
573       'self::relseq[@role="equality"]', 'count(./children/*)>2');
575   defineRule(
576       'multi-equality', 'default.short',
577       '[t] "equation sequence"; [m] ./children/* ' +
578           '(separator:./text())',
579       'self::relseq[@role="equality"]', 'count(./children/*)>2');
581   defineRule(
582       'equality', 'default.default',
583       '[t] "equation"; [t] "left hand side"; [n] children/*[1];' +
584           '[p] (pause:200); [n] text() (pause:200);' +
585           '[t] "right hand side"; [n] children/*[2]',
586       'self::relseq[@role="equality"]', 'count(./children/*)=2');
588   defineRule(
589       'simple-equality', 'default.default',
590       '[n] children/*[1]; [p] (pause:200); [n] text() (pause:200);' +
591           '[n] children/*[2]',
592       'self::relseq[@role="equality"]', 'count(./children/*)=2',
593       './children/identifier or ./children/number');
595   defineRule(
596       'simple-equality2', 'default.default',
597       '[n] children/*[1]; [p] (pause:200); [n] text() (pause:200);' +
598           '[n] children/*[2]',
599       'self::relseq[@role="equality"]', 'count(./children/*)=2',
600       './children/function or ./children/appl');
602   defineRule(
603       'multrel', 'default.default',
604       '[m] children/* (separator:./text())',
605       'self::relseq');
607   defineRule(
608       'binary-operation', 'default.default',
609       '[m] children/* (separator:text());',
610       'self::infixop');
612   defineRule(
613       'variable-addition', 'default.default',
614       '[t] "sum with variable number of summands";' +
615           '[p] (pause:400); [m] children/* (separator:./text())',
616       'self::infixop[@role="addition"]', 'count(children/*)>2',
617       'children/punct[@role="ellipsis"]');// Make that better!
619   defineRule(
620       'multi-addition', 'default.default',
621       '[t] "sum with,"; [t] count(./children/*); [t] ", summands";' +
622           '[p] (pause:400); [m] ./children/* (separator:./text())',
623       'self::infixop[@role="addition"]', 'count(./children/*)>2');
625   // Prefix Operator
626   defineRule(
627       'prefix', 'default.default',
628       '[t] "prefix"; [n] text(); [t] "of" (pause 150);' +
629       '[n] children/*[1]',
630       'self::prefixop');
632   defineRule(
633       'negative', 'default.default',
634       '[t] "negative"; [n] children/*[1]',
635       'self::prefixop', 'self::prefixop[@role="negative"]');
637   // Postfix Operator
638   defineRule(
639       'postfix', 'default.default',
640       '[n] children/*[1]; [t] "postfix"; [n] text() (pause 300)',
641       'self::postfixop');
643   defineRule(
644       'identifier', 'default.default',
645       '[n] text()', 'self::identifier');
647   defineRule(
648       'number', 'default.default',
649       '[n] text()', 'self::number');
651   defineRule(
652       'fraction', 'default.default',
653       '[p] (pause:250); [n] children/*[1] (pitch:0.3); [p] (pause:250);' +
654           ' [t] "divided by"; [n] children/*[2] (pitch:-0.3); [p] (pause:400)',
655       'self::fraction');
657   defineRule(
658       'superscript', 'default.default',
659       '[n] children/*[1]; [t] "super"; [n] children/*[2] (pitch:0.35);' +
660       '[p] (pause:300)',
661       'self::superscript');
662   defineRule(
663       'subscript', 'default.default',
664       '[n] children/*[1]; [t] "sub"; [n] children/*[2] (pitch:-0.35);' +
665       '[p] (pause:300)',
666       'self::subscript');
668   defineRule(
669       'ellipsis', 'default.default',
670       '[p] (pause:200); [t] "dot dot dot"; [p] (pause:300)',
671       'self::punct', 'self::punct[@role="ellipsis"]');
673   defineRule(
674       'fence-single', 'default.default',
675       '[n] text()',
676       'self::punct', 'self::punct[@role="openfence"]');
677   defineRuleAlias('fence-single', 'self::punct',
678                   'self::punct[@role="closefence"]');
679   defineRuleAlias('fence-single', 'self::punct',
680                   'self::punct[@role="vbar"]');
681   defineRuleAlias('fence-single', 'self::punct',
682                   'self::punct[@role="application"]');
684   // TODO (sorge) Refine punctuations further.
685   defineRule(
686       'omit-punct', 'default.default',
687       '[p] (pause:200);',
688       'self::punct');
690   defineRule(
691       'omit-empty', 'default.default',
692       '',
693       'self::empty');
695   // Fences rules.
696   defineRule(
697       'fences-open-close', 'default.default',
698       '[p] (pause:100); [t] "open"; [n] children/*[1]; [p] (pause:200);' +
699       '[t] "close"',
700       'self::fenced[@role="leftright"]');
702   defineRule(
703       'fences-open-close-in-appl', 'default.default',
704       '[p] (pause:100); [n] children/*[1]; [p] (pause:200);',
705       'self::fenced[@role="leftright"]', './parent::children/parent::appl');
707   defineRule(
708       'fences-neutral', 'default.default',
709       '[p] (pause:100); [t] "absolute value of"; [n] children/*[1];' +
710       '[p] (pause:350);',
711       'self::fenced', 'self::fenced[@role="neutral"]');
713   defineRule(
714       'omit-fences', 'default.default',
715       '[p] (pause:500); [n] children/*[1]; [p] (pause:200);',
716       'self::fenced');
718   // Matrix rules.
719   defineRule(
720       'matrix', 'default.default',
721       '[t] "matrix"; [m] children/* ' +
722       '(ctxtFunc:CTXFnodeCounter,context:"row",pause:100)',
723       'self::matrix');
725   defineRule(
726       'matrix-row', 'default.default',
727       '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)',
728       'self::row[@role="matrix"]');
730   defineRule(
731       'matrix-cell', 'default.default',
732       '[n] children/*[1]', 'self::cell[@role="matrix"]');
734   // Vector rules.
735   defineRule(
736       'vector', 'default.default',
737       '[t] "vector"; [m] children/* ' +
738       '(ctxtFunc:CTXFnodeCounter,context:"element",pause:100)',
739       'self::vector');
741   // Cases rules.
742   defineRule(
743       'cases', 'default.default',
744       '[t] "case statement"; [m] children/* ' +
745       '(ctxtFunc:CTXFnodeCounter,context:"case",pause:100)',
746       'self::cases');
748   defineRule(
749       'cases-row', 'default.default',
750       '[m] children/*', 'self::row[@role="cases"]');
752   defineRule(
753       'cases-cell', 'default.default',
754       '[n] children/*[1]', 'self::cell[@role="cases"]');
756   defineRule(
757       'row', 'default.default',
758       '[m] ./* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)',
759       'self::row"');
761   defineRule(
762       'cases-end', 'default.default',
763       '[t] "case statement"; ' +
764       '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"case",pause:100);' +
765       '[t] "end cases"',
766       'self::cases', 'following-sibling::*');
768   // Multiline rules.
769   defineRule(
770       'multiline', 'default.default',
771       '[t] "multiline equation";' +
772       '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"line",pause:100)',
773       'self::multiline');
775   defineRule(
776       'line', 'default.default',
777       '[m] children/*', 'self::line');
779   // Table rules.
780   defineRule(
781       'table', 'default.default',
782       '[t] "multiline equation";' +
783       '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"row",pause:200)',
784       'self::table');
786   defineRule(
787       'table-row', 'default.default',
788       '[m] children/* (pause:100)', 'self::row[@role="table"]');
790   defineRuleAlias(
791       'cases-cell', 'self::cell[@role="table"]');
794   // Rules for punctuated expressions.
795   defineRule(
796       'end-punct', 'default.default',
797       '[m] children/*; [p] (pause:300)',
798       'self::punctuated', '@role="endpunct"');
800   defineRule(
801       'start-punct', 'default.default',
802       '[n] content/*[1]; [p] (pause:200); [m] children/*',
803       'self::punctuated', '@role="startpunct"');
805   defineRule(
806       'integral-punct', 'default.default',
807       '[n] children/*[1] (rate:0.2); [n] children/*[3] (rate:0.2)',
808       'self::punctuated', '@role="integral"');
810   defineRule(
811       'punctuated', 'default.default',
812       '[m] children/* (pause:100)',
813       'self::punctuated');
815   // Function rules
816   defineRule(
817     'function', 'default.default',
818     '[n] text()', 'self::function');
820   defineRule(
821     'appl', 'default.default',
822     '[n] children/*[1]; [n] content/*[1]; [n] children/*[2]', 'self::appl');
824   // Limit operator rules
825   defineRule(
826     'limboth', 'default.default',
827     '[n] children/*[1]; [t] "from"; [n] children/*[2]; [t] "to";' +
828     '[n] children/*[3]', 'self::limboth');
830   defineRule(
831     'sum-only', 'default.default',
832     '[n] children/*[1]; [p] (pause 100); [t] "over"; [n] children/*[2];' +
833     '[p] (pause 250);',
834     'self::limboth', 'self::limboth[@role="sum"]');
836   defineRule(
837     'limlower', 'default.default',
838     '[n] children/*[1]; [t] "over"; [n] children/*[2];', 'self::limlower');
840   defineRule(
841     'limupper', 'default.default',
842     '[n] children/*[1]; [t] "under"; [n] children/*[2];', 'self::limupper');
844   // Bigoperator rules
845   defineRule(
846     'largeop', 'default.default',
847     '[n] text()', 'self::largeop');
849   defineRule(
850     'bigop', 'default.default',
851     '[n] children/*[1]; [p] (pause 100); [t] "over"; [n] children/*[2];' +
852     '[p] (pause 250);',
853     'self::bigop');
856   // Integral rules
857   defineRule(
858     'integral', 'default.default',
859     '[n] children/*[1]; [p] (pause 100); [n] children/*[2]; [p] (pause 200);' +
860     '[n] children/*[3] (rate:0.35);', 'self::integral');
863   defineRule(
864       'sqrt', 'default.default',
865       '[t] "Square root of"; [n] children/*[1] (rate:0.2); [p] (pause:400)',
866       'self::sqrt');
868   defineRule(
869       'square', 'default.default',
870       '[n] children/*[1]; [t] "square" (pitch:0.35); [p] (pause:300)',
871       'self::superscript', 'children/*[2][text()=2]');
873   defineRule(
874       'text-no-mult', 'default.default',
875       '[n] children/*[1]; [p] (pause:200); [n] children/*[2]',
876       'self::infixop', 'children/text');
879 }); // goog.scope