asciimath 1.0.9 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +20 -0
  3. data/AST.adoc +457 -0
  4. data/CHANGELOG.adoc +47 -1
  5. data/Gemfile +5 -0
  6. data/README.adoc +68 -4
  7. data/asciimath.gemspec +3 -6
  8. data/dump_symbol_table.rb +46 -0
  9. data/lib/asciimath.rb +5 -4
  10. data/lib/asciimath/ast.rb +456 -0
  11. data/lib/asciimath/cli.rb +4 -1
  12. data/lib/asciimath/color_table.rb +21 -0
  13. data/lib/asciimath/html.rb +128 -112
  14. data/lib/asciimath/latex.rb +399 -0
  15. data/lib/asciimath/markup.rb +509 -0
  16. data/lib/asciimath/mathml.rb +206 -87
  17. data/lib/asciimath/parser.rb +510 -350
  18. data/lib/asciimath/symbol_table.rb +25 -0
  19. data/lib/asciimath/version.rb +1 -1
  20. data/spec/ast.rb +144 -0
  21. data/spec/customisation_spec.rb +28 -0
  22. data/spec/parser_spec.rb +623 -165
  23. data/spec/schema/mathml2/common/common-attribs.xsd +41 -0
  24. data/spec/schema/mathml2/common/math.xsd +126 -0
  25. data/spec/schema/mathml2/common/xlink-href.xsd +20 -0
  26. data/spec/schema/mathml2/content/arith.xsd +90 -0
  27. data/spec/schema/mathml2/content/calculus.xsd +146 -0
  28. data/spec/schema/mathml2/content/common-attrib.xsd +30 -0
  29. data/spec/schema/mathml2/content/constants.xsd +83 -0
  30. data/spec/schema/mathml2/content/constructs.xsd +260 -0
  31. data/spec/schema/mathml2/content/elementary-functions.xsd +117 -0
  32. data/spec/schema/mathml2/content/functions.xsd +73 -0
  33. data/spec/schema/mathml2/content/linear-algebra.xsd +173 -0
  34. data/spec/schema/mathml2/content/logic.xsd +53 -0
  35. data/spec/schema/mathml2/content/relations.xsd +55 -0
  36. data/spec/schema/mathml2/content/semantics.xsd +85 -0
  37. data/spec/schema/mathml2/content/sets.xsd +236 -0
  38. data/spec/schema/mathml2/content/statistics.xsd +136 -0
  39. data/spec/schema/mathml2/content/tokens.xsd +120 -0
  40. data/spec/schema/mathml2/content/vector-calculus.xsd +88 -0
  41. data/spec/schema/mathml2/mathml2.xsd +59 -0
  42. data/spec/schema/mathml2/presentation/action.xsd +44 -0
  43. data/spec/schema/mathml2/presentation/characters.xsd +37 -0
  44. data/spec/schema/mathml2/presentation/common-attribs.xsd +113 -0
  45. data/spec/schema/mathml2/presentation/common-types.xsd +103 -0
  46. data/spec/schema/mathml2/presentation/error.xsd +40 -0
  47. data/spec/schema/mathml2/presentation/layout.xsd +195 -0
  48. data/spec/schema/mathml2/presentation/scripts.xsd +186 -0
  49. data/spec/schema/mathml2/presentation/space.xsd +52 -0
  50. data/spec/schema/mathml2/presentation/style.xsd +69 -0
  51. data/spec/schema/mathml2/presentation/table.xsd +216 -0
  52. data/spec/schema/mathml2/presentation/tokens.xsd +124 -0
  53. data/spec/schema/mathml3/mathml3-common.xsd +99 -0
  54. data/spec/schema/mathml3/mathml3-content.xsd +684 -0
  55. data/spec/schema/mathml3/mathml3-presentation.xsd +2151 -0
  56. data/spec/schema/mathml3/mathml3-strict-content.xsd +186 -0
  57. data/spec/schema/mathml3/mathml3.xsd +9 -0
  58. metadata +88 -48
  59. data/.travis.yml +0 -18
