mathml_store_rules.js revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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.
4
5/**
6 * @fileoverview Speech rules for mathml and mathjax nodes.
7 */
8
9goog.provide('cvox.MathmlStoreRules');
10
11goog.require('cvox.MathStore');
12goog.require('cvox.MathmlStore');
13goog.require('cvox.MathmlStoreUtil');
14goog.require('cvox.StoreUtil');
15
16
17/**
18 * Rule initialization.
19 * @constructor
20 */
21cvox.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_();
29};
30goog.addSingletonGetter(cvox.MathmlStoreRules);
31
32
33/**
34 * @type {cvox.MathStore}
35 */
36cvox.MathmlStoreRules.mathStore = cvox.MathmlStore.getInstance();
37/**
38 * @override
39 */
40cvox.MathmlStoreRules.mathStore.initialize = cvox.MathmlStoreRules.getInstance;
41
42// These are used to work around Closure's rules for aliasing.
43/** @private */
44cvox.MathmlStoreRules.defineDefaultMathmlRule_ = goog.bind(
45    cvox.MathmlStoreRules.mathStore.defineDefaultMathmlRule,
46    cvox.MathmlStoreRules.mathStore);
47/** @private */
48cvox.MathmlStoreRules.defineRule_ = goog.bind(
49    cvox.MathmlStoreRules.mathStore.defineRule,
50    cvox.MathmlStoreRules.mathStore);
51/** @private */
52cvox.MathmlStoreRules.defineRuleAlias_ = goog.bind(
53    cvox.MathmlStoreRules.mathStore.defineRuleAlias,
54    cvox.MathmlStoreRules.mathStore);
55/** @private */
56cvox.MathmlStoreRules.addContextFunction_ = goog.bind(
57    cvox.MathmlStoreRules.mathStore.contextFunctions.add,
58    cvox.MathmlStoreRules.mathStore.contextFunctions);
59/** @private */
60cvox.MathmlStoreRules.addCustomQuery_ = goog.bind(
61    cvox.MathmlStoreRules.mathStore.customQueries.add,
62    cvox.MathmlStoreRules.mathStore.customQueries);
63
64goog.scope(function() {
65var defineDefaultMathmlRule = cvox.MathmlStoreRules.defineDefaultMathmlRule_;
66var defineRule = cvox.MathmlStoreRules.defineRule_;
67var defineRuleAlias = cvox.MathmlStoreRules.defineRuleAlias_;
68
69var addCTXF = cvox.MathmlStoreRules.addContextFunction_;
70var addCQF = cvox.MathmlStoreRules.addCustomQuery_;
71
72/**
73 * Initialize the custom functions.
74 * @private
75 */
76cvox.MathmlStoreRules.initCustomFunctions_ = function() {
77  addCTXF('CTXFnodeCounter', cvox.StoreUtil.nodeCounter);
78  addCTXF('CTXFmfSeparators', cvox.MathmlStoreUtil.mfencedSeparators);
79  addCTXF('CTXFcontentIterator', cvox.MathmlStoreUtil.contentIterator);
80
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);
87
88};
89
90
91/**
92 * Initialize the default mathrules.
93 * @private
94 */
95cvox.MathmlStoreRules.initDefaultRules_ = function() {
96  // Initial rule
97  defineDefaultMathmlRule('math', '[m] ./*');
98
99  // Space elements
100  defineDefaultMathmlRule('mspace', '[p] (pause:250)');
101  defineDefaultMathmlRule('mstyle', '[m] ./*');
102  defineDefaultMathmlRule('mpadded', '[m] ./*');
103  defineDefaultMathmlRule('merror', '[m] ./*');
104  defineDefaultMathmlRule('mphantom', '[m] ./*');
105
106  // Token elements.
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()');
111
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"');
118
119  defineRule('mi-variant', 'default.default',
120      '[t] @mathvariant; [n] text()',
121      'self::mathml:mi', '@mathvariant', '@mathvariant!="normal"');
122
123  defineRuleAlias('mi-variant', 'self::mathml:mn',  // mn
124      '@mathvariant', '@mathvariant!="normal"');
125
126  defineRule('mo-variant', 'default.default',
127      '[t] @mathvariant; [n] text() (rate:-0.1)',
128      'self::mathml:mo', '@mathvariant', '@mathvariant!="normal"');
129
130  defineDefaultMathmlRule(
131      'ms',
132      '[t] "string" (pitch:0.5, rate:0.5); [t] text()');
133
134  // Script elements.
135  defineDefaultMathmlRule(
136      'msup', '[n] ./*[1]; [t] "super";' +
137          '[n] ./*[2] (pitch:0.35); [p] (pause:300)');
138  defineDefaultMathmlRule(
139      'msubsup',
140      '[n] ./*[1]; [t] "sub"; [n] ./*[2] (pitch:-0.35); [p] (pause:200);' +
141          '[t] "super"; [n] ./*[3] (pitch:0.35); [p] (pause:300)'
142      );
143  defineDefaultMathmlRule(
144      'msub',
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(
150      'munder',
151      '[n] ./*[2] (pitch:-0.35); [t] "under"; [n] ./*[1]; [p] (pause:400)');
152  defineDefaultMathmlRule(
153      'munderover',
154      '[n] ./*[2] (pitch:-0.35); [t] "under and"; [n] ./*[3] (pitch:0.35);' +
155          ' [t] "over"; [n] ./*[1]; [p] (pause:400)');
156
157  // Layout elements.
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)');
167
168
169  defineRule(
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');
174
175  defineRule(
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)=" "');
181
182  defineRule(
183      'mfenced-comma', 'default.default',
184      '[t] @open (context:"opening"); [m] ./* (separator:"comma");' +
185          '[t] @close (context:"closing")',
186      'self::mathml:mfenced');
187
188  defineRule(
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');
193
194  // Mtable rules.
195  defineRule(
196      'mtable', 'default.default',
197      '[t] "matrix"; [m] ./* (ctxtFunc:CTXFnodeCounter,' +
198          'context:"row",pause:100)',
199      'self::mathml:mtable');
200
201  defineRule(
202      'mtr', 'default.default',
203      '[m] ./* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)',
204      'self::mathml:mtr');
205
206  defineRule(
207      'mtd', 'default.default',
208      '[m] ./*', 'self::mathml:mtd');
209
210  // Mtable superbrief rules.
211  defineRule(
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');
216
217  // Mtable short rules.
218  defineRule(
219      'mtable', 'default.short',
220      '[t] "matrix"; [m] ./*',
221      'self::mathml:mtable');
222
223  defineRule(
224      'mtr', 'default.short',
225      '[m] ./*', 'self::mathml:mtr');
226
227  defineRule(
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] ./*',
232      'self::mathml:mtd');
233
234  // Mmultiscripts rules.
235  defineRule(
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');
243  defineRule(
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]');
251  defineRule(
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]');
259  defineRule(
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]');
267  defineRule(
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]');
275  defineRule(
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]');
282  defineRule(
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]');
289  defineRule(
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]');
296};
297
298
299/**
300 * Initialize mathJax Rules
301 * @private
302 */
303cvox.MathmlStoreRules.initMathjaxRules_ = function() {
304  // Initial rule
305  defineRule('mj-math', 'default.default',
306             '[n] ./*[1]/*[1]/*[1]', 'self::span[@class="math"]');
307
308  // Token Elements
309  defineRule(
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"]');
315  defineRule(
316      'mj-mo-ext', 'default.default',
317      '[n] CQFextender', 'self::span[@class="mo"]',
318      './*[1]/*[1]/text()', './*[1]/*[2]/text()');
319  defineRule(
320      'mj-texatom', 'default.default',
321      '[n] ./*[1]', 'self::span[@class="texatom"]');
322
323  // Script elements.
324  defineRule(
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);' +
328      '[p] (pause:300)',
329      'self::span[@class="msubsup"]');
330  defineRule(
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"]');
335  defineRule(
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"]');
340  defineRule(
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"]');
346  defineRule(
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"]');
351  defineRule(
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"]');
356
357
358  // Layout elements.
359  defineRule(
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);' +
363              '[p] (pause:400)',
364      'self::span[@class="mfrac"]');
365  defineRule(
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"]');
370  defineRule(
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"]');
375
376  defineRule(
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"]');
382
383  // Mtable short rules.
384  defineRuleAlias('mj-leaf', 'self::span[@class="mtable"]');
385  // Mmultiscripts rules.
386  defineRuleAlias('mj-leaf', 'self::span[@class="mmultiscripts"]');
387};
388
389
390/**
391 * Initialize mathJax Aliases
392 * @private
393 */
394cvox.MathmlStoreRules.initAliases_ = function() {
395  // Space elements
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"]');
401
402  // Token elements.
403  defineRuleAlias('ms', 'self::span[@class="ms"]');
404
405  // Layout elements.
406  defineRuleAlias('mrow', 'self::span[@class="mrow"]');
407
408  // The following rules fix bugs in MathJax's LaTeX translation.
409  defineRuleAlias(
410      'mj-msub', 'self::span[@class="msubsup"]', 'CQFmathmlmsub');
411
412  defineRuleAlias(
413      'mj-msup', 'self::span[@class="msubsup"]', 'CQFmathmlmsup');
414
415  defineRuleAlias(
416      'mj-munder', 'self::span[@class="munderover"]', 'CQFmathmlmunder');
417
418  defineRuleAlias(
419      'mj-mover', 'self::span[@class="munderover"]', 'CQFmathmlmover');
420};
421
422
423/**
424 * Initialize specializations wrt. content of nodes.
425 * @private
426 */
427cvox.MathmlStoreRules.initSpecializationRules_ = function() {
428  // Some special nodes for square and cube.
429  // MathML
430  defineRule(
431      'square', 'default.default',
432      '[n] ./*[1]; [t] "square" (pitch:0.35); [p] (pause:300)',
433      'self::mathml:msup', './*[2][text()=2]');
434  defineRuleAlias(
435      'square', 'self::mathml:msup',
436      './mathml:mrow=./*[2]', 'count(./*[2]/*)=1', './*[2]/*[1][text()=2]');
437
438  defineRule(
439      'cube', 'default.default',
440      '[n] ./*[1]; [t] "cube" (pitch:0.35); [p] (pause:300)',
441      'self::mathml:msup', './*[2][text()=3]');
442  defineRuleAlias(
443      'cube', 'self::mathml:msup',
444      './mathml:mrow=./*[2]', 'count(./*[2]/*)=1', './*[2]/*[1][text()=3]');
445
446  defineRule(
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]');
451  defineRuleAlias(
452      'square-sub', 'self::mathml:msubsup',
453      './mathml:mrow=./*[3]', 'count(./*[3]/*)=1', './*[3]/*[1][text()=2]');
454
455  defineRule(
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]');
460  defineRuleAlias(
461      'cube-sub', 'self::mathml:msubsup',
462      './mathml:mrow=./*[3]', 'count(./*[3]/*)=1', './*[3]/*[1][text()=3]');
463
464  // MathJax
465  defineRule(
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]');
469  defineRuleAlias(
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]');
473  defineRuleAlias(
474      'mj-square', 'self::span[@class="msubsup"]', 'CQFmathmlmsup',
475      './*[1]/*[2]/*[1][text()=2]');
476  defineRuleAlias(
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]');
480
481  defineRule(
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]');
485  defineRuleAlias(
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]');
489  defineRuleAlias(
490      'mj-cube', 'self::span[@class="msubsup"]', 'CQFmathmlmsup',
491      './*[1]/*[2]/*[1][text()=3]');
492  defineRuleAlias(
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]');
496
497  defineRule(
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]');
502  defineRuleAlias(
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]');
506
507  defineRule(
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]');
512  defineRuleAlias(
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]');
516};
517
518
519/**
520 * Initialize mathJax Aliases
521 * @private
522 */
523cvox.MathmlStoreRules.initSemanticRules_ = function() {
524  // Initial rule
525  defineRule(
526      'stree', 'default.default',
527      '[n] ./*[1]', 'self::stree');
528
529  defineRule(
530      'multrel', 'default.default',
531      '[t] "multirelation"; [m] children/* (sepFunc:CTXFcontentIterator)',
532      'self::multirel');
533
534  defineRule(
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!
540
541  defineRule(
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');
546
547  defineRule(
548      'multi-equality', 'default.short',
549      '[t] "equation sequence"; [m] ./children/* ' +
550          '(separator:./text())',
551      'self::relseq[@role="equality"]', 'count(./children/*)>2');
552
553  defineRule(
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');
559
560  defineRule(
561      'simple-equality', 'default.default',
562      '[n] children/*[1]; [p] (pause:200); [n] text() (pause:200);' +
563          '[n] children/*[2]',
564      'self::relseq[@role="equality"]', 'count(./children/*)=2',
565      './children/identifier or ./children/number');
566
567  defineRule(
568      'simple-equality2', 'default.default',
569      '[n] children/*[1]; [p] (pause:200); [n] text() (pause:200);' +
570          '[n] children/*[2]',
571      'self::relseq[@role="equality"]', 'count(./children/*)=2',
572      './children/function or ./children/appl');
573
574  defineRule(
575      'multrel', 'default.default',
576      '[m] children/* (separator:./text())',
577      'self::relseq');
578
579  defineRule(
580      'binary-operation', 'default.default',
581      '[m] children/* (separator:text());',
582      'self::infixop');
583
584  defineRule(
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!
590
591  defineRule(
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');
596
597  // Prefix Operator
598  defineRule(
599      'prefix', 'default.default',
600      '[t] "prefix"; [n] text(); [t] "of" (pause 150);' +
601      '[n] children/*[1]',
602      'self::prefixop');
603
604  defineRule(
605      'negative', 'default.default',
606      '[t] "negative"; [n] children/*[1]',
607      'self::prefixop', 'self::prefixop[@role="negative"]');
608
609  // Postfix Operator
610  defineRule(
611      'postfix', 'default.default',
612      '[n] children/*[1]; [t] "postfix"; [n] text() (pause 300)',
613      'self::postfixop');
614
615  defineRule(
616      'identifier', 'default.default',
617      '[n] text()', 'self::identifier');
618
619  defineRule(
620      'number', 'default.default',
621      '[n] text()', 'self::number');
622
623  defineRule(
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)',
627      'self::fraction');
628
629  defineRule(
630      'superscript', 'default.default',
631      '[n] children/*[1]; [t] "super"; [n] children/*[2] (pitch:0.35);' +
632      '[p] (pause:300)',
633      'self::superscript');
634  defineRule(
635      'subscript', 'default.default',
636      '[n] children/*[1]; [t] "sub"; [n] children/*[2] (pitch:-0.35);' +
637      '[p] (pause:300)',
638      'self::subscript');
639
640  defineRule(
641      'ellipsis', 'default.default',
642      '[p] (pause:200); [t] "dot dot dot"; [p] (pause:300)',
643      'self::punct', 'self::punct[@role="ellipsis"]');
644
645  defineRule(
646      'fence-single', 'default.default',
647      '[n] text()',
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"]');
655
656  // TODO (sorge) Refine punctuations further.
657  defineRule(
658      'omit-punct', 'default.default',
659      '[p] (pause:200);',
660      'self::punct');
661
662  defineRule(
663      'omit-empty', 'default.default',
664      '',
665      'self::empty');
666
667  // Fences rules.
668  defineRule(
669      'fences-open-close', 'default.default',
670      '[p] (pause:100); [t] "open"; [n] children/*[1]; [p] (pause:200);' +
671      '[t] "close"',
672      'self::fenced[@role="leftright"]');
673
674  defineRule(
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');
678
679  defineRule(
680      'fences-neutral', 'default.default',
681      '[p] (pause:100); [t] "absolute value of"; [n] children/*[1];' +
682      '[p] (pause:350);',
683      'self::fenced', 'self::fenced[@role="neutral"]');
684
685  defineRule(
686      'omit-fences', 'default.default',
687      '[p] (pause:500); [n] children/*[1]; [p] (pause:200);',
688      'self::fenced');
689
690  // Matrix rules.
691  defineRule(
692      'matrix', 'default.default',
693      '[t] "matrix"; [m] children/* ' +
694      '(ctxtFunc:CTXFnodeCounter,context:"row",pause:100)',
695      'self::matrix');
696
697  defineRule(
698      'matrix-row', 'default.default',
699      '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)',
700      'self::row[@role="matrix"]');
701
702  defineRule(
703      'matrix-cell', 'default.default',
704      '[n] children/*[1]', 'self::cell[@role="matrix"]');
705
706  // Vector rules.
707  defineRule(
708      'vector', 'default.default',
709      '[t] "vector"; [m] children/* ' +
710      '(ctxtFunc:CTXFnodeCounter,context:"element",pause:100)',
711      'self::vector');
712
713  // Cases rules.
714  defineRule(
715      'cases', 'default.default',
716      '[t] "case statement"; [m] children/* ' +
717      '(ctxtFunc:CTXFnodeCounter,context:"case",pause:100)',
718      'self::cases');
719
720  defineRule(
721      'cases-row', 'default.default',
722      '[m] children/*', 'self::row[@role="cases"]');
723
724  defineRule(
725      'cases-cell', 'default.default',
726      '[n] children/*[1]', 'self::cell[@role="cases"]');
727
728  defineRule(
729      'row', 'default.default',
730      '[m] ./* (ctxtFunc:CTXFnodeCounter,context:"column",pause:100)',
731      'self::row"');
732
733  defineRule(
734      'cases-end', 'default.default',
735      '[t] "case statement"; ' +
736      '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"case",pause:100);' +
737      '[t] "end cases"',
738      'self::cases', 'following-sibling::*');
739
740  // Multiline rules.
741  defineRule(
742      'multiline', 'default.default',
743      '[t] "multiline equation";' +
744      '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"line",pause:100)',
745      'self::multiline');
746
747  defineRule(
748      'line', 'default.default',
749      '[m] children/*', 'self::line');
750
751  // Table rules.
752  defineRule(
753      'table', 'default.default',
754      '[t] "multiline equation";' +
755      '[m] children/* (ctxtFunc:CTXFnodeCounter,context:"row",pause:200)',
756      'self::table');
757
758  defineRule(
759      'table-row', 'default.default',
760      '[m] children/* (pause:100)', 'self::row[@role="table"]');
761
762  defineRuleAlias(
763      'cases-cell', 'self::cell[@role="table"]');
764
765
766  // Rules for punctuated expressions.
767  defineRule(
768      'end-punct', 'default.default',
769      '[m] children/*; [p] (pause:300)',
770      'self::punctuated', '@role="endpunct"');
771
772  defineRule(
773      'start-punct', 'default.default',
774      '[n] content/*[1]; [p] (pause:200); [m] children/*',
775      'self::punctuated', '@role="startpunct"');
776
777  defineRule(
778      'integral-punct', 'default.default',
779      '[n] children/*[1] (rate:0.2); [n] children/*[3] (rate:0.2)',
780      'self::punctuated', '@role="integral"');
781
782  defineRule(
783      'punctuated', 'default.default',
784      '[m] children/* (pause:100)',
785      'self::punctuated');
786
787  // Function rules
788  defineRule(
789    'function', 'default.default',
790    '[n] text()', 'self::function');
791
792  defineRule(
793    'appl', 'default.default',
794    '[n] children/*[1]; [n] content/*[1]; [n] children/*[2]', 'self::appl');
795
796  // Limit operator rules
797  defineRule(
798    'limboth', 'default.default',
799    '[n] children/*[1]; [t] "from"; [n] children/*[2]; [t] "to";' +
800    '[n] children/*[3]', 'self::limboth');
801
802  defineRule(
803    'sum-only', 'default.default',
804    '[n] children/*[1]; [p] (pause 100); [t] "over"; [n] children/*[2];' +
805    '[p] (pause 250);',
806    'self::limboth', 'self::limboth[@role="sum"]');
807
808  defineRule(
809    'limlower', 'default.default',
810    '[n] children/*[1]; [t] "over"; [n] children/*[2];', 'self::limlower');
811
812  defineRule(
813    'limupper', 'default.default',
814    '[n] children/*[1]; [t] "under"; [n] children/*[2];', 'self::limupper');
815
816  // Bigoperator rules
817  defineRule(
818    'largeop', 'default.default',
819    '[n] text()', 'self::largeop');
820
821  defineRule(
822    'bigop', 'default.default',
823    '[n] children/*[1]; [p] (pause 100); [t] "over"; [n] children/*[2];' +
824    '[p] (pause 250);',
825    'self::bigop');
826
827
828  // Integral rules
829  defineRule(
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');
833
834
835  defineRule(
836      'sqrt', 'default.default',
837      '[t] "Square root of"; [n] children/*[1] (rate:0.2); [p] (pause:400)',
838      'self::sqrt');
839
840  defineRule(
841      'square', 'default.default',
842      '[n] children/*[1]; [t] "square" (pitch:0.35); [p] (pause:300)',
843      'self::superscript', 'children/*[2][text()=2]');
844
845  defineRule(
846      'text-no-mult', 'default.default',
847      '[n] children/*[1]; [p] (pause:200); [n] children/*[2]',
848      'self::infixop', 'children/text');
849};
850
851}); // goog.scope
852