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.
6 * @fileoverview Speech rules for mathml and mathjax nodes.
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');
18 * Rule initialization.
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);
34 * @type {cvox.MathStore}
36 cvox.MathmlStoreRules.mathStore = cvox.MathmlStore.getInstance();
40 cvox.MathmlStoreRules.mathStore.initialize = cvox.MathmlStoreRules.getInstance;
42 // These are used to work around Closure's rules for aliasing.
44 cvox.MathmlStoreRules.defineDefaultMathmlRule_ = goog.bind(
45 cvox.MathmlStoreRules.mathStore.defineDefaultMathmlRule,
46 cvox.MathmlStoreRules.mathStore);
48 cvox.MathmlStoreRules.defineRule_ = goog.bind(
49 cvox.MathmlStoreRules.mathStore.defineRule,
50 cvox.MathmlStoreRules.mathStore);
52 cvox.MathmlStoreRules.defineRuleAlias_ = goog.bind(
53 cvox.MathmlStoreRules.mathStore.defineRuleAlias,
54 cvox.MathmlStoreRules.mathStore);
56 cvox.MathmlStoreRules.addContextFunction_ = goog.bind(
57 cvox.MathmlStoreRules.mathStore.contextFunctions.add,
58 cvox.MathmlStoreRules.mathStore.contextFunctions);
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_;
73 * Initialize the custom functions.
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);
92 * Initialize the default mathrules.
95 cvox.MathmlStoreRules.initDefaultRules_ = function() {
97 defineDefaultMathmlRule('math', '[m] ./*');
98 defineDefaultMathmlRule('semantics', '[n] ./*[1]');
101 defineDefaultMathmlRule('mspace', '[p] (pause:250)');
102 defineDefaultMathmlRule('mstyle', '[m] ./*');
103 defineDefaultMathmlRule('mpadded', '[m] ./*');
104 defineDefaultMathmlRule('merror', '[t] ""');
105 defineDefaultMathmlRule('mphantom', '[t] ""');
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(
133 '[t] "string" (pitch:0.5, rate:0.5); [t] text()');
136 defineDefaultMathmlRule(
137 'msup', '[n] ./*[1]; [t] "super";' +
138 '[n] ./*[2] (pitch:0.35); [p] (pause:300)');
139 defineDefaultMathmlRule(
141 '[n] ./*[1]; [t] "sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);' +
142 '[t] "super"; [n] ./*[3] (pitch:0.35); [p] (pause:300)'
144 defineDefaultMathmlRule(
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(
152 '[n] ./*[2] (pitch:-0.35); [t] "under"; [n] ./*[1]; [p] (pause:400)');
153 defineDefaultMathmlRule(
155 '[n] ./*[2] (pitch:-0.35); [t] "under and"; [n] ./*[3] (pitch:0.35);' +
156 ' [t] "over"; [n] ./*[1]; [p] (pause:400)');
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)');
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');
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');
185 'mfenced-omit', 'default.default',
186 '[t] concat(substring(@open, 0 div boolean(@open)), ' +
187 'substring("(", 0 div not(boolean(@open)))) (context:"opening"); ' +
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)=""');
195 'mfenced-empty', 'default.default',
196 '[t] concat(substring(@open, 0 div boolean(@open)), ' +
197 'substring("(", 0 div not(boolean(@open)))) (context:"opening"); ' +
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)=" "');
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');
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');
224 'mtable', 'default.default',
225 '[t] "matrix"; [m] ./* (ctxtFunc:CTXFnodeCounter,' +
226 'context:"row",pause:100)',
227 'self::mathml:mtable');
230 'mtr', 'default.default',
231 '[m] ./* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)',
235 'mtd', 'default.default',
236 '[m] ./*', 'self::mathml:mtd');
238 // Mtable superbrief rules.
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.
247 'mtable', 'default.short',
248 '[t] "matrix"; [m] ./*',
249 'self::mathml:mtable');
252 'mtr', 'default.short',
253 '[m] ./*', 'self::mathml:mtr');
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] ./*',
262 // Mmultiscripts rules.
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');
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]');
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]');
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]');
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]');
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]');
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]');
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
331 cvox.MathmlStoreRules.initMathjaxRules_ = function() {
333 defineRule('mj-math', 'default.default',
334 '[n] ./*[1]/*[1]/*[1]', 'self::span[@class="math"]');
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"]');
344 'mj-mo-ext', 'default.default',
345 '[n] CQFextender', 'self::span[@class="mo"]',
346 './*[1]/*[1]/text()', './*[1]/*[2]/text()');
348 'mj-texatom', 'default.default',
349 '[n] ./*[1]', 'self::span[@class="texatom"]');
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);' +
357 'self::span[@class="msubsup"]');
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"]');
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"]');
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"]');
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"]');
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"]');
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);' +
392 'self::span[@class="mfrac"]');
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"]');
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"]');
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
422 cvox.MathmlStoreRules.initAliases_ = function() {
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"]');
431 defineRuleAlias('ms', 'self::span[@class="ms"]');
434 defineRuleAlias('mrow', 'self::span[@class="mrow"]');
436 // The following rules fix bugs in MathJax's LaTeX translation.
438 'mj-msub', 'self::span[@class="msubsup"]', 'CQFmathmlmsub');
441 'mj-msup', 'self::span[@class="msubsup"]', 'CQFmathmlmsup');
444 'mj-munder', 'self::span[@class="munderover"]', 'CQFmathmlmunder');
447 'mj-mover', 'self::span[@class="munderover"]', 'CQFmathmlmover');
452 * Initialize specializations wrt. content of nodes.
455 cvox.MathmlStoreRules.initSpecializationRules_ = function() {
456 // Some special nodes for square and cube.
459 'square', 'default.default',
460 '[n] ./*[1]; [t] "square" (pitch:0.35); [p] (pause:300)',
461 'self::mathml:msup', './*[2][text()=2]');
463 'square', 'self::mathml:msup',
464 './mathml:mrow=./*[2]', 'count(./*[2]/*)=1', './*[2]/*[1][text()=2]');
467 'cube', 'default.default',
468 '[n] ./*[1]; [t] "cube" (pitch:0.35); [p] (pause:300)',
469 'self::mathml:msup', './*[2][text()=3]');
471 'cube', 'self::mathml:msup',
472 './mathml:mrow=./*[2]', 'count(./*[2]/*)=1', './*[2]/*[1][text()=3]');
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]');
480 'square-sub', 'self::mathml:msubsup',
481 './mathml:mrow=./*[3]', 'count(./*[3]/*)=1', './*[3]/*[1][text()=2]');
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]');
489 'cube-sub', 'self::mathml:msubsup',
490 './mathml:mrow=./*[3]', 'count(./*[3]/*)=1', './*[3]/*[1][text()=3]');
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]');
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]');
502 'mj-square', 'self::span[@class="msubsup"]', 'CQFmathmlmsup',
503 './*[1]/*[2]/*[1][text()=2]');
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]');
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]');
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]');
518 'mj-cube', 'self::span[@class="msubsup"]', 'CQFmathmlmsup',
519 './*[1]/*[2]/*[1][text()=3]');
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]');
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]');
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]');
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]');
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
551 cvox.MathmlStoreRules.initSemanticRules_ = function() {
554 'stree', 'default.default',
555 '[n] ./*[1]', 'self::stree');
558 'multrel', 'default.default',
559 '[t] "multirelation"; [m] children/* (sepFunc:CTXFcontentIterator)',
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!
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');
576 'multi-equality', 'default.short',
577 '[t] "equation sequence"; [m] ./children/* ' +
578 '(separator:./text())',
579 'self::relseq[@role="equality"]', 'count(./children/*)>2');
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');
589 'simple-equality', 'default.default',
590 '[n] children/*[1]; [p] (pause:200); [n] text() (pause:200);' +
592 'self::relseq[@role="equality"]', 'count(./children/*)=2',
593 './children/identifier or ./children/number');
596 'simple-equality2', 'default.default',
597 '[n] children/*[1]; [p] (pause:200); [n] text() (pause:200);' +
599 'self::relseq[@role="equality"]', 'count(./children/*)=2',
600 './children/function or ./children/appl');
603 'multrel', 'default.default',
604 '[m] children/* (separator:./text())',
608 'binary-operation', 'default.default',
609 '[m] children/* (separator:text());',
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!
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');
627 'prefix', 'default.default',
628 '[t] "prefix"; [n] text(); [t] "of" (pause 150);' +
633 'negative', 'default.default',
634 '[t] "negative"; [n] children/*[1]',
635 'self::prefixop', 'self::prefixop[@role="negative"]');
639 'postfix', 'default.default',
640 '[n] children/*[1]; [t] "postfix"; [n] text() (pause 300)',
644 'identifier', 'default.default',
645 '[n] text()', 'self::identifier');
648 'number', 'default.default',
649 '[n] text()', 'self::number');
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)',
658 'superscript', 'default.default',
659 '[n] children/*[1]; [t] "super"; [n] children/*[2] (pitch:0.35);' +
661 'self::superscript');
663 'subscript', 'default.default',
664 '[n] children/*[1]; [t] "sub"; [n] children/*[2] (pitch:-0.35);' +
669 'ellipsis', 'default.default',
670 '[p] (pause:200); [t] "dot dot dot"; [p] (pause:300)',
671 'self::punct', 'self::punct[@role="ellipsis"]');
674 'fence-single', 'default.default',
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.
686 'omit-punct', 'default.default',
691 'omit-empty', 'default.default',
697 'fences-open-close', 'default.default',
698 '[p] (pause:100); [t] "open"; [n] children/*[1]; [p] (pause:200);' +
700 'self::fenced[@role="leftright"]');
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');
708 'fences-neutral', 'default.default',
709 '[p] (pause:100); [t] "absolute value of"; [n] children/*[1];' +
711 'self::fenced', 'self::fenced[@role="neutral"]');
714 'omit-fences', 'default.default',
715 '[p] (pause:500); [n] children/*[1]; [p] (pause:200);',
720 'matrix', 'default.default',
721 '[t] "matrix"; [m] children/* ' +
722 '(ctxtFunc:CTXFnodeCounter,context:"row",pause:100)',
726 'matrix-row', 'default.default',
727 '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)',
728 'self::row[@role="matrix"]');
731 'matrix-cell', 'default.default',
732 '[n] children/*[1]', 'self::cell[@role="matrix"]');
736 'vector', 'default.default',
737 '[t] "vector"; [m] children/* ' +
738 '(ctxtFunc:CTXFnodeCounter,context:"element",pause:100)',
743 'cases', 'default.default',
744 '[t] "case statement"; [m] children/* ' +
745 '(ctxtFunc:CTXFnodeCounter,context:"case",pause:100)',
749 'cases-row', 'default.default',
750 '[m] children/*', 'self::row[@role="cases"]');
753 'cases-cell', 'default.default',
754 '[n] children/*[1]', 'self::cell[@role="cases"]');
757 'row', 'default.default',
758 '[m] ./* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)',
762 'cases-end', 'default.default',
763 '[t] "case statement"; ' +
764 '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"case",pause:100);' +
766 'self::cases', 'following-sibling::*');
770 'multiline', 'default.default',
771 '[t] "multiline equation";' +
772 '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"line",pause:100)',
776 'line', 'default.default',
777 '[m] children/*', 'self::line');
781 'table', 'default.default',
782 '[t] "multiline equation";' +
783 '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"row",pause:200)',
787 'table-row', 'default.default',
788 '[m] children/* (pause:100)', 'self::row[@role="table"]');
791 'cases-cell', 'self::cell[@role="table"]');
794 // Rules for punctuated expressions.
796 'end-punct', 'default.default',
797 '[m] children/*; [p] (pause:300)',
798 'self::punctuated', '@role="endpunct"');
801 'start-punct', 'default.default',
802 '[n] content/*[1]; [p] (pause:200); [m] children/*',
803 'self::punctuated', '@role="startpunct"');
806 'integral-punct', 'default.default',
807 '[n] children/*[1] (rate:0.2); [n] children/*[3] (rate:0.2)',
808 'self::punctuated', '@role="integral"');
811 'punctuated', 'default.default',
812 '[m] children/* (pause:100)',
817 'function', 'default.default',
818 '[n] text()', 'self::function');
821 'appl', 'default.default',
822 '[n] children/*[1]; [n] content/*[1]; [n] children/*[2]', 'self::appl');
824 // Limit operator rules
826 'limboth', 'default.default',
827 '[n] children/*[1]; [t] "from"; [n] children/*[2]; [t] "to";' +
828 '[n] children/*[3]', 'self::limboth');
831 'sum-only', 'default.default',
832 '[n] children/*[1]; [p] (pause 100); [t] "over"; [n] children/*[2];' +
834 'self::limboth', 'self::limboth[@role="sum"]');
837 'limlower', 'default.default',
838 '[n] children/*[1]; [t] "over"; [n] children/*[2];', 'self::limlower');
841 'limupper', 'default.default',
842 '[n] children/*[1]; [t] "under"; [n] children/*[2];', 'self::limupper');
846 'largeop', 'default.default',
847 '[n] text()', 'self::largeop');
850 'bigop', 'default.default',
851 '[n] children/*[1]; [p] (pause 100); [t] "over"; [n] children/*[2];' +
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');
864 'sqrt', 'default.default',
865 '[t] "Square root of"; [n] children/*[1] (rate:0.2); [p] (pause:400)',
869 'square', 'default.default',
870 '[n] children/*[1]; [t] "square" (pitch:0.35); [p] (pause:300)',
871 'self::superscript', 'children/*[2][text()=2]');
874 'text-no-mult', 'default.default',
875 '[n] children/*[1]; [p] (pause:200); [n] children/*[2]',
876 'self::infixop', 'children/text');