@@ -0,0 +1,509 @@
1
+ require_relative 'ast'
2
+ require_relative 'symbol_table'
3
+
4
+ module AsciiMath
5
+ class MarkupBuilder
6
+ # Operation symbols
7
+ def self.add_default_display_symbols(b, fix_phi: true)
8
+ b.add(:plus, '+', :operator)
9
+ b.add(:minus, "\u2212", :operator)
10
+ b.add(:cdot, "\u22C5", :operator)
11
+ b.add(:ast, "\u002A", :operator)
12
+ b.add(:star, "\u22C6", :operator)
13
+ b.add(:slash, '/', :operator)
14
+ b.add(:backslash, '\\', :operator)
15
+ b.add(:setminus, '\\', :operator)
16
+ b.add(:times, "\u00D7", :operator)
17
+ b.add(:ltimes, "\u22C9", :operator)
18
+ b.add(:rtimes, "\u22CA", :operator)
19
+ b.add(:bowtie, "\u22C8", :operator)
20
+ b.add(:div, "\u00F7", :operator)
21
+ b.add(:circ, "\u26AC", :operator)
22
+ b.add(:oplus, "\u2295", :operator)
23
+ b.add(:otimes, "\u2297", :operator)
24
+ b.add(:odot, "\u2299", :operator)
25
+ b.add(:sum, "\u2211", :operator, :underover => true)
26
+ b.add(:prod, "\u220F", :operator, :underover => true)
27
+ b.add(:wedge, "\u2227", :operator)
28
+ b.add(:bigwedge, "\u22C0", :operator, :underover => true)
29
+ b.add(:vee, "\u2228", :operator)
30
+ b.add(:bigvee, "\u22C1", :operator, :underover => true)
31
+ b.add(:cap, "\u2229", :operator)
32
+ b.add(:bigcap, "\u22C2", :operator, :underover => true)
33
+ b.add(:cup, "\u222A", :operator)
34
+ b.add(:bigcup, "\u22C3", :operator, :underover => true)
35
+
36
+ # Relation symbols
37
+ b.add(:eq, '=', :operator)
38
+ b.add(:ne, "\u2260", :operator)
39
+ b.add(:assign, "\u2254", :operator)
40
+ b.add(:lt, "\u003C", :operator)
41
+ b.add(:gt, "\u003E", :operator)
42
+ b.add(:le, "\u2264", :operator)
43
+ b.add(:ge, "\u2265", :operator)
44
+ b.add(:prec, "\u227A", :operator)
45
+ b.add(:succ, "\u227B", :operator)
46
+ b.add(:preceq, "\u2AAF", :operator)
47
+ b.add(:succeq, "\u2AB0", :operator)
48
+ b.add(:in, "\u2208", :operator)
49
+ b.add(:notin, "\u2209", :operator)
50
+ b.add(:subset, "\u2282", :operator)
51
+ b.add(:supset, "\u2283", :operator)
52
+ b.add(:subseteq, "\u2286", :operator)
53
+ b.add(:supseteq, "\u2287", :operator)
54
+ b.add(:equiv, "\u2261", :operator)
55
+ b.add(:cong, "\u2245", :operator)
56
+ b.add(:approx, "\u2248", :operator)
57
+ b.add(:propto, "\u221D", :operator)
58
+
59
+ # Logical symbols
60
+ b.add(:and, 'and', :text)
61
+ b.add(:or, 'or', :text)
62
+ b.add(:not, "\u00AC", :operator)
63
+ b.add(:implies, "\u21D2", :operator)
64
+ b.add(:if, 'if', :operator)
65
+ b.add(:iff, "\u21D4", :operator)
66
+ b.add(:forall, "\u2200", :operator)
67
+ b.add(:exists, "\u2203", :operator)
68
+ b.add(:bot, "\u22A5", :operator)
69
+ b.add(:top, "\u22A4", :operator)
70
+ b.add(:vdash, "\u22A2", :operator)
71
+ b.add(:models, "\u22A8", :operator)
72
+
73
+ # Grouping brackets
74
+ b.add(:lparen, '(', :lparen)
75
+ b.add(:rparen, ')', :rparen)
76
+ b.add(:lbracket, '[', :lparen)
77
+ b.add(:rbracket, ']', :rparen)
78
+ b.add(:lbrace, '{', :lparen)
79
+ b.add(:rbrace, '}', :rparen)
80
+ b.add(:vbar, '|', :lrparen)
81
+ b.add(:langle, "\u2329", :lparen)
82
+ b.add(:rangle, "\u232A", :rparen)
83
+ b.add(:parallel, "\u2225", :lrparen)
84
+
85
+ # Miscellaneous symbols
86
+ b.add(:integral, "\u222B", :operator)
87
+ b.add(:dx, 'dx', :identifier)
88
+ b.add(:dy, 'dy', :identifier)
89
+ b.add(:dz, 'dz', :identifier)
90
+ b.add(:dt, 'dt', :identifier)
91
+ b.add(:contourintegral, "\u222E", :operator)
92
+ b.add(:partial, "\u2202", :operator)
93
+ b.add(:nabla, "\u2207", :operator)
94
+ b.add(:pm, "\u00B1", :operator)
95
+ b.add(:emptyset, "\u2205", :operator)
96
+ b.add(:infty, "\u221E", :operator)
97
+ b.add(:aleph, "\u2135", :operator)
98
+ b.add(:ellipsis, "\u2026", :operator)
99
+ b.add(:therefore, "\u2234", :operator)
100
+ b.add(:because, "\u2235", :operator)
101
+ b.add(:angle, "\u2220", :operator)
102
+ b.add(:triangle, "\u25B3", :operator)
103
+ b.add(:prime, "\u2032", :operator)
104
+ b.add(:tilde, "~", :accent, :position => :over)
105
+ b.add(:nbsp, "\u00A0", :operator)
106
+ b.add(:frown, "\u2322", :operator)
107
+ b.add(:quad, "\u00A0\u00A0", :operator)
108
+ b.add(:qquad, "\u00A0\u00A0\u00A0\u00A0", :operator)
109
+ b.add(:cdots, "\u22EF", :operator)
110
+ b.add(:vdots, "\u22EE", :operator)
111
+ b.add(:ddots, "\u22F1", :operator)
112
+ b.add(:diamond, "\u22C4", :operator)
113
+ b.add(:square, "\u25A1", :operator)
114
+ b.add(:lfloor, "\u230A", :operator)
115
+ b.add(:rfloor, "\u230B", :operator)
116
+ b.add(:lceiling, "\u2308", :operator)
117
+ b.add(:rceiling, "\u2309", :operator)
118
+ b.add(:dstruck_captial_c, "\u2102", :operator)
119
+ b.add(:dstruck_captial_n, "\u2115", :operator)
120
+ b.add(:dstruck_captial_q, "\u211A", :operator)
121
+ b.add(:dstruck_captial_r, "\u211D", :operator)
122
+ b.add(:dstruck_captial_z, "\u2124", :operator)
123
+ b.add(:f, 'f', :identifier)
124
+ b.add(:g, 'g', :identifier)
125
+
126
+ # Standard functions
127
+ b.add(:lim, 'lim', :operator, :underover => true)
128
+ b.add(:Lim, 'Lim', :operator, :underover => true)
129
+ b.add(:min, 'min', :operator, :underover => true)
130
+ b.add(:max, 'max', :operator, :underover => true)
131
+ b.add(:sin, 'sin', :identifier)
132
+ b.add(:Sin, 'Sin', :identifier)
133
+ b.add(:cos, 'cos', :identifier)
134
+ b.add(:Cos, 'Cos', :identifier)
135
+ b.add(:tan, 'tan', :identifier)
136
+ b.add(:Tan, 'Tan', :identifier)
137
+ b.add(:sinh, 'sinh', :identifier)
138
+ b.add(:Sinh, 'Sinh', :identifier)
139
+ b.add(:cosh, 'cosh', :identifier)
140
+ b.add(:Cosh, 'Cosh', :identifier)
141
+ b.add(:tanh, 'tanh', :identifier)
142
+ b.add(:Tanh, 'Tanh', :identifier)
143
+ b.add(:cot, 'cot', :identifier)
144
+ b.add(:Cot, 'Cot', :identifier)
145
+ b.add(:sec, 'sec', :identifier)
146
+ b.add(:Sec, 'Sec', :identifier)
147
+ b.add(:csc, 'csc', :identifier)
148
+ b.add(:Csc, 'Csc', :identifier)
149
+ b.add(:arcsin, 'arcsin', :identifier)
150
+ b.add(:arccos, 'arccos', :identifier)
151
+ b.add(:arctan, 'arctan', :identifier)
152
+ b.add(:coth, 'coth', :identifier)
153
+ b.add(:sech, 'sech', :identifier)
154
+ b.add(:csch, 'csch', :identifier)
155
+ b.add(:exp, 'exp', :identifier)
156
+ b.add(:abs, 'abs', :wrap, :lparen => '|', :rparen => '|')
157
+ b.add(:norm, 'norm', :wrap, :lparen => "\u2225", :rparen => "\u2225")
158
+ b.add(:floor, 'floor', :wrap, :lparen => "\u230A", :rparen => "\u230B")
159
+ b.add(:ceil, 'ceil', :wrap, :lparen => "\u2308", :rparen => "\u2309")
160
+ b.add(:log, 'log', :identifier)
161
+ b.add(:Log, 'Log', :identifier)
162
+ b.add(:ln, 'ln', :identifier)
163
+ b.add(:Ln, 'Ln', :identifier)
164
+ b.add(:det, 'det', :identifier)
165
+ b.add(:dim, 'dim', :identifier)
166
+ b.add(:ker, 'ker', :identifier)
167
+ b.add(:mod, 'mod', :identifier)
168
+ b.add(:gcd, 'gcd', :identifier)
169
+ b.add(:lcm, 'lcm', :identifier)
170
+ b.add(:lub, 'lub', :identifier)
171
+ b.add(:glb, 'glb', :identifier)
172
+
173
+ # Arrows
174
+ b.add(:uparrow, "\u2191", :operator)
175
+ b.add(:downarrow, "\u2193", :operator)
176
+ b.add(:rightarrow, "\u2192", :operator)
177
+ b.add(:to, "\u2192", :operator)
178
+ b.add(:rightarrowtail, "\u21A3", :operator)
179
+ b.add(:twoheadrightarrow, "\u21A0", :operator)
180
+ b.add(:twoheadrightarrowtail, "\u2916", :operator)
181
+ b.add(:mapsto, "\u21A6", :operator)
182
+ b.add(:leftarrow, "\u2190", :operator)
183
+ b.add(:leftrightarrow, "\u2194", :operator)
184
+ b.add(:Rightarrow, "\u21D2", :operator)
185
+ b.add(:Leftarrow, "\u21D0", :operator)
186
+ b.add(:Leftrightarrow, "\u21D4", :operator)
187
+
188
+ # Unary tags
189
+ b.add(:sqrt, :sqrt, :sqrt)
190
+ b.add(:cancel, :cancel, :cancel)
191
+
192
+ # Binary tags
193
+ b.add(:root, :root, :root)
194
+ b.add(:frac, :frac, :frac)
195
+ b.add(:stackrel, :stackrel, :over)
196
+ b.add(:overset, :overset, :over)
197
+ b.add(:underset, :underset, :under)
198
+ b.add(:color, :color, :color)
199
+
200
+ b.add(:sub, "_", :operator)
201
+ b.add(:sup, "^", :operator)
202
+ b.add(:hat, "\u005E", :accent, :position => :over)
203
+ b.add(:overline, "\u00AF", :accent, :position => :over)
204
+ b.add(:vec, "\u2192", :accent, :position => :over)
205
+ b.add(:dot, '.', :accent, :position => :over)
206
+ b.add(:ddot, '..', :accent, :position => :over)
207
+ b.add(:overarc, "\u23DC", :accent, :position => :over)
208
+ b.add(:underline, '_', :accent, :position => :under)
209
+ b.add(:underbrace, "\u23DF", :accent, :position => :under)
210
+ b.add(:overbrace, "\u23DE", :accent, :position => :over)
211
+ b.add(:bold, :bold, :font)
212
+ b.add(:double_struck, :double_struck, :font)
213
+ b.add(:italic, :italic, :font)
214
+ b.add(:bold_italic, :bold_italic, :font)
215
+ b.add(:script, :script, :font)
216
+ b.add(:bold_script, :bold_script, :font)
217
+ b.add(:monospace, :monospace, :font)
218
+ b.add(:fraktur, :fraktur, :font)
219
+ b.add(:bold_fraktur, :bold_fraktur, :font)
220
+ b.add(:sans_serif, :sans_serif, :font)
221
+ b.add(:bold_sans_serif, :bold_sans_serif, :font)
222
+ b.add(:sans_serif_italic, :sans_serif_italic, :font)
223
+ b.add(:sans_serif_bold_italic, :sans_serif_bold_italic, :font)
224
+ b.add(:roman, :normal, :font)
225
+
226
+ # Greek letters
227
+ b.add(:alpha, "\u03b1", :identifier)
228
+ b.add(:Alpha, "\u0391", :identifier)
229
+ b.add(:beta, "\u03b2", :identifier)
230
+ b.add(:Beta, "\u0392", :identifier)
231
+ b.add(:gamma, "\u03b3", :identifier)
232
+ b.add(:Gamma, "\u0393", :operator)
233
+ b.add(:delta, "\u03b4", :identifier)
234
+ b.add(:Delta, "\u0394", :operator)
235
+ b.add(:epsilon, "\u03b5", :identifier)
236
+ b.add(:Epsilon, "\u0395", :identifier)
237
+ b.add(:varepsilon, "\u025b", :identifier)
238
+ b.add(:zeta, "\u03b6", :identifier)
239
+ b.add(:Zeta, "\u0396", :identifier)
240
+ b.add(:eta, "\u03b7", :identifier)
241
+ b.add(:Eta, "\u0397", :identifier)
242
+ b.add(:theta, "\u03b8", :identifier)
243
+ b.add(:Theta, "\u0398", :operator)
244
+ b.add(:vartheta, "\u03d1", :identifier)
245
+ b.add(:iota, "\u03b9", :identifier)
246
+ b.add(:Iota, "\u0399", :identifier)
247
+ b.add(:kappa, "\u03ba", :identifier)
248
+ b.add(:Kappa, "\u039a", :identifier)
249
+ b.add(:lambda, "\u03bb", :identifier)
250
+ b.add(:Lambda, "\u039b", :operator)
251
+ b.add(:mu, "\u03bc", :identifier)
252
+ b.add(:Mu, "\u039c", :identifier)
253
+ b.add(:nu, "\u03bd", :identifier)
254
+ b.add(:Nu, "\u039d", :identifier)
255
+ b.add(:xi, "\u03be", :identifier)
256
+ b.add(:Xi, "\u039e", :operator)
257
+ b.add(:omicron, "\u03bf", :identifier)
258
+ b.add(:Omicron, "\u039f", :identifier)
259
+ b.add(:pi, "\u03c0", :identifier)
260
+ b.add(:Pi, "\u03a0", :operator)
261
+ b.add(:rho, "\u03c1", :identifier)
262
+ b.add(:Rho, "\u03a1", :identifier)
263
+ b.add(:sigma, "\u03c3", :identifier)
264
+ b.add(:Sigma, "\u03a3", :operator)
265
+ b.add(:tau, "\u03c4", :identifier)
266
+ b.add(:Tau, "\u03a4", :identifier)
267
+ b.add(:upsilon, "\u03c5", :identifier)
268
+ b.add(:Upsilon, "\u03a5", :identifier)
269
+ if fix_phi
270
+ b.add(:phi, "\u03d5", :identifier)
271
+ b.add(:varphi, "\u03c6", :identifier)
272
+ else
273
+ b.add(:phi, "\u03c6", :identifier)
274
+ b.add(:varphi, "\u03d5", :identifier)
275
+ end
276
+ b.add(:Phi, "\u03a6", :identifier)
277
+ b.add(:chi, "\u03c7", :identifier)
278
+ b.add(:Chi, "\u03a7", :identifier)
279
+ b.add(:psi, "\u03c8", :identifier)
280
+ b.add(:Psi, "\u03a8", :identifier)
281
+ b.add(:omega, "\u03c9", :identifier)
282
+ b.add(:Omega, "\u03a9", :operator)
283
+
284
+ b
285
+ end
286
+
287
+ private
288
+ DEFAULT_SYMBOL_TABLE = ::AsciiMath::MarkupBuilder.add_default_display_symbols(AsciiMath::SymbolTableBuilder.new, fix_phi: false).build
289
+ DEFAULT_SYMBOL_TABLE_FIX_PHI = ::AsciiMath::MarkupBuilder.add_default_display_symbols(AsciiMath::SymbolTableBuilder.new, fix_phi: true).build
290
+
291
+ public
292
+ def self.default_display_symbol_table(fix_phi: true)
293
+ if fix_phi
294
+ DEFAULT_SYMBOL_TABLE_FIX_PHI
295
+ else
296
+ DEFAULT_SYMBOL_TABLE
297
+ end
298
+ end
299
+
300
+ def initialize(symbol_table)
301
+ @symbol_table = symbol_table
302
+ end
303
+
304
+ private
305
+
306
+ def append(node, opts = {})
307
+ row_mode = opts[:row] || :avoid
308
+ if row_mode == :force
309
+ case node
310
+ when ::AsciiMath::AST::Sequence
311
+ append_row(node)
312
+ else
313
+ append_row([node])
314
+ end
315
+ return
316
+ end
317
+
318
+ case node
319
+ when ::AsciiMath::AST::Sequence
320
+ if (node.length <= 1 && row_mode == :avoid) || row_mode == :omit
321
+ node.each { |e| append(e) }
322
+ else
323
+ append_row(node)
324
+ end
325
+ when ::AsciiMath::AST::Group
326
+ append(node.expression)
327
+ when ::AsciiMath::AST::Text
328
+ append_text(node.value)
329
+ when ::AsciiMath::AST::Number
330
+ append_number(node.value)
331
+ when ::AsciiMath::AST::Identifier
332
+ append_identifier_or_operator(node.value)
333
+ when ::AsciiMath::AST::Symbol
334
+ if (symbol = resolve_symbol(node))
335
+ case symbol[:type]
336
+ when :operator, :accent, :lparen, :rparen, :lrparen
337
+ append_operator(symbol[:value])
338
+ else
339
+ append_identifier(symbol[:value])
340
+ end
341
+ else
342
+ append_identifier_or_operator(node[:value])
343
+ end
344
+ when ::AsciiMath::AST::Paren
345
+ append_paren(resolve_paren(node.lparen), node.expression, resolve_paren(node.rparen), opts)
346
+ when ::AsciiMath::AST::SubSup
347
+ if (resolve_symbol(node.base_expression) || {})[:underover]
348
+ append_underover(node.base_expression, node.sub_expression, node.sup_expression)
349
+ else
350
+ append_subsup(node.base_expression, node.sub_expression, node.sup_expression)
351
+ end
352
+ when ::AsciiMath::AST::UnaryOp
353
+ if (symbol = resolve_symbol(node.operator))
354
+ case symbol[:type]
355
+ when :identifier
356
+ append_identifier_unary(symbol[:value], node.operand)
357
+ when :operator
358
+ append_operator_unary(symbol[:value], node.operand)
359
+ when :wrap
360
+ append_paren(resolve_paren(symbol[:lparen]), node.operand, resolve_paren(symbol[:rparen]), opts)
361
+ when :accent
362
+ if symbol[:position] == :over
363
+ append_underover(node.operand, nil, node.operator)
364
+ else
365
+ append_underover(node.operand, node.operator, nil)
366
+ end
367
+ when :font
368
+ append_font(symbol[:value], node.operand)
369
+ when :cancel
370
+ append_cancel(node.operand)
371
+ when :sqrt
372
+ append_sqrt(node.operand)
373
+ end
374
+ end
375
+ when ::AsciiMath::AST::BinaryOp
376
+ if (symbol = resolve_symbol(node.operator))
377
+ case symbol[:type]
378
+ when :over
379
+ append_underover(node.operand2, nil, node.operand1)
380
+ when :under
381
+ append_underover(node.operand2, node.operand1, nil)
382
+ when :root
383
+ append_root(node.operand2, node.operand1)
384
+ when :color
385
+ append_color(node.operand1.to_hex_rgb, node.operand2)
386
+ end
387
+ end
388
+ when ::AsciiMath::AST::InfixOp
389
+ if (symbol = resolve_symbol(node.operator))
390
+ case symbol[:type]
391
+ when :frac
392
+ append_fraction(node.operand1, node.operand2)
393
+ end
394
+ end
395
+ when ::AsciiMath::AST::Matrix
396
+ append_matrix(resolve_paren(node.lparen), node, resolve_paren(node.rparen))
397
+ end
398
+ end
399
+
400
+ def append_row(expressions)
401
+ raise NotImplementedError.new __method__.to_s
402
+ end
403
+
404
+ def append_operator(operator)
405
+ raise NotImplementedError.new __method__.to_s
406
+ end
407
+
408
+ def append_identifier_or_operator(value)
409
+ if value.empty? || value =~ /[[:alnum:]].*/
410
+ append_identifier(value)
411
+ else
412
+ append_operator(value)
413
+ end
414
+ end
415
+
416
+ def append_identifier(identifier)
417
+ raise NotImplementedError.new __method__.to_s
418
+ end
419
+
420
+ def append_text(text_string)
421
+ raise NotImplementedError.new __method__.to_s
422
+ end
423
+
424
+ def append_number(number)
425
+ raise NotImplementedError.new __method__.to_s
426
+ end
427
+
428
+ def append_sqrt(expression)
429
+ raise NotImplementedError.new __method__.to_s
430
+ end
431
+
432
+ def append_cancel(expression)
433
+ raise NotImplementedError.new __method__.to_s
434
+ end
435
+
436
+ def append_root(base, index)
437
+ raise NotImplementedError.new __method__.to_s
438
+ end
439
+
440
+ def append_color(color, expression)
441
+ raise NotImplementedError.new __method__.to_s
442
+ end
443
+
444
+ def append_fraction(numerator, denominator)
445
+ raise NotImplementedError.new __method__.to_s
446
+ end
447
+
448
+ def append_font(style, expression)
449
+ raise NotImplementedError.new __method__.to_s
450
+ end
451
+
452
+ def append_matrix(lparen, rows, rparen)
453
+ raise NotImplementedError.new __method__.to_s
454
+ end
455
+
456
+ def append_operator_unary(operator, expression)
457
+ raise NotImplementedError.new __method__.to_s
458
+ end
459
+
460
+ def append_identifier_unary(identifier, expression)
461
+ raise NotImplementedError.new __method__.to_s
462
+ end
463
+
464
+ def append_paren(lparen, expression, rparen, opts)
465
+ raise NotImplementedError.new __method__.to_s
466
+ end
467
+
468
+ def append_subsup(base, sub, sup)
469
+ raise NotImplementedError.new __method__.to_s
470
+ end
471
+
472
+ def append_underover(base, under, over)
473
+ raise NotImplementedError.new __method__.to_s
474
+ end
475
+
476
+ def resolve_paren(paren_symbol)
477
+ if paren_symbol.nil?
478
+ return nil
479
+ end
480
+
481
+ if (resolved = resolve_symbol(paren_symbol))
482
+ resolved[:value]
483
+ else
484
+ case paren_symbol
485
+ when ::AsciiMath::AST::Symbol
486
+ paren_symbol.value
487
+ else
488
+ paren_symbol
489
+ end
490
+ end
491
+ end
492
+
493
+ def resolve_symbol(node)
494
+ case node
495
+ when ::AsciiMath::AST::Symbol
496
+ @symbol_table[node.value]
497
+ when ::Symbol
498
+ @symbol_table[node]
499
+ else
500
+ nil
501
+ end
502
+ end
503
+
504
+ def is_accent(node)
505
+ resolved = resolve_symbol(node)
506
+ !resolved.nil? && resolved[:type] == :accent
507
+ end
508
+ end
509
+ end