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] ./*');
100 defineDefaultMathmlRule('mspace', '[p] (pause:250)');
101 defineDefaultMathmlRule('mstyle', '[m] ./*');
102 defineDefaultMathmlRule('mpadded', '[m] ./*');
103 defineDefaultMathmlRule('merror', '[m] ./*');
104 defineDefaultMathmlRule('mphantom', '[m] ./*');
107 defineDefaultMathmlRule('mtext', '[t] text(); [p] (pause:200)');
108 defineDefaultMathmlRule('mi', '[n] text()');
109 defineDefaultMathmlRule('mo', '[n] text() (rate:-0.1)');
110 defineDefaultMathmlRule('mn', '[n] text()');
112 // Dealing with fonts.
113 defineRule('mtext-variant', 'default.default',
114 '[t] "begin"; [t] @mathvariant (pause:150);' +
115 '[t] text() (pause:150); [t] "end"; ' +
116 '[t] @mathvariant (pause:200)',
117 'self::mathml:mtext', '@mathvariant', '@mathvariant!="normal"');
119 defineRule('mi-variant', 'default.default',
120 '[t] @mathvariant; [n] text()',
121 'self::mathml:mi', '@mathvariant', '@mathvariant!="normal"');
123 defineRuleAlias('mi-variant', 'self::mathml:mn', // mn
124 '@mathvariant', '@mathvariant!="normal"');
126 defineRule('mo-variant', 'default.default',
127 '[t] @mathvariant; [n] text() (rate:-0.1)',
128 'self::mathml:mo', '@mathvariant', '@mathvariant!="normal"');
130 defineDefaultMathmlRule(
132 '[t] "string" (pitch:0.5, rate:0.5); [t] text()');
135 defineDefaultMathmlRule(
136 'msup', '[n] ./*[1]; [t] "super";' +
137 '[n] ./*[2] (pitch:0.35); [p] (pause:300)');
138 defineDefaultMathmlRule(
140 '[n] ./*[1]; [t] "sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);' +
141 '[t] "super"; [n] ./*[3] (pitch:0.35); [p] (pause:300)'
143 defineDefaultMathmlRule(
145 '[n] ./*[1]; [t] "sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:300)');
146 defineDefaultMathmlRule(
147 'mover', '[n] ./*[2] (pitch:0.35); [p] (pause:200);' +
148 ' [t] "over"; [n] ./*[1]; [p] (pause:400)');
149 defineDefaultMathmlRule(
151 '[n] ./*[2] (pitch:-0.35); [t] "under"; [n] ./*[1]; [p] (pause:400)');
152 defineDefaultMathmlRule(
154 '[n] ./*[2] (pitch:-0.35); [t] "under and"; [n] ./*[3] (pitch:0.35);' +
155 ' [t] "over"; [n] ./*[1]; [p] (pause:400)');
158 defineDefaultMathmlRule('mrow', '[m] ./*');
159 defineDefaultMathmlRule(
160 'msqrt', '[t] "Square root of"; [m] ./* (rate:0.2); [p] (pause:400)');
161 defineDefaultMathmlRule(
162 'mroot', '[t] "root of order"; [n] ./*[2]; [t] "of";' +
163 '[n] ./*[1] (rate:0.2); [p] (pause:400)');
164 defineDefaultMathmlRule(
165 'mfrac', ' [p] (pause:400); [n] ./*[1] (pitch:0.3);' +
166 ' [t] "divided by"; [n] ./*[2] (pitch:-0.3); [p] (pause:400)');
170 'mfenced-single', 'default.default',
171 '[t] @open (context:"opening"); [m] ./* (separator:@separators);' +
172 '[t] @close (context:"closing")',
173 'self::mathml:mfenced', 'string-length(string(@separators))=1');
176 'mfenced-empty', 'default.default',
177 '[t] @open (context:"opening"); [m] ./*;' +
178 '[t] @close (context:"closing")',
179 'self::mathml:mfenced', 'string-length(string(@separators))=1',
180 'string(@separators)=" "');
183 'mfenced-comma', 'default.default',
184 '[t] @open (context:"opening"); [m] ./* (separator:"comma");' +
185 '[t] @close (context:"closing")',
186 'self::mathml:mfenced');
189 'mfenced-multi', 'default.default',
190 '[t] @open (context:"opening"); [m] ./* (sepFunc:CTXFmfSeparators,' +
191 'separator:@separators); [t] @close (context:"closing")',
192 'self::mathml:mfenced', 'string-length(string(@separators))>1');
196 'mtable', 'default.default',
197 '[t] "matrix"; [m] ./* (ctxtFunc:CTXFnodeCounter,' +
198 'context:"row",pause:100)',
199 'self::mathml:mtable');
202 'mtr', 'default.default',
203 '[m] ./* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)',
207 'mtd', 'default.default',
208 '[m] ./*', 'self::mathml:mtd');
210 // Mtable superbrief rules.
212 'mtable', 'default.superbrief',
213 '[t] count(child::mathml:mtr); [t] "by";' +
214 '[t] count(child::mathml:mtr[1]/mathml:mtd); [t] "matrix";',
215 'self::mathml:mtable');
217 // Mtable short rules.
219 'mtable', 'default.short',
220 '[t] "matrix"; [m] ./*',
221 'self::mathml:mtable');
224 'mtr', 'default.short',
225 '[m] ./*', 'self::mathml:mtr');
228 'mtd', 'default.short',
229 '[t] "Element"; [t] count(./preceding-sibling::mathml:mtd)+1;' +
230 '[t] count(./parent::mathml:mtr/preceding-sibling::mathml:mtr)+1;' +
231 '[p] (pause:500); [m] ./*',
234 // Mmultiscripts rules.
236 'mmultiscripts-4', 'default.default',
237 '[n] ./*[1]; [p] (pause:200);' +
238 '[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);' +
239 '[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:200);' +
240 '[t] "right sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);' +
241 '[t] "right super"; [n] ./*[3] (pitch:0.35); [p] (pause:300);',
242 'self::mathml:mmultiscripts');
244 'mmultiscripts-3-1', 'default.default',
245 '[n] ./*[1]; [p] (pause:200);' +
246 '[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);' +
247 '[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:200);' +
248 '[t] "right super"; [n] ./*[3] (pitch:0.35); [p] (pause:300);',
249 'self::mathml:mmultiscripts', './mathml:none=./*[2]',
250 './mathml:mprescripts=./*[4]');
252 'mmultiscripts-3-2', 'default.default',
253 '[n] ./*[1]; [p] (pause:200);' +
254 '[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);' +
255 '[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:200);' +
256 '[t] "right sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);',
257 'self::mathml:mmultiscripts', './mathml:none=./*[3]',
258 './mathml:mprescripts=./*[4]');
260 'mmultiscripts-3-3', 'default.default',
261 '[n] ./*[1]; [p] (pause:200);' +
262 '[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:200);' +
263 '[t] "right sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);' +
264 '[t] "right super"; [n] ./*[3] (pitch:0.35); [p] (pause:300);',
265 'self::mathml:mmultiscripts', './mathml:none=./*[5]',
266 './mathml:mprescripts=./*[4]');
268 'mmultiscripts-3-4', 'default.default',
269 '[n] ./*[1]; [p] (pause:200);' +
270 '[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);' +
271 '[t] "right sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);' +
272 '[t] "right super"; [n] ./*[3] (pitch:0.35); [p] (pause:300);',
273 'self::mathml:mmultiscripts', './mathml:none=./*[6]',
274 './mathml:mprescripts=./*[4]');
276 'mmultiscripts-2-1', 'default.default',
277 '[n] ./*[1]; [p] (pause:200);' +
278 '[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);' +
279 '[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:300);',
280 'self::mathml:mmultiscripts', './mathml:none=./*[2]',
281 './mathml:none=./*[3]', './mathml:mprescripts=./*[4]');
283 'mmultiscripts-1-1', 'default.default',
284 '[n] ./*[1]; [p] (pause:200);' +
285 '[t] "left super"; [n] ./*[6] (pitch:0.35); [p] (pause:300);',
286 'self::mathml:mmultiscripts', './mathml:none=./*[2]',
287 './mathml:none=./*[3]', './mathml:mprescripts=./*[4]',
288 './mathml:none=./*[5]');
290 'mmultiscripts-1-2', 'default.default',
291 '[n] ./*[1]; [p] (pause:200);' +
292 '[t] "left sub"; [n] ./*[5] (pitch:-0.35); [p] (pause:200);',
293 'self::mathml:mmultiscripts', './mathml:none=./*[2]',
294 './mathml:none=./*[3]', './mathml:mprescripts=./*[4]',
295 './mathml:none=./*[6]');
300 * Initialize mathJax Rules
303 cvox
.MathmlStoreRules
.initMathjaxRules_ = function() {
305 defineRule('mj-math', 'default.default',
306 '[n] ./*[1]/*[1]/*[1]', 'self::span[@class="math"]');
310 'mj-leaf', 'default.default',
311 '[n] CQFlookupleaf', 'self::span[@class="mi"]');
312 defineRuleAlias('mj-leaf', 'self::span[@class="mo"]');
313 defineRuleAlias('mj-leaf', 'self::span[@class="mn"]');
314 defineRuleAlias('mj-leaf', 'self::span[@class="mtext"]');
316 'mj-mo-ext', 'default.default',
317 '[n] CQFextender', 'self::span[@class="mo"]',
318 './*[1]/*[1]/text()', './*[1]/*[2]/text()');
320 'mj-texatom', 'default.default',
321 '[n] ./*[1]', 'self::span[@class="texatom"]');
325 'mj-msubsup', 'default.default',
326 '[n] ./*[1]/*[1]/*[1]; [t] "sub"; [n] ./*[1]/*[3]/*[1] (pitch:-0.35);' +
327 '[p] (pause:200); [t] "super"; [n] ./*[1]/*[2]/*[1] (pitch:0.35);' +
329 'self::span[@class="msubsup"]');
331 'mj-msub', 'default.default',
332 '[n] ./*[1]/*[1]/*[1]; [t] "sub";' +
333 '[n] ./*[1]/*[2]/*[1] (pitch:-0.35); [p] (pause:300)',
334 'self::span[@class="msub"]');
336 'mj-msup', 'default.default',
337 '[n] ./*[1]/*[1]/*[1]; [t] "super";' +
338 '[n] ./*[1]/*[2]/*[1] (pitch:0.35); [p] (pause:300)',
339 'self::span[@class="msup"]');
341 'mj-munderover', 'default.default',
342 '[n] ./*[1]/*[2]/*[1] (pitch:0.35); [t] "under and";' +
343 '[n] ./*[1]/*[3]/*[1] (pitch:-0.35); [t] "over";' +
344 '[n] ./*[1]/*[1]/*[1]; [p] (pause:400)',
345 'self::span[@class="munderover"]');
347 'mj-munder', 'default.default',
348 '[n] ./*[1]/*[2]/*[1] (pitch:0.35); [t] "under";' +
349 '[n] ./*[1]/*[1]/*[1]; [p] (pause:400)',
350 'self::span[@class="munder"]');
352 'mj-mover', 'default.default',
353 '[n] ./*[1]/*[2]/*[1] (pitch:0.35); [t] "over";' +
354 '[n] ./*[1]/*[1]/*[1]; [p] (pause:400)',
355 'self::span[@class="mover"]');
360 'mj-mfrac', 'default.default',
361 '[p] (pause:250); [n] ./*[1]/*[1]/*[1] (pitch:0.3); [p] (pause:250);' +
362 ' [t] "divided by"; [n] ./*[1]/*[2]/*[1] (pitch:-0.3);' +
364 'self::span[@class="mfrac"]');
366 'mj-msqrt', 'default.default',
367 '[t] "Square root of";' +
368 '[n] ./*[1]/*[1]/*[1] (rate:0.2); [p] (pause:400)',
369 'self::span[@class="msqrt"]');
371 'mj-mroot', 'default.default',
372 '[t] "root of order"; [n] ./*[1]/*[4]/*[1]; [t] "of";' +
373 '[n] ./*[1]/*[1]/*[1] (rate:0.2); [p] (pause:400)',
374 'self::span[@class="mroot"]');
377 'mj-mfenced', 'default.default',
378 '[t] "opening"; [n] ./*[1]; ' +
379 '[m] ./*[position()>1 and position()<last()];' +
380 ' [t] "closing"; [n] ./*[last()]',
381 'self::span[@class="mfenced"]');
383 // Mtable short rules.
384 defineRuleAlias('mj-leaf', 'self::span[@class="mtable"]');
385 // Mmultiscripts rules.
386 defineRuleAlias('mj-leaf', 'self::span[@class="mmultiscripts"]');
391 * Initialize mathJax Aliases
394 cvox
.MathmlStoreRules
.initAliases_ = function() {
396 defineRuleAlias('mspace', 'self::span[@class="mspace"]');
397 defineRuleAlias('mstyle', 'self::span[@class="mstyle"]');
398 defineRuleAlias('mpadded', 'self::span[@class="mpadded"]');
399 defineRuleAlias('merror', 'self::span[@class="merror"]');
400 defineRuleAlias('mphantom', 'self::span[@class="mphantom"]');
403 defineRuleAlias('ms', 'self::span[@class="ms"]');
406 defineRuleAlias('mrow', 'self::span[@class="mrow"]');
408 // The following rules fix bugs in MathJax's LaTeX translation.
410 'mj-msub', 'self::span[@class="msubsup"]', 'CQFmathmlmsub');
413 'mj-msup', 'self::span[@class="msubsup"]', 'CQFmathmlmsup');
416 'mj-munder', 'self::span[@class="munderover"]', 'CQFmathmlmunder');
419 'mj-mover', 'self::span[@class="munderover"]', 'CQFmathmlmover');
424 * Initialize specializations wrt. content of nodes.
427 cvox
.MathmlStoreRules
.initSpecializationRules_ = function() {
428 // Some special nodes for square and cube.
431 'square', 'default.default',
432 '[n] ./*[1]; [t] "square" (pitch:0.35); [p] (pause:300)',
433 'self::mathml:msup', './*[2][text()=2]');
435 'square', 'self::mathml:msup',
436 './mathml:mrow=./*[2]', 'count(./*[2]/*)=1', './*[2]/*[1][text()=2]');
439 'cube', 'default.default',
440 '[n] ./*[1]; [t] "cube" (pitch:0.35); [p] (pause:300)',
441 'self::mathml:msup', './*[2][text()=3]');
443 'cube', 'self::mathml:msup',
444 './mathml:mrow=./*[2]', 'count(./*[2]/*)=1', './*[2]/*[1][text()=3]');
447 'square-sub', 'default.default',
448 '[n] ./*[1]; [t] "sub"; [n] ./*[2] (pitch:-0.35);' +
449 '[p] (pause:300); [t] "square" (pitch:0.35); [p] (pause:400)',
450 'self::mathml:msubsup', './*[3][text()=2]');
452 'square-sub', 'self::mathml:msubsup',
453 './mathml:mrow=./*[3]', 'count(./*[3]/*)=1', './*[3]/*[1][text()=2]');
456 'cube-sub', 'default.default',
457 '[n] ./*[1]; [t] "sub"; [n] ./*[2] (pitch:-0.35);' +
458 '[p] (pause:300); [t] "cube" (pitch:0.35); [p] (pause:400)',
459 'self::mathml:msubsup', './*[3][text()=3]');
461 'cube-sub', 'self::mathml:msubsup',
462 './mathml:mrow=./*[3]', 'count(./*[3]/*)=1', './*[3]/*[1][text()=3]');
466 'mj-square', 'default.default',
467 '[n] ./*[1]/*[1]/*[1]; [t] "square" (pitch:0.35); [p] (pause:300)',
468 'self::span[@class="msup"]', './*[1]/*[2]/*[1][text()=2]');
470 'mj-square', 'self::span[@class="msup"]',
471 './*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]',
472 'count(./*[1]/*[2]/*[1]/*)=1', './*[1]/*[2]/*[1]/*[1][text()=2]');
474 'mj-square', 'self::span[@class="msubsup"]', 'CQFmathmlmsup',
475 './*[1]/*[2]/*[1][text()=2]');
477 'mj-square', 'self::span[@class="msubsup"]', 'CQFmathmlmsup',
478 './*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]',
479 'count(./*[1]/*[2]/*[1]/*)=1', './*[1]/*[2]/*[1]/*[1][text()=2]');
482 'mj-cube', 'default.default',
483 '[n] ./*[1]/*[1]/*[1]; [t] "cube" (pitch:0.35); [p] (pause:300)',
484 'self::span[@class="msup"]', './*[1]/*[2]/*[1][text()=3]');
486 'mj-cube', 'self::span[@class="msup"]',
487 './*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]',
488 'count(./*[1]/*[2]/*[1]/*)=1', './*[1]/*[2]/*[1]/*[1][text()=3]');
490 'mj-cube', 'self::span[@class="msubsup"]', 'CQFmathmlmsup',
491 './*[1]/*[2]/*[1][text()=3]');
493 'mj-cube', 'self::span[@class="msubsup"]', 'CQFmathmlmsup',
494 './*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]',
495 'count(./*[1]/*[2]/*[1]/*)=1', './*[1]/*[2]/*[1]/*[1][text()=3]');
498 'mj-square-sub', 'default.default',
499 '[n] ./*[1]/*[1]/*[1]; [t] "sub"; [n] ./*[1]/*[3]/*[1] (pitch:-0.35); ' +
500 '[p] (pause:300); [t] "square" (pitch:0.35); [p] (pause:400)',
501 'self::span[@class="msubsup"]', './*[1]/*[2]/*[1][text()=2]');
503 'mj-square-sub', 'self::span[@class="msubsup"]',
504 './*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]',
505 'count(./*[1]/*[2]/*[1]/*)=1', './*[1]/*[2]/*[1]/*[1][text()=2]');
508 'mj-cube-sub', 'default.default',
509 '[n] ./*[1]/*[1]/*[1]; [t] "sub"; [n] ./*[1]/*[3]/*[1] (pitch:-0.35); ' +
510 '[p] (pause:300); [t] "cube" (pitch:0.35); [p] (pause:400)',
511 'self::span[@class="msubsup"]', './*[1]/*[2]/*[1][text()=3]');
513 'mj-cube-sub', 'self::span[@class="msubsup"]',
514 './*[1]/*[2]/*[1]=./*[1]/*[2]/span[@class="mrow"]',
515 'count(./*[1]/*[2]/*[1]/*)=1', './*[1]/*[2]/*[1]/*[1][text()=3]');
520 * Initialize mathJax Aliases
523 cvox
.MathmlStoreRules
.initSemanticRules_ = function() {
526 'stree', 'default.default',
527 '[n] ./*[1]', 'self::stree');
530 'multrel', 'default.default',
531 '[t] "multirelation"; [m] children/* (sepFunc:CTXFcontentIterator)',
535 'variable-equality', 'default.default',
536 '[t] "equation sequence"; [m] ./children/* ' +
537 '(context:"part",ctxtFunc:CTXFnodeCounter,separator:./text())',
538 'self::relseq[@role="equality"]', 'count(./children/*)>2',
539 './children/punct[@role="ellipsis"]');// Make that better!
542 'multi-equality', 'default.default',
543 '[t] "equation sequence"; [m] ./children/* ' +
544 '(context:"part",ctxtFunc:CTXFnodeCounter,separator:./text())',
545 'self::relseq[@role="equality"]', 'count(./children/*)>2');
548 'multi-equality', 'default.short',
549 '[t] "equation sequence"; [m] ./children/* ' +
550 '(separator:./text())',
551 'self::relseq[@role="equality"]', 'count(./children/*)>2');
554 'equality', 'default.default',
555 '[t] "equation"; [t] "left hand side"; [n] children/*[1];' +
556 '[p] (pause:200); [n] text() (pause:200);' +
557 '[t] "right hand side"; [n] children/*[2]',
558 'self::relseq[@role="equality"]', 'count(./children/*)=2');
561 'simple-equality', 'default.default',
562 '[n] children/*[1]; [p] (pause:200); [n] text() (pause:200);' +
564 'self::relseq[@role="equality"]', 'count(./children/*)=2',
565 './children/identifier or ./children/number');
568 'simple-equality2', 'default.default',
569 '[n] children/*[1]; [p] (pause:200); [n] text() (pause:200);' +
571 'self::relseq[@role="equality"]', 'count(./children/*)=2',
572 './children/function or ./children/appl');
575 'multrel', 'default.default',
576 '[m] children/* (separator:./text())',
580 'binary-operation', 'default.default',
581 '[m] children/* (separator:text());',
585 'variable-addition', 'default.default',
586 '[t] "sum with variable number of summands";' +
587 '[p] (pause:400); [m] children/* (separator:./text())',
588 'self::infixop[@role="addition"]', 'count(children/*)>2',
589 'children/punct[@role="ellipsis"]');// Make that better!
592 'multi-addition', 'default.default',
593 '[t] "sum with,"; [t] count(./children/*); [t] ", summands";' +
594 '[p] (pause:400); [m] ./children/* (separator:./text())',
595 'self::infixop[@role="addition"]', 'count(./children/*)>2');
599 'prefix', 'default.default',
600 '[t] "prefix"; [n] text(); [t] "of" (pause 150);' +
605 'negative', 'default.default',
606 '[t] "negative"; [n] children/*[1]',
607 'self::prefixop', 'self::prefixop[@role="negative"]');
611 'postfix', 'default.default',
612 '[n] children/*[1]; [t] "postfix"; [n] text() (pause 300)',
616 'identifier', 'default.default',
617 '[n] text()', 'self::identifier');
620 'number', 'default.default',
621 '[n] text()', 'self::number');
624 'fraction', 'default.default',
625 '[p] (pause:250); [n] children/*[1] (pitch:0.3); [p] (pause:250);' +
626 ' [t] "divided by"; [n] children/*[2] (pitch:-0.3); [p] (pause:400)',
630 'superscript', 'default.default',
631 '[n] children/*[1]; [t] "super"; [n] children/*[2] (pitch:0.35);' +
633 'self::superscript');
635 'subscript', 'default.default',
636 '[n] children/*[1]; [t] "sub"; [n] children/*[2] (pitch:-0.35);' +
641 'ellipsis', 'default.default',
642 '[p] (pause:200); [t] "dot dot dot"; [p] (pause:300)',
643 'self::punct', 'self::punct[@role="ellipsis"]');
646 'fence-single', 'default.default',
648 'self::punct', 'self::punct[@role="openfence"]');
649 defineRuleAlias('fence-single', 'self::punct',
650 'self::punct[@role="closefence"]');
651 defineRuleAlias('fence-single', 'self::punct',
652 'self::punct[@role="vbar"]');
653 defineRuleAlias('fence-single', 'self::punct',
654 'self::punct[@role="application"]');
656 // TODO (sorge) Refine punctuations further.
658 'omit-punct', 'default.default',
663 'omit-empty', 'default.default',
669 'fences-open-close', 'default.default',
670 '[p] (pause:100); [t] "open"; [n] children/*[1]; [p] (pause:200);' +
672 'self::fenced[@role="leftright"]');
675 'fences-open-close-in-appl', 'default.default',
676 '[p] (pause:100); [n] children/*[1]; [p] (pause:200);',
677 'self::fenced[@role="leftright"]', './parent::children/parent::appl');
680 'fences-neutral', 'default.default',
681 '[p] (pause:100); [t] "absolute value of"; [n] children/*[1];' +
683 'self::fenced', 'self::fenced[@role="neutral"]');
686 'omit-fences', 'default.default',
687 '[p] (pause:500); [n] children/*[1]; [p] (pause:200);',
692 'matrix', 'default.default',
693 '[t] "matrix"; [m] children/* ' +
694 '(ctxtFunc:CTXFnodeCounter,context:"row",pause:100)',
698 'matrix-row', 'default.default',
699 '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)',
700 'self::row[@role="matrix"]');
703 'matrix-cell', 'default.default',
704 '[n] children/*[1]', 'self::cell[@role="matrix"]');
708 'vector', 'default.default',
709 '[t] "vector"; [m] children/* ' +
710 '(ctxtFunc:CTXFnodeCounter,context:"element",pause:100)',
715 'cases', 'default.default',
716 '[t] "case statement"; [m] children/* ' +
717 '(ctxtFunc:CTXFnodeCounter,context:"case",pause:100)',
721 'cases-row', 'default.default',
722 '[m] children/*', 'self::row[@role="cases"]');
725 'cases-cell', 'default.default',
726 '[n] children/*[1]', 'self::cell[@role="cases"]');
729 'row', 'default.default',
730 '[m] ./* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)',
734 'cases-end', 'default.default',
735 '[t] "case statement"; ' +
736 '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"case",pause:100);' +
738 'self::cases', 'following-sibling::*');
742 'multiline', 'default.default',
743 '[t] "multiline equation";' +
744 '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"line",pause:100)',
748 'line', 'default.default',
749 '[m] children/*', 'self::line');
753 'table', 'default.default',
754 '[t] "multiline equation";' +
755 '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"row",pause:200)',
759 'table-row', 'default.default',
760 '[m] children/* (pause:100)', 'self::row[@role="table"]');
763 'cases-cell', 'self::cell[@role="table"]');
766 // Rules for punctuated expressions.
768 'end-punct', 'default.default',
769 '[m] children/*; [p] (pause:300)',
770 'self::punctuated', '@role="endpunct"');
773 'start-punct', 'default.default',
774 '[n] content/*[1]; [p] (pause:200); [m] children/*',
775 'self::punctuated', '@role="startpunct"');
778 'integral-punct', 'default.default',
779 '[n] children/*[1] (rate:0.2); [n] children/*[3] (rate:0.2)',
780 'self::punctuated', '@role="integral"');
783 'punctuated', 'default.default',
784 '[m] children/* (pause:100)',
789 'function', 'default.default',
790 '[n] text()', 'self::function');
793 'appl', 'default.default',
794 '[n] children/*[1]; [n] content/*[1]; [n] children/*[2]', 'self::appl');
796 // Limit operator rules
798 'limboth', 'default.default',
799 '[n] children/*[1]; [t] "from"; [n] children/*[2]; [t] "to";' +
800 '[n] children/*[3]', 'self::limboth');
803 'sum-only', 'default.default',
804 '[n] children/*[1]; [p] (pause 100); [t] "over"; [n] children/*[2];' +
806 'self::limboth', 'self::limboth[@role="sum"]');
809 'limlower', 'default.default',
810 '[n] children/*[1]; [t] "over"; [n] children/*[2];', 'self::limlower');
813 'limupper', 'default.default',
814 '[n] children/*[1]; [t] "under"; [n] children/*[2];', 'self::limupper');
818 'largeop', 'default.default',
819 '[n] text()', 'self::largeop');
822 'bigop', 'default.default',
823 '[n] children/*[1]; [p] (pause 100); [t] "over"; [n] children/*[2];' +
830 'integral', 'default.default',
831 '[n] children/*[1]; [p] (pause 100); [n] children/*[2]; [p] (pause 200);' +
832 '[n] children/*[3] (rate:0.35);', 'self::integral');
836 'sqrt', 'default.default',
837 '[t] "Square root of"; [n] children/*[1] (rate:0.2); [p] (pause:400)',
841 'square', 'default.default',
842 '[n] children/*[1]; [t] "square" (pitch:0.35); [p] (pause:300)',
843 'self::superscript', 'children/*[2][text()=2]');
846 'text-no-mult', 'default.default',
847 '[n] children/*[1]; [p] (pause:200); [n] children/*[2]',
848 'self::infixop', 'children/text');