math_semantic_attr.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 Semantic attributes of Math symbols and expressions.
7 *
8 * This file contains the basic functionality to lookup and assign semantic
9 * attributes for mathematical expressions. Since there is no such thing as a
10 * well-defined semantics for all of mathematics we compute a default semantics
11 * that closely models mathematical expressions found in K-12 mathematics as
12 * well as in general undergraduate curriculum (i.e., calculus, linear algebra,
13 * etc).
14 *
15 * Currently semantic attributes of symbols consist of the following two parts:
16 *
17 * type -- An unmutable property of an expression, regardless of its position in
18 *         the math expression. For example, the letter 'f' will always have the
19 *         type identifier, regardless of its use in context, e.g. as function
20 *         symbol or variable.
21 *
22 * role -- A mutable description of the role an expression plays in the context
23 *         of the overall mathematical expression. For instance, the symbol '|'
24 *         is of type punctuation, but depending on context it has the role of a
25 *         neutral fence or of a single vertical bar.
26 *
27 * In addition for some symbols we record the font as a further attribute.
28 *
29 * When a semantically interpreted expression is transformed into a XML
30 * representation, types become tag names, while role, font, etc. are added as
31 * attributes.
32 *
33 * This file is part of the content script as we do not want to call out to the
34 * background page every time we need to look up the semantic of a symbol.
35 *
36 * TODO (sorge) Move semantic tree translation into the background page
37 *    alongside MathJax.
38 *
39 */
40
41goog.provide('cvox.SemanticAttr');
42
43goog.require('cvox.SemanticUtil');
44
45
46/**
47 * Contains the basic mappings of characters/symbols and functions to semantic
48 * attributes.
49 *
50 * Observe that all characters are given as hex code number in order to ease the
51 * comparison with those in the JSON files that define speech rules per
52 * character.
53 * @constructor
54 */
55cvox.SemanticAttr = function() {
56  // Punctuation Characters.
57  /**
58   * @type {Array.<string>}
59   */
60  this.generalPunctuations =
61      [
62        '!', '"', '#', '%', '&', '\'', '*', ',', ':', ';', '?', '@', '\\',
63        '¡', '§', '¶', '·', '¿', '‗', '†', '‡', '•', '‣', '․', '‥', '‧',
64        '‰', '‱', '‸', '※', '‼', '‽', '‾', '⁁', '⁂', '⁃', '⁇', '⁈', '⁉',
65        '⁋', '⁌', '⁍', '⁎', '⁏', '⁐', '⁑', '⁓', '⁕', '⁖', '⁘', '⁙', '⁚',
66        '⁛', '⁜', '⁝', '⁞', '︐', '︓', '︔', '︕', '︖', '︰', '﹅', '﹆',
67        '﹉', '﹊', '﹋', '﹌', '﹐', '﹔', '﹕', '﹖', '﹗', '﹟', '﹠', '﹡', '﹨',
68        '﹪', '﹫', '!', '"', '#', '%', '&', ''', '*', ',', '/', ':',
69        ';', '?', '@', '\'
70      ];
71  /**
72   * @type {string}
73   * @private
74   */
75  this.invisibleComma_ = cvox.SemanticUtil.numberToUnicode(0x2063);
76  this.generalPunctuations.push(this.invisibleComma_);
77  /**
78   * @type {Array.<string>}
79   */
80  this.ellipses =
81      [
82        '…', '⋮', '⋯', '⋰', '⋱', '︙'
83      ];
84  /**
85   * @type {Array.<string>}
86   */
87  this.fullStops =
88      [
89        '.', '﹒', '.'
90      ];
91  /**
92   * @type {Array.<string>}
93   */
94  this.dashes =
95      [
96        '‒', '–', '—', '―', '〜', '︱', '︲', '﹘'
97      ];
98  /**
99   * @type {Array.<string>}
100   */
101  this.primes =
102      [
103        '′', '″', '‴', '‵', '‶', '‷', '⁗'
104      ];
105
106  // Fences.
107  // Fences are treated slightly differently from other symbols as we want to
108  // record pairs of opening/closing and top/bottom fences.
109  /**
110   * Mapping opening to closing fences.
111   * @type {Object.<string, string>}
112   */
113  this.openClosePairs =
114      {
115        // Unicode categories Ps and Pe.
116        // Observe that left quotation 301D could also be matched to 301F,
117        // but is currently matched to 301E.
118        '(': ')', '[': ']', '{': '}', '⁅': '⁆', '〈': '〉', '❨': '❩',
119        '❪': '❫', '❬': '❭', '❮': '❯', '❰': '❱', '❲': '❳', '❴': '❵',
120        '⟅': '⟆', '⟦': '⟧', '⟨': '⟩', '⟪': '⟫', '⟬': '⟭', '⟮': '⟯',
121        '⦃': '⦄', '⦅': '⦆', '⦇': '⦈', '⦉': '⦊', '⦋': '⦌', '⦍': '⦎',
122        '⦏': '⦐', '⦑': '⦒', '⦓': '⦔', '⦕': '⦖', '⦗': '⦘', '⧘': '⧙',
123        '⧚': '⧛', '⧼': '⧽', '⸢': '⸣', '⸤': '⸥', '⸦': '⸧', '⸨': '⸩',
124        '〈': '〉', '《': '》', '「': '」', '『': '』', '【': '】',
125        '〔': '〕', '〖': '〗', '〘': '〙', '〚': '〛', '〝': '〞',
126        '﴾': '﴿', '︗': '︘', '﹙': '﹚', '﹛': '﹜', '﹝': '﹞', '(': ')',
127        '[': ']', '{': '}', '⦅': '⦆', '「': '」',
128        // Unicode categories Sm and So.
129        '⌈': '⌉', '⌊': '⌋', '⌌': '⌍', '⌎': '⌏', '⌜': '⌝', '⌞': '⌟',
130        // Extender fences.
131        // Parenthesis.
132        '⎛': '⎞', '⎜': '⎟', '⎝': '⎠',
133        // Square bracket.
134        '⎡': '⎤', '⎢': '⎥', '⎣': '⎦',
135        // Curly bracket.
136        '⎧': '⎫', '⎨': '⎬', '⎩': '⎭', '⎰': '⎱', '⎸': '⎹'
137      };
138  /**
139   * Mapping top to bottom fences.
140   * @type {Object.<string, string>}
141   */
142  this.topBottomPairs =
143      {
144        '⎴': '⎵', '⏜': '⏝', '⏞': '⏟', '⏠': '⏡', '︵': '︶', '︷': '︸',
145        '︹': '︺', '︻': '︼', '︽': '︾', '︿': '﹀', '﹁': '﹂',
146        '﹃': '﹄', '﹇': '﹈'
147      };
148  /**
149   * @type {Array.<string>}
150   */
151  this.leftFences = cvox.SemanticUtil.objectsToKeys(this.openClosePairs);
152  /**
153   * @type {Array.<string>}
154   */
155  this.rightFences = cvox.SemanticUtil.objectsToValues(this.openClosePairs);
156  this.rightFences.push('〟');
157  /**
158   * @type {Array.<string>}
159   */
160  this.topFences = cvox.SemanticUtil.objectsToKeys(this.topBottomPairs);
161  /**
162   * @type {Array.<string>}
163   */
164  this.bottomFences = cvox.SemanticUtil.objectsToValues(this.topBottomPairs);
165  /**
166   * @type {Array.<string>}
167   */
168  this.neutralFences =
169      [
170        '|', '¦', '‖', '❘', '⦀', '⫴', '¦', '|'
171      ];
172  /** Array of all fences.
173   * @type {Array.<string>}
174   */
175  this.fences = this.neutralFences.concat(
176      this.leftFences, this.rightFences, this.topFences, this.bottomFences);
177
178  // Identifiers.
179  // Latin Alphabets.
180  /**
181   * @type {Array.<string>}
182   */
183  this.capitalLatin =
184      [
185        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
186        'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
187      ];
188  /**
189   * @type {Array.<string>}
190   */
191  this.smallLatin =
192      [
193        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
194        'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
195        // dotless i and j.
196        'ı', 'ȷ'
197      ];
198  /**
199   * @type {Array.<string>}
200   */
201  this.capitalLatinFullWidth =
202      [
203        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
204       'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
205      ];
206  /**
207   * @type {Array.<string>}
208   */
209  this.smallLatinFullWidth =
210      [
211        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
212        'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
213      ];
214  /**
215   * @type {Array.<string>}
216   */
217  this.capitalLatinBold =
218      [
219        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
220       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
221        ];
222  /**
223   * @type {Array.<string>}
224   */
225  this.smallLatinBold =
226      [
227        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
228       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
229        ];
230  /**
231   * @type {Array.<string>}
232   */
233  this.capitalLatinItalic =
234      [
235        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
236       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
237        ];
238  /**
239   * @type {Array.<string>}
240   */
241  this.smallLatinItalic =
242      [
243        '��', '��', '��', '��', '��', '��', '��', 'ℎ', '��', '��', '��', '��', '��',
244       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
245       // dotless i and j.
246       '��', '��'
247        ];
248  /**
249   * @type {Array.<string>}
250   */
251  this.capitalLatinScript =
252      [
253        '��', 'ℬ', '��', '��', 'ℰ', 'ℱ', '��', 'ℋ', 'ℐ', '��', '��', 'ℒ', 'ℳ',
254       '��', '��', '��', '��', 'ℛ', '��', '��', '��', '��', '��', '��', '��', '��',
255       // Powerset Cap P.
256       '℘'
257        ];
258  /**
259   * @type {Array.<string>}
260   */
261  this.smallLatinScript =
262      [
263        '��', '��', '��', '��', 'ℯ', '��', 'ℊ', '��', '��', '��', '��', '��', '��',
264       '��', 'ℴ', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
265       // script small l
266       'ℓ'
267        ];
268  /**
269   * @type {Array.<string>}
270   */
271  this.capitalLatinBoldScript =
272      [
273        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
274       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
275        ];
276  /**
277   * @type {Array.<string>}
278   */
279  this.smallLatinBoldScript =
280      [
281        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
282       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
283        ];
284  /**
285   * @type {Array.<string>}
286   */
287  this.capitalLatinFraktur =
288      [
289        '��', '��', 'ℭ', '��', '��', '��', '��', 'ℌ', 'ℑ', '��', '��', '��', '��',
290       '��', '��', '��', '��', 'ℜ', '��', '��', '��', '��', '��', '��', '��', 'ℨ'
291        ];
292  /**
293   * @type {Array.<string>}
294   */
295  this.smallLatinFraktur =
296      [
297        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
298       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
299        ];
300  /**
301   * @type {Array.<string>}
302   */
303  this.capitalLatinDoubleStruck =
304      [
305        '��', '��', 'ℂ', '��', '��', '��', '��', 'ℍ', '��', '��', '��', '��', '��',
306       'ℕ', '��', 'ℙ', 'ℚ', 'ℝ', '��', '��', '��', '��', '��', '��', '��', 'ℤ'
307        ];
308  /**
309   * @type {Array.<string>}
310   */
311  this.smallLatinDoubleStruck =
312      [
313        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
314       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
315        ];
316  /**
317   * @type {Array.<string>}
318   */
319  this.capitalLatinBoldFraktur =
320      [
321        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
322       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
323        ];
324  /**
325   * @type {Array.<string>}
326   */
327  this.smallLatinBoldFraktur =
328      [
329        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
330       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
331        ];
332  /**
333   * @type {Array.<string>}
334   */
335  this.capitalLatinSansSerif =
336      [
337        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
338       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
339        ];
340  /**
341   * @type {Array.<string>}
342   */
343  this.smallLatinSansSerif =
344      [
345        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
346       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
347        ];
348  /**
349   * @type {Array.<string>}
350   */
351  this.capitalLatinSansSerifBold =
352      [
353        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
354       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
355        ];
356  /**
357   * @type {Array.<string>}
358   */
359  this.smallLatinSansSerifBold =
360      [
361        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
362       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
363        ];
364  /**
365   * @type {Array.<string>}
366   */
367  this.capitalLatinSansSerifItalic =
368      [
369        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
370       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
371        ];
372  /**
373   * @type {Array.<string>}
374   */
375  this.smallLatinSansSerifItalic =
376      [
377        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
378       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
379        ];
380  /**
381   * @type {Array.<string>}
382   */
383  this.capitalLatinMonospace =
384      [
385        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
386       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
387        ];
388  /**
389   * @type {Array.<string>}
390   */
391  this.smallLatinMonospace =
392      [
393        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
394       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
395        ];
396  /**
397   * @type {Array.<string>}
398   */
399  this.latinDoubleStruckItalic =
400      [
401        'ⅅ', 'ⅆ', 'ⅇ', 'ⅈ', 'ⅉ'
402        ];
403
404  // Greek Alphabets
405  /**
406   * @type {Array.<string>}
407   */
408  this.capitalGreek =
409      [
410        'Α', 'Β', 'Γ', 'Δ', 'Ε', 'Ζ', 'Η', 'Θ', 'Ι', 'Κ', 'Λ', 'Μ', 'Ν',
411       'Ξ', 'Ο', 'Π', 'Ρ', 'Σ', 'Τ', 'Υ', 'Φ', 'Χ', 'Ψ', 'Ω'
412        ];
413  /**
414   * @type {Array.<string>}
415   */
416  this.smallGreek =
417      [
418        'α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ', 'ι', 'κ', 'λ', 'μ', 'ν',
419       'ξ', 'ο', 'π', 'ρ', 'ς', 'σ', 'τ', 'υ', 'φ', 'χ', 'ψ', 'ω'
420        ];
421  /**
422   * @type {Array.<string>}
423   */
424  this.capitalGreekBold =
425      [
426        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
427       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
428        ];
429  /**
430   * @type {Array.<string>}
431   */
432  this.smallGreekBold =
433      [
434        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
435       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
436        ];
437  /**
438   * @type {Array.<string>}
439   */
440  this.capitalGreekItalic =
441      [
442        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
443       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
444        ];
445  /**
446   * @type {Array.<string>}
447   */
448  this.smallGreekItalic =
449      [
450        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
451       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
452        ];
453  /**
454   * @type {Array.<string>}
455   */
456  this.capitalGreekSansSerifBold =
457      [
458        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
459       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
460        ];
461  /**
462   * @type {Array.<string>}
463   */
464  this.smallGreekSansSerifBold =
465      [
466        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��',
467       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
468        ];
469  /**
470   * @type {Array.<string>}
471   */
472  this.greekDoubleStruck =
473      [
474        'ℼ', 'ℽ', 'ℾ', 'ℿ'
475        ];
476
477  // Other alphabets.
478  /**
479   * @type {Array.<string>}
480   */
481  this.hebrewLetters =
482      [
483        'ℵ', 'ℶ', 'ℷ', 'ℸ'
484        ];
485
486  //Operator symbols
487  /**
488   * @type {Array.<string>}
489   */
490  this.additions =
491      [
492        '+', '±', '∓', '∔', '∧', '∨', '∩', '∪', '⊌', '⊓', '⊔', '⊝', '⊞',
493        '⊤', '⊥', '⊺', '⊻', '⊼', '⋄', '⋎', '⋏', '⋒', '⋓', '△', '▷', '▽',
494        '◁', '⩞', '⊕'
495        ];
496      /**
497       * @type {Array.<string>}
498           */
499  /**
500   * Invisible operator for plus.
501   * @type {string}
502   * @private
503   */
504  this.invisiblePlus_ = cvox.SemanticUtil.numberToUnicode(0x2064);
505  this.additions.push(this.invisiblePlus_);
506  /**
507   * @type {Array.<string>}
508   */
509  this.multiplications =
510      [
511        '†', '‡', '∐', '∗', '∘', '∙', '≀', '⊚', '⊛', '⊠', '⊡', '⋅', '⋆', '⋇',
512        '⋉', '⋊', '⋋', '⋌', '○'
513        ];
514  /**
515   * Invisible operator for multiplication.
516   * @type {string}
517   * @private
518   */
519  this.invisibleTimes_ = cvox.SemanticUtil.numberToUnicode(0x2062);
520  this.multiplications.push(this.invisibleTimes_);
521  /**
522   * @type {Array.<string>}
523   */
524  this.subtractions =
525      [
526        '-', '⁒', '⁻', '₋', '−', '∖', '∸', '≂', '⊖', '⊟', '➖', '⨩', '⨪',
527       '⨫', '⨬', '⨺', '⩁', '⩬', '﹣', '-', '‐', '‑'
528        ];
529  /**
530   * @type {Array.<string>}
531   */
532  this.divisions =
533      [
534        '/', '÷', '⁄', '∕', '⊘', '⟌', '⦼', '⨸'
535        ];
536  /**
537   * Invisible operator for function application.
538   * @type {string}
539   * @private
540   */
541  this.functionApplication_ = cvox.SemanticUtil.numberToUnicode(0x2061);
542
543  //Relation symbols
544  /**
545   * @type {Array.<string>}
546   */
547  this.equalities =
548      [
549        '=', '~', '⁼', '₌', '∼', '∽', '≃', '≅', '≈', '≊', '≋', '≌', '≍',
550       '≎', '≑', '≒', '≓', '≔', '≕', '≖', '≗', '≘', '≙', '≚', '≛', '≜',
551       '≝', '≞', '≟', '≡', '≣', '⧤', '⩦', '⩮', '⩯', '⩰', '⩱', '⩲', '⩳',
552       '⩴', '⩵', '⩶', '⩷', '⩸', '⋕', '⩭', '⩪', '⩫', '⩬', '﹦', '='
553        ];
554  /**
555   * @type {Array.<string>}
556   */
557  this.inequalities =
558      [
559        '<', '>', '≁', '≂', '≄', '≆', '≇', '≉', '≏', '≐', '≠', '≢', '≤',
560        '≥', '≦', '≧', '≨', '≩', '≪', '≫', '≬', '≭', '≮', '≯', '≰', '≱',
561        '≲', '≳', '≴', '≵', '≶', '≷', '≸', '≹', '≺', '≻', '≼', '≽', '≾',
562        '≿', '⊀', '⊁', '⋖', '⋗', '⋘', '⋙', '⋚', '⋛', '⋜', '⋝', '⋞', '⋟',
563        '⋠', '⋡', '⋢', '⋣', '⋤', '⋥', '⋦', '⋧', '⋨', '⋩', '⩹', '⩺', '⩻',
564        '⩼', '⩽', '⩾', '⩿', '⪀', '⪁', '⪂', '⪃', '⪄', '⪅', '⪆', '⪇', '⪈',
565        '⪉', '⪊', '⪋', '⪌', '⪍', '⪎', '⪏', '⪐', '⪑', '⪒', '⪓', '⪔', '⪕',
566        '⪖', '⪗', '⪘', '⪙', '⪚', '⪛', '⪜', '⪝', '⪞', '⪟', '⪠', '⪡', '⪢',
567        '⪣', '⪤', '⪥', '⪦', '⪧', '⪨', '⪩', '⪪', '⪫', '⪬', '⪭', '⪮', '⪯',
568        '⪰', '⪱', '⪲', '⪳', '⪴', '⪵', '⪶', '⪷', '⪸', '⪹', '⪺', '⪻', '⪼',
569        '⫷', '⫸', '⫹', '⫺', '⧀', '⧁', '﹤', '﹥', '<', '>'
570      ];
571  /**
572   * @type {Array.<string>}
573   */
574  this.relations =
575      [
576            // TODO (sorge): Add all the other relations.
577      ];
578  /**
579   * @type {Array.<string>}
580   */
581  this.arrows =
582      [
583        '←', '↑', '→', '↓', '↔', '↕', '↖', '↗', '↘', '↙', '↚', '↛', '↜',
584        '↝', '↞', '↟', '↠', '↡', '↢', '↣', '↤', '↥', '↦', '↧', '↨', '↩',
585        '↪', '↫', '↬', '↭', '↮', '↯', '↰', '↱', '↲', '↳', '↴', '↵', '↶',
586        '↷', '↸', '↹', '↺', '↻', '⇄', '⇅', '⇆', '⇇', '⇈', '⇉', '⇊', '⇍',
587        '⇎', '⇏', '⇐', '⇑', '⇒', '⇓', '⇔', '⇕', '⇖', '⇗', '⇘', '⇙', '⇚',
588        '⇛', '⇜', '⇝', '⇞', '⇟', '⇠', '⇡', '⇢', '⇣', '⇤', '⇥', '⇦', '⇧',
589        '⇨', '⇩', '⇪', '⇫', '⇬', '⇭', '⇮', '⇯', '⇰', '⇱', '⇲', '⇳', '⇴',
590        '⇵', '⇶', '⇷', '⇸', '⇹', '⇺', '⇻', '⇼', '⇽', '⇾', '⇿', '⌁', '⌃',
591        '⌄', '⌤', '⎋', '➔', '➘', '➙', '➚', '➛', '➜', '➝', '➞', '➟', '➠',
592        '➡', '➢', '➣', '➤', '➥', '➦', '➧', '➨', '➩', '➪', '➫', '➬', '➭',
593        '➮', '➯', '➱', '➲', '➳', '➴', '➵', '➶', '➷', '➸', '➹', '➺', '➻',
594        '➼', '➽', '➾', '⟰', '⟱', '⟲', '⟳', '⟴', '⟵', '⟶', '⟷', '⟸', '⟹',
595        '⟺', '⟻', '⟼', '⟽', '⟾', '⟿', '⤀', '⤁', '⤂', '⤃', '⤄', '⤅', '⤆',
596        '⤇', '⤈', '⤉', '⤊', '⤋', '⤌', '⤍', '⤎', '⤏', '⤐', '⤑', '⤒', '⤓',
597        '⤔', '⤕', '⤖', '⤗', '⤘', '⤙', '⤚', '⤛', '⤜', '⤝', '⤞', '⤟', '⤠',
598        '⤡', '⤢', '⤣', '⤤', '⤥', '⤦', '⤧', '⤨', '⤩', '⤪', '⤭', '⤮', '⤯',
599        '⤰', '⤱', '⤲', '⤳', '⤴', '⤵', '⤶', '⤷', '⤸', '⤹', '⤺', '⤻', '⤼',
600        '⤽', '⤾', '⤿', '⥀', '⥁', '⥂', '⥃', '⥄', '⥅', '⥆', '⥇', '⥈', '⥉',
601        '⥰', '⥱', '⥲', '⥳', '⥴', '⥵', '⥶', '⥷', '⥸', '⥹', '⥺', '⥻', '⦳',
602        '⦴', '⦽', '⧪', '⧬', '⧭', '⨗', '⬀', '⬁', '⬂', '⬃', '⬄', '⬅', '⬆',
603        '⬇', '⬈', '⬉', '⬊', '⬋', '⬌', '⬍', '⬎', '⬏', '⬐', '⬑', '⬰', '⬱',
604        '⬲', '⬳', '⬴', '⬵', '⬶', '⬷', '⬸', '⬹', '⬺', '⬻', '⬼', '⬽', '⬾',
605        '⬿', '⭀', '⭁', '⭂', '⭃', '⭄', '⭅', '⭆', '⭇', '⭈', '⭉', '⭊', '⭋',
606        '⭌', '←', '↑', '→', '↓',
607        // Harpoons
608        '↼', '↽', '↾', '↿', '⇀', '⇁', '⇂', '⇃', '⇋', '⇌', '⥊', '⥋', '⥌',
609        '⥍', '⥎', '⥏', '⥐', '⥑', '⥒', '⥓', '⥔', '⥕', '⥖', '⥗', '⥘', '⥙',
610        '⥚', '⥛', '⥜', '⥝', '⥞', '⥟', '⥠', '⥡', '⥢', '⥣', '⥤', '⥥', '⥦',
611        '⥧', '⥨', '⥩', '⥪', '⥫', '⥬', '⥭', '⥮', '⥯', '⥼', '⥽', '⥾', '⥿'
612      ];
613
614  //Big operation symbols
615  /**
616   * @type {Array.<string>}
617   */
618  this.sumOps =
619      [
620        '⅀', // double struck
621        '∏', '∐', '∑', '⋀', '⋁', '⋂', '⋃', '⨀', '⨁', '⨂', '⨃', '⨄', '⨅',
622        '⨆', '⨇', '⨈', '⨉', '⨊', '⨋', '⫼', '⫿'
623        ];
624  /**
625   * @type {Array.<string>}
626   */
627  this.intOps =
628      [
629        '∫', '∬', '∭', '∮', '∯', '∰', '∱', '∲', '∳', '⨌', '⨍', '⨎', '⨏',
630        '⨐', '⨑', '⨒', '⨓', '⨔', '⨕', '⨖', '⨗', '⨘', '⨙', '⨚', '⨛', '⨜'
631      ];
632  /**
633   * @type {Array.<string>}
634   */
635  this.prefixOps =
636      // TODO (sorge) Insert nabla, differential operators etc.
637      [
638        '∀', '∃'
639      ];
640  /**
641   * @type {Array.<string>}
642   */
643  this.operatorBits =
644      // TODO (sorge) What to do if single glyphs of big ops occur on their own.
645      [
646        '⌠', '⌡', '⎶', '⎪', '⎮', '⎯', '⎲', '⎳', '⎷'
647      ];
648
649  // Accents.
650  // TODO (sorge) Add accented characters.
651
652  // Numbers.
653  // Digits.
654  /**
655   * @type {Array.<string>}
656   */
657  this.digitsNormal =
658      [
659        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
660        ];
661  /**
662   * @type {Array.<string>}
663   */
664  this.digitsFullWidth =
665      [
666        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
667      ];
668  /**
669   * @type {Array.<string>}
670   */
671  this.digitsBold =
672      [
673        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
674        ];
675  /**
676   * @type {Array.<string>}
677   */
678  this.digitsDoubleStruck =
679      [
680        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
681        ];
682  /**
683   * @type {Array.<string>}
684   */
685  this.digitsSansSerif =
686      [
687        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
688        ];
689  /**
690   * @type {Array.<string>}
691   */
692  this.digitsSansSerifBold =
693      [
694        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
695        ];
696  /**
697   * @type {Array.<string>}
698   */
699  this.digitsMonospace =
700      [
701        '��', '��', '��', '��', '��', '��', '��', '��', '��', '��'
702        ];
703  /**
704   * @type {Array.<string>}
705   */
706  this.digitsSuperscript =
707      [
708        '²', '³', '¹', '⁰', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹'
709        ];
710  /**
711   * @type {Array.<string>}
712   */
713  this.digitsSubscript =
714      [
715        '₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉'
716        ];
717  /**
718   * @type {Array.<string>}
719   */
720  this.fractions =
721      [
722        '¼', '½', '¾', '⅐', '⅑', '⅒', '⅓', '⅔', '⅕', '⅖', '⅗', '⅘', '⅙',
723        '⅚', '⅛', '⅜', '⅝', '⅞', '⅟', '↉'
724      ];
725  /**
726   * @type {Array.<string>}
727   */
728  this.enclosedNumbers =
729      // Encircled numbers.
730      [
731        '①', '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩', '⑪', '⑫', '⑬',
732        '⑭', '⑮', '⑯', '⑰', '⑱', '⑲', '⑳', '⓪', '⓫', '⓬', '⓭', '⓮', '⓯',
733        '⓰', '⓱', '⓲', '⓳', '⓴', '⓵', '⓶', '⓷', '⓸', '⓹', '⓺', '⓻', '⓼',
734        '⓽', '⓾', '⓿', '❶', '❷', '❸', '❹', '❺', '❻', '❼', '❽', '❾', '❿',
735        '➀', '➁', '➂', '➃', '➄', '➅', '➆', '➇', '➈', '➉', '➊', '➋', '➌',
736        '➍', '➎', '➏', '➐', '➑', '➒', '➓', '㉈', '㉉', '㉊', '㉋', '㉌',
737        '㉍', '㉎', '㉏', '㉑', '㉒', '㉓', '㉔', '㉕', '㉖', '㉗', '㉘',
738        '㉙', '㉚', '㉛', '㉜', '㉝', '㉞', '㉟', '㊱', '㊲', '㊳', '㊴',
739        '㊵', '㊶', '㊷', '㊸', '㊹', '㊺', '㊻', '㊼', '㊽', '㊾', '㊿'];
740  /**
741   * @type {Array.<string>}
742   */
743  this.fencedNumbers =
744      // Numbers in Parenthesis.
745      [
746        '⑴', '⑵', '⑶', '⑷', '⑸', '⑹', '⑺', '⑻', '⑼', '⑽', '⑾', '⑿', '⒀',
747        '⒁', '⒂', '⒃', '⒄', '⒅', '⒆', '⒇'
748      ];
749  /**
750   * @type {Array.<string>}
751   */
752  this.punctuatedNumbers =
753      // Numbers with other punctuation.
754      ['⒈', '⒉', '⒊', '⒋', '⒌', '⒍', '⒎', '⒏', '⒐', '⒑', '⒒', '⒓', '⒔',
755       '⒕', '⒖', '⒗', '⒘', '⒙', '⒚', '⒛', // full stop.
756       '��', '��', '��', '��', '��', '��', '��', '��', '��', '��', '��' // comma.
757      ];
758  /** Array of all single digits.
759   * @type {Array.<string>}
760   */
761  this.digits = this.digitsNormal.concat(
762      this.digitsFullWidth, this.digitsBold, this.digitsDoubleStruck,
763      this.digitsSansSerif, this.digitsSansSerifBold, this.digitsMonospace);
764  /** Array of all non-digit number symbols.
765   * @type {Array.<string>}
766   */
767  this.numbers = this.fractions.concat(
768      this.digitsSuperscript, this.digitsSubscript,
769      this.enclosedNumbers, this.fencedNumbers, this.punctuatedNumbers);
770  /** Array of all number symbols.
771   * @type {Array.<string>}
772   */
773  this.allNumbers = this.digits.concat(this.numbers);
774
775  // Functions.
776  /**
777   * @type {Array.<string>}
778   */
779  this.trigonometricFunctions =
780      [
781        'cos', 'cot', 'csc', 'sec', 'sin', 'tan', 'arccos', 'arccot',
782        'arccsc', 'arcsec', 'arcsin', 'arctan'
783      ];
784  /**
785   * @type {Array.<string>}
786   */
787  this.hyperbolicFunctions =
788      [
789        'cosh', 'coth', 'csch', 'sech', 'sinh', 'tanh',
790        'arcosh', 'arcoth', 'arcsch', 'arsech', 'arsinh', 'artanh',
791        'arccosh', 'arccoth', 'arccsch', 'arcsech', 'arcsinh', 'arctanh'
792      ];
793  /**
794   * @type {Array.<string>}
795   */
796  this.algebraicFunctions =
797      [
798        'deg', 'det', 'dim', 'hom', 'ker', 'Tr', 'tr'
799      ];
800  /**
801   * @type {Array.<string>}
802   */
803  this.elementaryFunctions =
804      [
805        'log', 'ln', 'lg', 'exp', 'expt', 'gcd', 'gcd', 'arg', 'im', 're', 'Pr'
806      ];
807  /** All predefined prefix functions.
808   * @type {Array.<string>}
809   */
810  this.prefixFunctions = this.trigonometricFunctions.concat(
811      this.hyperbolicFunctions,
812      this.algebraicFunctions,
813      this.elementaryFunctions
814      );
815  /** Limit functions are handled separately as they can have lower (and upper)
816   * limiting expressions.
817   * @type {Array.<string>}
818   */
819  this.limitFunctions =
820      [
821        'inf', 'lim', 'liminf', 'limsup', 'max', 'min', 'sup', 'injlim',
822        'projlim'
823      ];
824  /**
825   * @type {Array.<string>}
826   */
827  this.infixFunctions =
828      [
829        'mod', 'rem'
830      ];
831  /**
832   * Default assignments of semantic attributes.
833   * @type  {Array.<{set: Array.<string>,
834   *         role: cvox.SemanticAttr.Role,
835   *         type: cvox.SemanticAttr.Type,
836   *         font: cvox.SemanticAttr.Font}>} The semantic meaning of the symbol.
837   * @private
838   */
839  this.symbolSetToSemantic_ = [
840    // Punctuation
841    {set: this.generalPunctuations,
842     type: cvox.SemanticAttr.Type.PUNCTUATION,
843     role: cvox.SemanticAttr.Role.UNKNOWN
844    },
845    {set: this.ellipses,
846     type: cvox.SemanticAttr.Type.PUNCTUATION,
847     role: cvox.SemanticAttr.Role.ELLIPSIS
848    },
849    {set: this.fullStops,
850     type: cvox.SemanticAttr.Type.PUNCTUATION,
851     role: cvox.SemanticAttr.Role.FULLSTOP
852    },
853    {set: this.dashes,
854     type: cvox.SemanticAttr.Type.PUNCTUATION,
855     role: cvox.SemanticAttr.Role.DASH
856    },
857    {set: this.primes,
858     type: cvox.SemanticAttr.Type.PUNCTUATION,
859     role: cvox.SemanticAttr.Role.PRIME
860    },
861    // Fences
862    {set: this.leftFences,
863     type: cvox.SemanticAttr.Type.FENCE,
864     role: cvox.SemanticAttr.Role.OPEN
865    },
866    {set: this.rightFences,
867     type: cvox.SemanticAttr.Type.FENCE,
868     role: cvox.SemanticAttr.Role.CLOSE
869    },
870    {set: this.topFences,
871     type: cvox.SemanticAttr.Type.FENCE,
872     role: cvox.SemanticAttr.Role.TOP
873    },
874    {set: this.bottomFences,
875     type: cvox.SemanticAttr.Type.FENCE,
876     role: cvox.SemanticAttr.Role.BOTTOM
877    },
878    {set: this.neutralFences,
879     type: cvox.SemanticAttr.Type.FENCE,
880     role: cvox.SemanticAttr.Role.NEUTRAL
881    },
882    // Single characters.
883    // Latin alphabets.
884    {set: this.smallLatin,
885     type: cvox.SemanticAttr.Type.IDENTIFIER,
886     role: cvox.SemanticAttr.Role.LATINLETTER,
887     font: cvox.SemanticAttr.Font.NORMAL
888    },
889    {set: this.capitalLatin,
890     type: cvox.SemanticAttr.Type.IDENTIFIER,
891     role: cvox.SemanticAttr.Role.LATINLETTER,
892     font: cvox.SemanticAttr.Font.NORMAL
893    },
894    {set: this.smallLatinFullWidth,
895     type: cvox.SemanticAttr.Type.IDENTIFIER,
896     role: cvox.SemanticAttr.Role.LATINLETTER,
897     font: cvox.SemanticAttr.Font.NORMAL
898    },
899    {set: this.capitalLatinFullWidth,
900     type: cvox.SemanticAttr.Type.IDENTIFIER,
901     role: cvox.SemanticAttr.Role.LATINLETTER,
902     font: cvox.SemanticAttr.Font.NORMAL
903    },
904    {set: this.smallLatinBold,
905     type: cvox.SemanticAttr.Type.IDENTIFIER,
906     role: cvox.SemanticAttr.Role.LATINLETTER,
907     font: cvox.SemanticAttr.Font.BOLD
908    },
909    {set: this.capitalLatinBold,
910     type: cvox.SemanticAttr.Type.IDENTIFIER,
911     role: cvox.SemanticAttr.Role.LATINLETTER,
912     font: cvox.SemanticAttr.Font.BOLD
913    },
914    {set: this.smallLatinItalic,
915     type: cvox.SemanticAttr.Type.IDENTIFIER,
916     role: cvox.SemanticAttr.Role.LATINLETTER,
917     font: cvox.SemanticAttr.Font.ITALIC
918    },
919    {set: this.capitalLatinItalic,
920     type: cvox.SemanticAttr.Type.IDENTIFIER,
921     role: cvox.SemanticAttr.Role.LATINLETTER,
922     font: cvox.SemanticAttr.Font.ITALIC
923    },
924    {set: this.smallLatinScript,
925     type: cvox.SemanticAttr.Type.IDENTIFIER,
926     role: cvox.SemanticAttr.Role.LATINLETTER,
927     font: cvox.SemanticAttr.Font.SCRIPT
928    },
929    {set: this.capitalLatinScript,
930     type: cvox.SemanticAttr.Type.IDENTIFIER,
931     role: cvox.SemanticAttr.Role.LATINLETTER,
932     font: cvox.SemanticAttr.Font.SCRIPT
933    },
934    {set: this.smallLatinBoldScript,
935     type: cvox.SemanticAttr.Type.IDENTIFIER,
936     role: cvox.SemanticAttr.Role.LATINLETTER,
937     font: cvox.SemanticAttr.Font.BOLDSCRIPT
938    },
939    {set: this.capitalLatinBoldScript,
940     type: cvox.SemanticAttr.Type.IDENTIFIER,
941     role: cvox.SemanticAttr.Role.LATINLETTER,
942     font: cvox.SemanticAttr.Font.BOLDSCRIPT
943    },
944    {set: this.smallLatinFraktur,
945     type: cvox.SemanticAttr.Type.IDENTIFIER,
946     role: cvox.SemanticAttr.Role.LATINLETTER,
947     font: cvox.SemanticAttr.Font.FRAKTUR
948    },
949    {set: this.capitalLatinFraktur,
950     type: cvox.SemanticAttr.Type.IDENTIFIER,
951     role: cvox.SemanticAttr.Role.LATINLETTER,
952     font: cvox.SemanticAttr.Font.FRAKTUR
953    },
954    {set: this.smallLatinDoubleStruck,
955     type: cvox.SemanticAttr.Type.IDENTIFIER,
956     role: cvox.SemanticAttr.Role.LATINLETTER,
957     font: cvox.SemanticAttr.Font.DOUBLESTRUCK
958    },
959    {set: this.capitalLatinDoubleStruck,
960     type: cvox.SemanticAttr.Type.IDENTIFIER,
961     role: cvox.SemanticAttr.Role.LATINLETTER,
962     font: cvox.SemanticAttr.Font.DOUBLESTRUCK
963    },
964    {set: this.smallLatinBoldFraktur,
965     type: cvox.SemanticAttr.Type.IDENTIFIER,
966     role: cvox.SemanticAttr.Role.LATINLETTER,
967     font: cvox.SemanticAttr.Font.BOLDFRAKTUR
968    },
969    {set: this.capitalLatinBoldFraktur,
970     type: cvox.SemanticAttr.Type.IDENTIFIER,
971     role: cvox.SemanticAttr.Role.LATINLETTER,
972     font: cvox.SemanticAttr.Font.BOLDFRAKTUR
973    },
974    {set: this.smallLatinSansSerif,
975     type: cvox.SemanticAttr.Type.IDENTIFIER,
976     role: cvox.SemanticAttr.Role.LATINLETTER,
977     font: cvox.SemanticAttr.Font.SANSSERIF
978    },
979    {set: this.capitalLatinSansSerif,
980     type: cvox.SemanticAttr.Type.IDENTIFIER,
981     role: cvox.SemanticAttr.Role.LATINLETTER,
982     font: cvox.SemanticAttr.Font.SANSSERIF
983    },
984    {set: this.smallLatinSansSerifBold,
985     type: cvox.SemanticAttr.Type.IDENTIFIER,
986     role: cvox.SemanticAttr.Role.LATINLETTER,
987     font: cvox.SemanticAttr.Font.SANSSERIFBOLD
988    },
989    {set: this.capitalLatinSansSerifBold,
990     type: cvox.SemanticAttr.Type.IDENTIFIER,
991     role: cvox.SemanticAttr.Role.LATINLETTER,
992     font: cvox.SemanticAttr.Font.SANSSERIFBOLD
993    },
994    {set: this.smallLatinSansSerifItalic,
995     type: cvox.SemanticAttr.Type.IDENTIFIER,
996     role: cvox.SemanticAttr.Role.LATINLETTER,
997     font: cvox.SemanticAttr.Font.SANSSERIFITALIC
998    },
999    {set: this.capitalLatinSansSerifItalic,
1000     type: cvox.SemanticAttr.Type.IDENTIFIER,
1001     role: cvox.SemanticAttr.Role.LATINLETTER,
1002     font: cvox.SemanticAttr.Font.SANSSERIFITALIC
1003    },
1004    {set: this.smallLatinMonospace,
1005     type: cvox.SemanticAttr.Type.IDENTIFIER,
1006     role: cvox.SemanticAttr.Role.LATINLETTER,
1007     font: cvox.SemanticAttr.Font.MONOSPACE
1008    },
1009    {set: this.capitalLatinMonospace,
1010     type: cvox.SemanticAttr.Type.IDENTIFIER,
1011     role: cvox.SemanticAttr.Role.LATINLETTER,
1012     font: cvox.SemanticAttr.Font.MONOSPACE
1013    },
1014    {set: this.latinDoubleStruckItalic,
1015     type: cvox.SemanticAttr.Type.IDENTIFIER,
1016     role: cvox.SemanticAttr.Role.LATINLETTER,
1017     font: cvox.SemanticAttr.Font.DOUBLESTRUCKITALIC
1018    },
1019    // Greek alphabets.
1020    {set: this.smallGreek,
1021     type: cvox.SemanticAttr.Type.IDENTIFIER,
1022     role: cvox.SemanticAttr.Role.GREEKLETTER,
1023     font: cvox.SemanticAttr.Font.NORMAL
1024    },
1025    {set: this.capitalGreek,
1026     type: cvox.SemanticAttr.Type.IDENTIFIER,
1027     role: cvox.SemanticAttr.Role.GREEKLETTER,
1028     font: cvox.SemanticAttr.Font.NORMAL
1029    },
1030    {set: this.smallGreekBold,
1031     type: cvox.SemanticAttr.Type.IDENTIFIER,
1032     role: cvox.SemanticAttr.Role.GREEKLETTER,
1033     font: cvox.SemanticAttr.Font.BOLD
1034    },
1035    {set: this.capitalGreekBold,
1036     type: cvox.SemanticAttr.Type.IDENTIFIER,
1037     role: cvox.SemanticAttr.Role.GREEKLETTER,
1038     font: cvox.SemanticAttr.Font.BOLD
1039    },
1040    {set: this.smallGreekItalic,
1041     type: cvox.SemanticAttr.Type.IDENTIFIER,
1042     role: cvox.SemanticAttr.Role.GREEKLETTER,
1043     font: cvox.SemanticAttr.Font.ITALIC
1044    },
1045    {set: this.capitalGreekItalic,
1046     type: cvox.SemanticAttr.Type.IDENTIFIER,
1047     role: cvox.SemanticAttr.Role.GREEKLETTER,
1048     font: cvox.SemanticAttr.Font.ITALIC
1049    },
1050    {set: this.smallGreekSansSerifBold,
1051     type: cvox.SemanticAttr.Type.IDENTIFIER,
1052     role: cvox.SemanticAttr.Role.GREEKLETTER,
1053     font: cvox.SemanticAttr.Font.SANSSERIFBOLD
1054    },
1055    {set: this.capitalGreekSansSerifBold,
1056     type: cvox.SemanticAttr.Type.IDENTIFIER,
1057     role: cvox.SemanticAttr.Role.GREEKLETTER,
1058     font: cvox.SemanticAttr.Font.SANSSERIFBOLD
1059    },
1060    {set: this.greekDoubleStruck,
1061     type: cvox.SemanticAttr.Type.IDENTIFIER,
1062     role: cvox.SemanticAttr.Role.GREEKLETTER,
1063     font: cvox.SemanticAttr.Font.DOUBLESTRUCK
1064    },
1065    // Other alphabets.
1066    {set: this.hebrewLetters,
1067     type: cvox.SemanticAttr.Type.IDENTIFIER,
1068     role: cvox.SemanticAttr.Role.OTHERLETTER,
1069     font: cvox.SemanticAttr.Font.NORMAL
1070    },
1071    // Numbers.
1072    {set: this.digitsNormal,
1073     type: cvox.SemanticAttr.Type.NUMBER,
1074     role: cvox.SemanticAttr.Role.INTEGER,
1075     font: cvox.SemanticAttr.Font.NORMAL
1076    },
1077    {set: this.digitsFullWidth,
1078     type: cvox.SemanticAttr.Type.NUMBER,
1079     role: cvox.SemanticAttr.Role.INTEGER,
1080     font: cvox.SemanticAttr.Font.NORMAL
1081    },
1082    {set: this.digitsBold,
1083     type: cvox.SemanticAttr.Type.NUMBER,
1084     role: cvox.SemanticAttr.Role.INTEGER,
1085     font: cvox.SemanticAttr.Font.BOLD
1086    },
1087    {set: this.digitsDoubleStruck,
1088     type: cvox.SemanticAttr.Type.NUMBER,
1089     role: cvox.SemanticAttr.Role.INTEGER,
1090     font: cvox.SemanticAttr.Font.DOUBLESTRUCK
1091    },
1092    {set: this.digitsSansSerif,
1093     type: cvox.SemanticAttr.Type.NUMBER,
1094     role: cvox.SemanticAttr.Role.INTEGER,
1095     font: cvox.SemanticAttr.Font.SANSSERIF
1096    },
1097    {set: this.digitsSansSerifBold,
1098     type: cvox.SemanticAttr.Type.NUMBER,
1099     role: cvox.SemanticAttr.Role.INTEGER,
1100     font: cvox.SemanticAttr.Font.SANSSERIFBOLD
1101    },
1102    {set: this.digitsMonospace,
1103     type: cvox.SemanticAttr.Type.NUMBER,
1104     role: cvox.SemanticAttr.Role.INTEGER,
1105     font: cvox.SemanticAttr.Font.MONOSPACE
1106    },
1107   {set: this.numbers,
1108     type: cvox.SemanticAttr.Type.NUMBER,
1109     role: cvox.SemanticAttr.Role.INTEGER
1110    },
1111    // Operators.
1112    {set: this.additions,
1113     type: cvox.SemanticAttr.Type.OPERATOR,
1114     role: cvox.SemanticAttr.Role.ADDITION
1115    },
1116    {set: this.multiplications,
1117     type: cvox.SemanticAttr.Type.OPERATOR,
1118     role: cvox.SemanticAttr.Role.MULTIPLICATION
1119    },
1120    {set: this.subtractions,
1121     type: cvox.SemanticAttr.Type.OPERATOR,
1122     role: cvox.SemanticAttr.Role.SUBTRACTION
1123    },
1124    {set: this.divisions,
1125     type: cvox.SemanticAttr.Type.OPERATOR,
1126     role: cvox.SemanticAttr.Role.DIVISION
1127    },
1128    {set: this.prefixOps,
1129     type: cvox.SemanticAttr.Type.PREFIXOP,
1130     role: cvox.SemanticAttr.Role.PREFIXFUNC
1131    },
1132    // Relations
1133    {set: this.equalities,
1134     type: cvox.SemanticAttr.Type.RELATION,
1135     role: cvox.SemanticAttr.Role.EQUALITY
1136    },
1137    {set: this.inequalities,
1138     type: cvox.SemanticAttr.Type.RELATION,
1139     role: cvox.SemanticAttr.Role.INEQUALITY
1140    },
1141    {set: this.relations,
1142     type: cvox.SemanticAttr.Type.RELATION,
1143     role: cvox.SemanticAttr.Role.UNKNOWN
1144    },
1145    {set: this.arrows,
1146     type: cvox.SemanticAttr.Type.RELATION,
1147     role: cvox.SemanticAttr.Role.ARROW
1148    },
1149    // Large operators
1150    {set: this.sumOps,
1151     type: cvox.SemanticAttr.Type.LARGEOP,
1152     role: cvox.SemanticAttr.Role.SUM},
1153    {set: this.intOps,
1154     type: cvox.SemanticAttr.Type.LARGEOP,
1155     role: cvox.SemanticAttr.Role.INTEGRAL},
1156    // Functions
1157    {set: this.limitFunctions,
1158     type: cvox.SemanticAttr.Type.FUNCTION,
1159     role: cvox.SemanticAttr.Role.LIMFUNC},
1160    {set: this.prefixFunctions,
1161     type: cvox.SemanticAttr.Type.FUNCTION,
1162     role: cvox.SemanticAttr.Role.PREFIXFUNC},
1163    {set: this.infixFunctions,
1164     type: cvox.SemanticAttr.Type.OPERATOR,
1165     role: cvox.SemanticAttr.Role.MULTIPLICATION
1166    }
1167    // TODO (sorge) Add some of the remaining elements.
1168  ];
1169};
1170goog.addSingletonGetter(cvox.SemanticAttr);
1171
1172
1173/**
1174 * Union type of semantic attributes.
1175 * @typedef {cvox.SemanticAttr.Type|cvox.SemanticAttr.Role}
1176 */
1177cvox.SemanticAttr.Attr;
1178
1179
1180/**
1181 * Mapping for types of elements.
1182 * @enum {string}
1183 */
1184cvox.SemanticAttr.Type = {
1185  // Leafs.
1186  // Punctuation like comma, dot, ellipses.
1187  PUNCTUATION: 'punctuation',
1188  // Fence symbol.
1189  FENCE: 'fence',
1190  // One or several digits, plus some punctuation.
1191  NUMBER: 'number',
1192  // Single or multiple letters.
1193  IDENTIFIER: 'identifier',
1194  // Regular text in a math expression.
1195  TEXT: 'text',
1196  // e.g. +, *.
1197  OPERATOR: 'operator',
1198  // Relation symbol, e.g. equals.
1199  RELATION: 'relation',
1200  // e.g. Sum, product, integral.
1201  LARGEOP: 'largeop',
1202  // Some named function.
1203  FUNCTION: 'function',
1204
1205  // Branches.
1206  // Compound Symbols.
1207  ACCENT: 'accent',
1208  FENCED: 'fenced',
1209  FRACTION: 'fraction',
1210  PUNCTUATED: 'punctuated',
1211
1212  // Relations.
1213  // Relation sequence of a single relation.
1214  RELSEQ: 'relseq',
1215  // Relation sequence containing at least two different relations.
1216  MULTIREL: 'multirel',
1217  // Operations.
1218  INFIXOP: 'infixop',
1219  PREFIXOP: 'prefixop',
1220  POSTFIXOP: 'postfixop',
1221
1222  // Function and Bigop Application.
1223  APPL: 'appl',
1224  INTEGRAL: 'integral',
1225  BIGOP: 'bigop',
1226
1227  SQRT: 'sqrt',
1228  ROOT: 'root',
1229  // These are bigops or functions with limits.
1230  LIMUPPER: 'limupper',
1231  LIMLOWER: 'limlower',
1232  LIMBOTH: 'limboth',
1233  SUBSCRIPT: 'subscript',
1234  SUPERSCRIPT: 'superscript',
1235  UNDERSCORE: 'underscore',
1236  OVERSCORE: 'overscore',
1237
1238  // Tables and their elements.
1239  TABLE: 'table',
1240  MULTILINE: 'multiline',
1241  MATRIX: 'matrix',
1242  VECTOR: 'vector',
1243  CASES: 'cases',
1244  ROW: 'row',
1245  // Lines are effectively single cell rows.
1246  LINE: 'line',
1247  CELL: 'cell',
1248
1249  // General.
1250  UNKNOWN: 'unknown',
1251  EMPTY: 'empty'
1252};
1253
1254
1255/**
1256 * Mapping for roles of nodes.
1257 * Roles are more specific than types.
1258 * @enum {string}
1259 */
1260cvox.SemanticAttr.Role = {
1261  // Punctuation.
1262  ELLIPSIS: 'ellipsis',
1263  FULLSTOP: 'fullstop',
1264  DASH: 'dash',
1265  PRIME: 'prime',   // Superscript.
1266  VBAR: 'vbar',  // A vertical bar.
1267  OPENFENCE: 'openfence',
1268  CLOSEFENCE: 'closefence',
1269  APPLICATION: 'application', // Function Application.
1270
1271  // Fences.
1272  OPEN: 'open',
1273  CLOSE: 'close',
1274  TOP: 'top',
1275  BOTTOM: 'bottom',
1276  NEUTRAL: 'neutral',
1277
1278  // Letters.
1279  LATINLETTER: 'latinletter',
1280  GREEKLETTER: 'greekletter',
1281  OTHERLETTER: 'otherletter',
1282
1283  // Numbers.
1284  INTEGER: 'integer',
1285  FLOAT: 'float',
1286  OTHERNUMBER: 'othernumber',
1287
1288  // Accents.
1289  MULTIACCENT: 'multiaccent',
1290  OVERACCENT: 'overaccent',
1291  UNDERACCENT: 'underaccent',
1292
1293  // Fenced.
1294  LEFTRIGHT: 'leftright',
1295  ABOVEBELOW: 'abovebelow',
1296
1297  // Punctuated elements.
1298  SEQUENCE: 'sequence',
1299  ENDPUNCT: 'endpunct',
1300  STARTPUNCT: 'startpunct',
1301
1302  // Operators.
1303  NEGATIVE: 'negative',
1304  NEGATION: 'negation',
1305  MULTIOP: 'multiop',
1306
1307  // Functions.
1308  LIMFUNC: 'limit function',
1309  INFIXFUNC: 'infix function',
1310  PREFIXFUNC: 'prefix function',
1311  POSTFIXFUNC: 'postfix function',
1312
1313  // Large operators.
1314  SUM: 'sum',
1315  INTEGRAL: 'integral',
1316
1317  // Binary operations.
1318  ADDITION: 'addition',
1319  MULTIPLICATION: 'multiplication',
1320  DIVISION: 'division',
1321  SUBTRACTION: 'subtraction',
1322  IMPLICIT: 'implicit',
1323
1324  // Relations.
1325  EQUALITY: 'equality',
1326  INEQUALITY: 'inequality',
1327  ELEMENT: 'element',
1328  BINREL: 'binrel',
1329  ARROW: 'arrow',
1330
1331  // Roles of rows, lines, cells.
1332  // They mirror the different types for tables.
1333  MULTILINE: 'multiline',
1334  MATRIX: 'matrix',
1335  VECTOR: 'vector',
1336  CASES: 'cases',
1337  TABLE: 'table',
1338
1339  // General
1340  UNKNOWN: 'unknown'
1341};
1342
1343
1344/**
1345 * Mapping for font annotations. (Taken from MathML2 section 3.2.2, with the
1346 * exception of double-struck-italic.)
1347 * @enum {string}
1348 */
1349cvox.SemanticAttr.Font = {
1350  BOLD: 'bold',
1351  BOLDFRAKTUR: 'bold-fraktur',
1352  BOLDITALIC: 'bold-italic',
1353  BOLDSCRIPT: 'bold-script',
1354  DOUBLESTRUCK: 'double-struck',
1355  DOUBLESTRUCKITALIC: 'double-struck-italic',
1356  FRAKTUR: 'fraktur',
1357  ITALIC: 'italic',
1358  MONOSPACE: 'monospace',
1359  NORMAL: 'normal',
1360  SCRIPT: 'script',
1361  SANSSERIF: 'sans-serif',
1362  SANSSERIFITALIC: 'sans-serif-italic',
1363  SANSSERIFBOLD: 'sans-serif-bold',
1364  SANSSERIFBOLDITALIC: 'sans-serif-bold-italic',
1365  UNKNOWN: 'unknown'
1366};
1367
1368
1369/**
1370 * Lookup the semantic type of a symbol.
1371 * @param {string} symbol The symbol to which we want to determine the type.
1372 * @return {cvox.SemanticAttr.Type} The semantic type of the symbol.
1373 */
1374cvox.SemanticAttr.prototype.lookupType = function(symbol) {
1375  return cvox.SemanticAttr.Type.UNKNOWN;
1376};
1377
1378
1379/**
1380 * Lookup the semantic role of a symbol.
1381 * @param {string} symbol The symbol to which we want to determine the role.
1382 * @return {cvox.SemanticAttr.Role} The semantic role of the symbol.
1383 */
1384cvox.SemanticAttr.prototype.lookupRole = function(symbol) {
1385  return cvox.SemanticAttr.Role.UNKNOWN;
1386};
1387
1388
1389/**
1390 * Lookup the semantic meaning of a symbol in terms of type and role.
1391 * @param {string} symbol The symbol to which we want to determine the meaning.
1392 * @return {{role: cvox.SemanticAttr.Role,
1393 *           type: cvox.SemanticAttr.Type}} The semantic meaning of the symbol.
1394 */
1395cvox.SemanticAttr.lookupMeaning = function(symbol) {
1396  return cvox.SemanticAttr.getInstance().lookupMeaning_(symbol);
1397};
1398
1399
1400/**
1401 * String representation of the invisible times unicode character.
1402 * @return {string} The invisible times character.
1403 */
1404cvox.SemanticAttr.invisibleTimes = function() {
1405  return cvox.SemanticAttr.getInstance().invisibleTimes_;
1406};
1407
1408
1409/**
1410 * String representation of the invisible comma unicode character.
1411 * @return {string} The invisible comma character.
1412 */
1413cvox.SemanticAttr.invisibleComma = function() {
1414  return cvox.SemanticAttr.getInstance().invisibleComma_;
1415};
1416
1417
1418/**
1419 * String representation of the function application character.
1420 * @return {string} The invisible function application character.
1421 */
1422cvox.SemanticAttr.functionApplication = function() {
1423  return cvox.SemanticAttr.getInstance().functionApplication_;
1424};
1425
1426
1427/**
1428 * Decide when two fences match. Currently we match any right to left
1429 * or bottom to top fence and neutral to neutral.
1430 * @param {cvox.SemanticAttr.Role} open Opening fence.
1431 * @param {cvox.SemanticAttr.Role} close Closing fence.
1432 * @return {boolean} True if the fences are matching.
1433 */
1434cvox.SemanticAttr.isMatchingFenceRole = function(open, close) {
1435  return (open == cvox.SemanticAttr.Role.OPEN &&
1436      close == cvox.SemanticAttr.Role.CLOSE) ||
1437          (open == cvox.SemanticAttr.Role.NEUTRAL &&
1438              close == cvox.SemanticAttr.Role.NEUTRAL) ||
1439                  (open == cvox.SemanticAttr.Role.TOP &&
1440                      close == cvox.SemanticAttr.Role.BOTTOM);
1441};
1442
1443
1444/**
1445 * Decide when opening and closing fences match. For neutral fences they have to
1446 * be the same.
1447 * @param {string} open Opening fence.
1448 * @param {string} close Closing fence.
1449 * @return {boolean} True if the fences are matching.
1450 */
1451cvox.SemanticAttr.isMatchingFence = function(open, close) {
1452  return cvox.SemanticAttr.getInstance().isMatchingFence_(open, close);
1453};
1454
1455
1456/**
1457 * Determines if a fence is an opening fence.
1458 * @param {cvox.SemanticAttr.Role} fence Opening fence.
1459 * @return {boolean} True if the fence is open or neutral.
1460 */
1461cvox.SemanticAttr.isOpeningFence = function(fence) {
1462  return (fence == cvox.SemanticAttr.Role.OPEN ||
1463          fence == cvox.SemanticAttr.Role.NEUTRAL);
1464};
1465
1466
1467/**
1468 * Determines if a fence is a closing fence.
1469 * @param {cvox.SemanticAttr.Role} fence Closing fence.
1470 * @return {boolean} True if the fence is close or neutral.
1471 */
1472cvox.SemanticAttr.isClosingFence = function(fence) {
1473  return (fence == cvox.SemanticAttr.Role.CLOSE ||
1474          fence == cvox.SemanticAttr.Role.NEUTRAL);
1475};
1476
1477
1478// TODO (sorge) Make this depended on position in the alphabets.
1479/**
1480 * Check if a character is a small 'd' in some font.
1481 * @param {!string} chr The character string.
1482 * @return {boolean} True if the character is indeed a single small d.
1483 */
1484cvox.SemanticAttr.isCharacterD = function(chr) {
1485  var Ds = ['d', 'ⅆ', 'd', '��', '��', '��', '��', '��',
1486            '��', '��', '��', '��', '��', '��'];
1487  return Ds.indexOf(chr) != -1;
1488};
1489
1490
1491/**
1492 * Decide when opening and closing fences match. For neutral fences they have to
1493 * be the same.
1494 * @param {!string} open Opening fence.
1495 * @param {!string} close Closing fence.
1496 * @return {boolean} True if the fences are matching.
1497 * @private
1498 */
1499cvox.SemanticAttr.prototype.isMatchingFence_ = function(open, close) {
1500  if (this.neutralFences.indexOf(open) != -1) {
1501    return open == close;
1502  }
1503  return this.openClosePairs[open] == close ||
1504      this.topBottomPairs[open] == close;
1505};
1506
1507
1508/**
1509 * Lookup the semantic meaning of a symbol in terms of type and role.
1510 * @param {!string} symbol The symbol to which we want to determine the meaning.
1511 * @return {{role: cvox.SemanticAttr.Role,
1512 *           type: cvox.SemanticAttr.Type,
1513 *           font: cvox.SemanticAttr.Font}} The semantic meaning of the symbol.
1514 * @private
1515 */
1516cvox.SemanticAttr.prototype.lookupMeaning_ = function(symbol) {
1517  for (var i = 0, set; set = this.symbolSetToSemantic_[i]; i++) {
1518    if (set.set.indexOf(symbol) != -1) {
1519      return {role: set.role || cvox.SemanticAttr.Role.UNKNOWN,
1520              type: set.type || cvox.SemanticAttr.Type.UNKNOWN,
1521              font: set.font || cvox.SemanticAttr.Font.UNKNOWN
1522             };
1523    }
1524  }
1525  return {role: cvox.SemanticAttr.Role.UNKNOWN,
1526          type: cvox.SemanticAttr.Type.UNKNOWN,
1527          font: cvox.SemanticAttr.Font.UNKNOWN
1528         };
1529};
1530