plurimath 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +13 -0
  3. data/.github/workflows/release.yml +22 -0
  4. data/.gitignore +1 -0
  5. data/.hound.yml +5 -0
  6. data/.rubocop.yml +8 -0
  7. data/AsciiMath-Supported-Data.adoc +2000 -0
  8. data/Gemfile +3 -0
  9. data/Latex-Supported-Data.adoc +1879 -0
  10. data/MathML-Supported-Data.adoc +287 -0
  11. data/README.adoc +96 -0
  12. data/lib/plurimath/asciimath/constants.rb +267 -229
  13. data/lib/plurimath/asciimath/parse.rb +125 -26
  14. data/lib/plurimath/asciimath/parser.rb +6 -3
  15. data/lib/plurimath/asciimath/transform.rb +1135 -208
  16. data/lib/plurimath/asciimath.rb +1 -1
  17. data/lib/plurimath/html/constants.rb +50 -0
  18. data/lib/plurimath/html/parse.rb +149 -0
  19. data/lib/plurimath/html/parser.rb +26 -0
  20. data/lib/plurimath/html/transform.rb +363 -0
  21. data/lib/plurimath/html.rb +1 -1
  22. data/lib/plurimath/latex/constants.rb +3729 -1906
  23. data/lib/plurimath/latex/parse.rb +167 -51
  24. data/lib/plurimath/latex/parser.rb +12 -4
  25. data/lib/plurimath/latex/transform.rb +598 -183
  26. data/lib/plurimath/math/base.rb +15 -0
  27. data/lib/plurimath/math/formula.rb +96 -11
  28. data/lib/plurimath/math/function/bar.rb +34 -0
  29. data/lib/plurimath/math/function/base.rb +32 -5
  30. data/lib/plurimath/math/function/binary_function.rb +104 -17
  31. data/lib/plurimath/math/function/cancel.rb +8 -0
  32. data/lib/plurimath/math/function/ceil.rb +3 -0
  33. data/lib/plurimath/math/function/color.rb +16 -6
  34. data/lib/plurimath/math/function/f.rb +8 -0
  35. data/lib/plurimath/math/function/fenced.rb +95 -3
  36. data/lib/plurimath/math/function/floor.rb +15 -0
  37. data/lib/plurimath/math/function/font_style/bold.rb +37 -0
  38. data/lib/plurimath/math/function/font_style/double_struck.rb +37 -0
  39. data/lib/plurimath/math/function/font_style/fraktur.rb +37 -0
  40. data/lib/plurimath/math/function/font_style/italic.rb +37 -0
  41. data/lib/plurimath/math/function/font_style/monospace.rb +37 -0
  42. data/lib/plurimath/math/function/font_style/normal.rb +37 -0
  43. data/lib/plurimath/math/function/font_style/sans-serif.rb +37 -0
  44. data/lib/plurimath/math/function/font_style/script.rb +37 -0
  45. data/lib/plurimath/math/function/font_style.rb +18 -25
  46. data/lib/plurimath/math/function/frac.rb +35 -5
  47. data/lib/plurimath/math/function/g.rb +7 -0
  48. data/lib/plurimath/math/function/hat.rb +12 -0
  49. data/lib/plurimath/math/function/inf.rb +21 -1
  50. data/lib/plurimath/math/function/int.rb +23 -2
  51. data/lib/plurimath/math/function/left.rb +25 -4
  52. data/lib/plurimath/math/function/lim.rb +40 -2
  53. data/lib/plurimath/math/function/limits.rb +8 -0
  54. data/lib/plurimath/math/function/log.rb +61 -4
  55. data/lib/plurimath/math/function/longdiv.rb +12 -0
  56. data/lib/plurimath/math/function/mbox.rb +31 -0
  57. data/lib/plurimath/math/function/menclose.rb +46 -0
  58. data/lib/plurimath/math/function/merror.rb +12 -0
  59. data/lib/plurimath/math/function/mod.rb +25 -4
  60. data/lib/plurimath/math/function/msgroup.rb +37 -0
  61. data/lib/plurimath/math/function/msline.rb +12 -0
  62. data/lib/plurimath/math/function/multiscript.rb +30 -0
  63. data/lib/plurimath/math/function/norm.rb +18 -1
  64. data/lib/plurimath/math/function/obrace.rb +17 -0
  65. data/lib/plurimath/math/function/oint.rb +2 -2
  66. data/lib/plurimath/math/function/over.rb +36 -0
  67. data/lib/plurimath/math/function/overset.rb +36 -7
  68. data/lib/plurimath/math/function/phantom.rb +28 -0
  69. data/lib/plurimath/math/function/power.rb +33 -9
  70. data/lib/plurimath/math/function/power_base.rb +110 -5
  71. data/lib/plurimath/math/function/prod.rb +29 -2
  72. data/lib/plurimath/math/function/right.rb +44 -0
  73. data/lib/plurimath/math/function/root.rb +27 -4
  74. data/lib/plurimath/math/function/rule.rb +33 -0
  75. data/lib/plurimath/math/function/scarries.rb +12 -0
  76. data/lib/plurimath/math/function/scarry.rb +12 -0
  77. data/lib/plurimath/math/function/sqrt.rb +24 -2
  78. data/lib/plurimath/math/function/stackrel.rb +27 -0
  79. data/lib/plurimath/math/function/substack.rb +7 -1
  80. data/lib/plurimath/math/function/sum.rb +56 -2
  81. data/lib/plurimath/math/function/sup.rb +3 -0
  82. data/lib/plurimath/math/function/table/align.rb +24 -0
  83. data/lib/plurimath/math/function/table/array.rb +44 -0
  84. data/lib/plurimath/math/function/table/bmatrix.rb +37 -0
  85. data/lib/plurimath/math/function/table/matrix.rb +32 -0
  86. data/lib/plurimath/math/function/table/multline.rb +24 -0
  87. data/lib/plurimath/math/function/table/pmatrix.rb +24 -0
  88. data/lib/plurimath/math/function/table/split.rb +24 -0
  89. data/lib/plurimath/math/function/table/vmatrix.rb +24 -0
  90. data/lib/plurimath/math/function/table.rb +190 -20
  91. data/lib/plurimath/math/function/td.rb +27 -9
  92. data/lib/plurimath/math/function/ternary_function.rb +83 -8
  93. data/lib/plurimath/math/function/text.rb +45 -8
  94. data/lib/plurimath/math/function/tr.rb +28 -4
  95. data/lib/plurimath/math/function/ubrace.rb +17 -0
  96. data/lib/plurimath/math/function/ul.rb +29 -0
  97. data/lib/plurimath/math/function/unary_function.rb +85 -7
  98. data/lib/plurimath/math/function/underline.rb +12 -0
  99. data/lib/plurimath/math/function/underover.rb +107 -0
  100. data/lib/plurimath/math/function/underset.rb +39 -0
  101. data/lib/plurimath/math/function/vec.rb +10 -0
  102. data/lib/plurimath/math/function.rb +13 -2
  103. data/lib/plurimath/math/number.rb +11 -3
  104. data/lib/plurimath/math/symbol.rb +57 -9
  105. data/lib/plurimath/math/unicode.rb +11 -0
  106. data/lib/plurimath/math.rb +15 -6
  107. data/lib/plurimath/mathml/constants.rb +224 -179
  108. data/lib/plurimath/mathml/parser.rb +24 -7
  109. data/lib/plurimath/mathml/transform.rb +249 -148
  110. data/lib/plurimath/mathml.rb +1 -1
  111. data/lib/plurimath/omml/parser.rb +42 -0
  112. data/lib/plurimath/omml/transform.rb +278 -0
  113. data/lib/plurimath/omml.rb +1 -1
  114. data/lib/plurimath/unitsml.rb +4 -0
  115. data/lib/plurimath/utility.rb +395 -0
  116. data/lib/plurimath/version.rb +1 -1
  117. data/plurimath.gemspec +1 -0
  118. metadata +66 -9
  119. data/.github/workflows/test.yml +0 -36
  120. data/README.md +0 -40
  121. data/lib/plurimath/mathml/parse.rb +0 -63
@@ -3,192 +3,293 @@
3
3
  module Plurimath
4
4
  class Mathml
5
5
  class Transform < Parslet::Transform
6
- rule(tag: simple(:tag)) { tag }
7
- rule(tag: sequence(:tag)) { tag }
8
- rule(text: simple(:text)) { Plurimath::Math::Symbol.new(text.to_s) }
9
- rule(class: simple(:string)) { Transform.get_class(string).new }
10
- rule(number: simple(:number)) { Plurimath::Math::Number.new(number.to_s) }
11
- rule(tag: sequence(:tag), sequence: simple(:sequence)) { tag + [sequence] }
12
- rule(tag: simple(:tag), sequence: sequence(:sequence)) { [tag] + sequence }
13
- rule(tag: sequence(:tag), sequence: sequence(:sequence)) { tag + sequence }
14
-
15
- rule(quoted_text: simple(:quoted_text)) do
16
- text = quoted_text.to_s
17
- Constants::UNICODE_SYMBOLS.each do |code, string|
18
- text.gsub!(code.to_s, "unicode[:#{string}]")
6
+ rule(mi: simple(:mi)) { mi }
7
+ rule(mo: simple(:mo)) { mo }
8
+ rule(mo: sequence(:mo)) { Utility.mathml_unary_classes(mo) }
9
+ rule(xref: simple(:xref)) { nil }
10
+ rule(mtd: sequence(:mtd)) { Math::Function::Td.new(mtd) }
11
+ rule(mtr: sequence(:mtr)) { Math::Function::Tr.new(mtr) }
12
+ rule(accent: simple(:acc)) { nil }
13
+ rule(none: sequence(:none)) { nil }
14
+ rule(maxsize: simple(:att)) { nil }
15
+ rule(minsize: simple(:att)) { nil }
16
+ rule(notation: simple(:att)) { Math::Function::Menclose.new(att) }
17
+ rule(mtable: simple(:table)) { table }
18
+ rule(msqrt: sequence(:sqrt)) { Math::Function::Sqrt.new(sqrt.first) }
19
+ rule(mstyle: simple(:mstyle)) { mstyle }
20
+ rule(msline: sequence(:line)) { Math::Function::Msline.new }
21
+ rule(value: sequence(:value)) { Utility.filter_values(value) }
22
+
23
+ rule(mspace: sequence(:space)) { nil }
24
+ rule(mstyle: sequence(:mstyle)) { Utility.filter_values(mstyle) }
25
+ rule(mfenced: simple(:mfenced)) { mfenced }
26
+ rule(mtable: sequence(:mtable)) { Math::Function::Table.new(mtable) }
27
+ rule(mscarry: sequence(:scarry)) { nil }
28
+ rule(displaystyle: simple(:att)) { nil }
29
+ rule(menclose: simple(:enclose)) { enclose }
30
+ rule(mlabeledtr: sequence(:mtr)) { Math::Function::Tr.new(mtr) }
31
+ rule(mpadded: sequence(:padded)) { Utility.filter_values(padded) }
32
+ rule(malignmark: sequence(:mark)) { nil }
33
+ rule(maligngroup: sequence(:att)) { nil }
34
+ rule(mprescripts: sequence(:att)) { "mprescripts" }
35
+ rule(columnlines: simple(:lines)) { lines }
36
+
37
+ rule(math: subtree(:math)) do
38
+ Utility.filter_values(
39
+ math.flatten.compact,
40
+ )
41
+ end
42
+
43
+ rule(mphantom: sequence(:phantom)) do
44
+ Math::Function::Phantom.new(phantom)
45
+ end
46
+
47
+ rule(mn: sequence(:mn)) do
48
+ Math::Number.new(
49
+ Utility.string_to_html_entity(
50
+ mn.join,
51
+ ),
52
+ )
53
+ end
54
+
55
+ rule(mathvariant: simple(:variant)) do
56
+ Utility::FONT_STYLES[variant.to_sym]&.new(nil, variant)
57
+ end
58
+
59
+ rule(mi: sequence(:mi)) do
60
+ mi.any?(String) ? Utility.mathml_unary_classes(mi) : mi
61
+ end
62
+
63
+ rule(open: simple(:lparen)) do
64
+ Math::Function::Fenced.new(Math::Symbol.new(lparen))
65
+ end
66
+
67
+ rule(msgroup: sequence(:group)) do
68
+ if group.any?(String)
69
+ group.each_with_index do |object, ind|
70
+ group[ind] = Utility.text_classes(object) if object.is_a?(String)
71
+ end
19
72
  end
20
- Plurimath::Math::Function::Text.new(text)
73
+ Math::Function::Msgroup.new(group.flatten.compact)
74
+ end
75
+
76
+ rule(mlongdiv: sequence(:long)) do
77
+ Math::Function::Longdiv.new(long.flatten.compact)
21
78
  end
22
79
 
23
- rule(
24
- tag: sequence(:tag),
25
- sequence: sequence(:sequence),
26
- iteration: simple(:iteration),
27
- ) do
28
- new_arr = []
29
- new_arr = new_arr + tag unless tag.compact.empty?
30
- new_arr = new_arr + sequence unless sequence.compact.empty?
31
- new_arr << iteration unless iteration.to_s.empty?
32
- new_arr
80
+ rule(menclose: sequence(:close)) do
81
+ Math::Function::Menclose.new(
82
+ nil,
83
+ Utility.filter_values(close),
84
+ )
33
85
  end
34
86
 
35
- rule(
36
- tag: sequence(:tag),
37
- sequence: simple(:sequence),
38
- iteration: simple(:iteration),
39
- ) do
40
- Plurimath::Math::Formula.new(tag + [sequence])
87
+ rule(mroot: sequence(:mroot)) do
88
+ Math::Function::Root.new(
89
+ mroot[1],
90
+ mroot[0],
91
+ )
41
92
  end
42
93
 
43
- rule(
44
- tag: simple(:tag),
45
- sequence: simple(:sequence),
46
- iteration: simple(:iteration),
47
- ) do
48
- [tag, sequence]
94
+ rule(merror: sequence(:merror)) do
95
+ Math::Function::Merror.new(
96
+ merror[0],
97
+ merror[1],
98
+ )
49
99
  end
50
100
 
51
- rule(tag: sequence(:tag), iteration: simple(:iteration)) do
52
- new_arr = []
53
- new_arr = tag unless tag.compact.empty?
54
- new_arr << iteration unless iteration.to_s.empty?
55
- new_arr
101
+ rule(mfrac: sequence(:mfrac)) do
102
+ Math::Function::Frac.new(
103
+ mfrac[0],
104
+ mfrac[1],
105
+ )
56
106
  end
57
107
 
58
- rule(tag: simple(:tag), sequence: simple(:sequence)) do
59
- new_arr = []
60
- new_arr << tag unless tag.nil?
61
- new_arr << sequence unless sequence.nil?
62
- new_arr
108
+ rule(mfraction: sequence(:mfrac)) do
109
+ Math::Function::Frac.new(
110
+ mfrac[0],
111
+ mfrac[1],
112
+ )
63
113
  end
64
114
 
65
- rule(tag: simple(:tag), iteration: simple(:iteration)) do
66
- new_arr = []
67
- new_arr << tag unless tag.to_s.empty?
68
- new_arr << iteration unless iteration.to_s.empty?
69
- new_arr
115
+ rule(msub: sequence(:msub)) do
116
+ Math::Function::Base.new(
117
+ msub[0],
118
+ msub[1],
119
+ )
70
120
  end
71
121
 
72
- rule(symbol: simple(:symbol)) do
73
- decoded_symbol = Constants::UNICODE_SYMBOLS[symbol.to_sym]
74
- if Constants::CLASSES.include?(decoded_symbol)
75
- [Transform.get_class(decoded_symbol).new]
76
- elsif decoded_symbol.nil? && Constants::SYMBOLS[symbol.to_sym]
77
- Plurimath::Math::Symbol.new(Constants::SYMBOLS[symbol.to_sym])
122
+ rule(msup: sequence(:msup)) do
123
+ Math::Function::Power.new(
124
+ msup[0],
125
+ msup[1],
126
+ )
127
+ end
128
+
129
+ rule(msubsup: sequence(:msubsup)) do
130
+ Math::Function::PowerBase.new(
131
+ msubsup[0],
132
+ msubsup[1],
133
+ msubsup[2],
134
+ )
135
+ end
136
+
137
+ rule(munderover: sequence(:function)) do
138
+ binary_function = Plurimath::Math::Function::BinaryFunction
139
+ base_class = function[0]&.value&.first if function[0].is_a?(Math::Formula)
140
+ if base_class&.class&.ancestors&.include?(binary_function)
141
+ base_class.parameter_one = function[1]
142
+ base_class.parameter_two = function[2]
143
+ base_class
78
144
  else
79
- Plurimath::Math::Symbol.new(decoded_symbol)
145
+ Math::Function::Underover.new(
146
+ function[0],
147
+ function[1],
148
+ function[2],
149
+ )
80
150
  end
81
151
  end
82
152
 
83
- rule(name: simple(:name), value: simple(:value)) do
84
- if ["open", "close"].include?(name.to_s)
85
- Plurimath::Math::Symbol.new(value.to_s)
86
- elsif name.to_s == "mathcolor"
87
- Plurimath::Math::Function::Color.new(value.to_s)
88
- elsif name.to_s == "mathvariant"
89
- value.to_s
153
+ rule(mrow: subtree(:mrow)) do
154
+ if mrow.any?(String)
155
+ mrow.each_with_index do |object, ind|
156
+ mrow[ind] = Utility.mathml_unary_classes([object]) if object.is_a?(String)
157
+ end
90
158
  end
159
+ Math::Formula.new(mrow.flatten.compact)
91
160
  end
92
161
 
93
- rule(
94
- tag: simple(:tag),
95
- sequence: sequence(:sequence),
96
- iteration: simple(:iteration),
97
- ) do
98
- tag_str = tag.to_s.split("::").last.downcase.to_sym
99
- if Constants::BINARY_CLASSES.include?(tag_str)
100
- tag.new(sequence.first, sequence.last)
162
+ rule(msrow: sequence(:msrow)) do
163
+ Math::Formula.new(msrow.flatten.compact)
164
+ end
165
+
166
+ rule(mstack: sequence(:stack)) do
167
+ Math::Function::Stackrel.new(
168
+ Utility.filter_values(stack),
169
+ )
170
+ end
171
+
172
+ rule(mover: sequence(:mover)) do
173
+ if ["ubrace", "obrace"].any?(mover.last.class_name)
174
+ mover.last.parameter_one = mover.shift if mover.length > 1
175
+ mover.last
101
176
  else
102
- new_arr = sequence.compact
103
- new_arr = [tag] + new_arr unless tag.nil?
104
- new_arr << iteration unless iteration.to_s.empty?
105
- new_arr
177
+ Math::Function::Overset.new(
178
+ mover[1],
179
+ mover[0],
180
+ )
106
181
  end
107
182
  end
108
183
 
109
- rule(
110
- open: simple(:open_tag),
111
- attributes: sequence(:attributes),
112
- iteration: sequence(:iteration),
113
- close: simple(:close_tag),
114
- ) do
115
- Transform.raise_error!(open_tag, close_tag) unless open_tag == close_tag
116
-
117
- if open_tag == "mrow"
118
- Plurimath::Math::Formula.new(iteration)
119
- elsif open_tag == "munder"
120
- if Transform.get_class("obrace") == iteration.last.class
121
- iteration.last.parameter_one = iteration.first
122
- iteration.last
123
- else
124
- Plurimath::Math::Function::Underset.new(iteration[1], iteration[0])
125
- end
126
- elsif open_tag == "munderover"
127
- Plurimath::Math::Function::Underover.new(iteration[0], iteration[1], iteration[2])
128
- elsif open_tag == "mover"
129
- if Transform.get_class("ubrace") == iteration.last.class
130
- iteration.last.parameter_one = iteration.first
131
- iteration.last
132
- else
133
- Plurimath::Math::Function::Overset.new(iteration[1], iteration[0])
134
- end
135
- elsif open_tag == "msup"
136
- Plurimath::Math::Function::Power.new(iteration[0], iteration[1])
137
- elsif open_tag == "msub"
138
- Plurimath::Math::Function::Base.new(iteration[0], iteration[1])
139
- elsif open_tag == "msubsup"
140
- Plurimath::Math::Function::PowerBase.new(iteration[0], iteration[1], iteration[2])
141
- elsif open_tag == "mfrac"
142
- Plurimath::Math::Function::Frac.new(iteration.first, iteration.last)
143
- elsif open_tag == "msqrt"
144
- Plurimath::Math::Function::Sqrt.new(iteration.first)
145
- elsif open_tag == "mroot"
146
- Plurimath::Math::Function::Root.new(iteration[0], iteration[1])
147
- elsif open_tag == "mfenced"
148
- Plurimath::Math::Function::Fenced.new(attributes[0], iteration, attributes[1])
149
- elsif open_tag == "mtable"
150
- Plurimath::Math::Function::Table.new(iteration)
151
- elsif open_tag == "mtr"
152
- Plurimath::Math::Function::Tr.new(iteration)
153
- elsif open_tag == "mtd"
154
- Plurimath::Math::Function::Td.new(iteration)
155
- elsif attributes.first.is_a?(Plurimath::Math::Function::Color)
156
- attributes.first.parameter_two = iteration.first
157
- attributes.first
158
- elsif open_tag == "mstyle" && !attributes.compact.empty?
159
- font_type = attributes.compact.last.to_sym
160
- if Constants::FONT_CLASSES.include?(font_type)
161
- Math::Function::FontStyle.new(iteration.last, font_type.to_s)
184
+ rule(munder: sequence(:munder)) do
185
+ if munder.any?(String)
186
+ munder.each_with_index do |object, ind|
187
+ munder[ind] = Utility.mathml_unary_classes([object]) if object.is_a?(String)
162
188
  end
189
+ end
190
+ if ["ubrace", "obrace"].any?(munder.last.class_name)
191
+ munder.last.parameter_one = munder.shift if munder.length > 1
192
+ munder.last
163
193
  else
164
- iteration
194
+ Math::Function::Underset.new(
195
+ munder[1],
196
+ munder[0],
197
+ )
198
+ end
199
+ end
200
+
201
+ rule(mscarries: sequence(:scarries)) do
202
+ Math::Function::Scarries.new(
203
+ Utility.filter_values(scarries),
204
+ )
205
+ end
206
+
207
+ rule(mtext: sequence(:mtext)) do
208
+ entities = HTMLEntities.new
209
+ symbols = Constants::UNICODE_SYMBOLS.transform_keys(&:to_s)
210
+ text = entities.encode(mtext.first, :hexadecimal)
211
+ symbols.each do |code, string|
212
+ text.gsub!(code.downcase, "unicode[:#{string}]")
213
+ end
214
+ Math::Function::Text.new(text)
215
+ end
216
+
217
+ rule(ms: sequence(:ms)) do
218
+ entities = HTMLEntities.new
219
+ symbols = Constants::UNICODE_SYMBOLS.transform_keys(&:to_s)
220
+ text = entities.encode(ms.first, :hexadecimal)
221
+ symbols.each do |code, string|
222
+ text.gsub!(code.downcase, "unicode[:#{string}]")
165
223
  end
224
+ Math::Function::Text.new(text)
225
+ end
226
+
227
+ rule(mfenced: sequence(:fenced)) do
228
+ Math::Function::Fenced.new(
229
+ Math::Symbol.new("("),
230
+ fenced,
231
+ Math::Symbol.new(")"),
232
+ )
166
233
  end
167
234
 
168
- rule(
169
- open: simple(:open_tag),
170
- attributes: sequence(:attributes),
171
- iteration: simple(:iteration),
172
- close: simple(:close_tag),
173
- ) do
174
- Transform.raise_error!(open_tag, close_tag) unless open_tag == close_tag
235
+ rule(mmultiscripts: subtree(:script)) do
236
+ multi = Utility.multiscript(script.compact)
237
+ prescripts = multi[1]
238
+ Math::Function::Multiscript.new(
239
+ multi[0],
240
+ (prescripts[0] if prescripts),
241
+ (prescripts[1] if prescripts),
242
+ )
243
+ end
244
+
245
+ rule(mathcolor: simple(:color)) do
246
+ Math::Function::Color.new(
247
+ Math::Function::Text.new(color),
248
+ )
249
+ end
250
+
251
+ rule(open: simple(:lparen),
252
+ close: simple(:rparen)) do
253
+ Math::Function::Fenced.new(
254
+ Math::Symbol.new(lparen),
255
+ nil,
256
+ Math::Symbol.new(rparen),
257
+ )
258
+ end
175
259
 
176
- if iteration.to_s.include?("Function")
177
- iteration
260
+ rule(mathcolor: simple(:color),
261
+ mathvariant: simple(:variant)) do
262
+ variant_class = Utility::FONT_STYLES[variant.to_sym]
263
+ if variant_class
264
+ Math::Function::Color.new(
265
+ Math::Function::Text.new(
266
+ color,
267
+ ),
268
+ variant_class.new(
269
+ nil,
270
+ variant,
271
+ ),
272
+ )
178
273
  else
179
- [iteration.to_s.empty? ? nil : iteration]
274
+ Math::Function::Color.new(
275
+ Math::Function::Text.new(
276
+ color,
277
+ ),
278
+ )
180
279
  end
181
280
  end
182
281
 
183
- def self.get_class(text)
184
- Object.const_get("Plurimath::Math::Function::#{text.to_s.capitalize}")
282
+ rule(attributes: simple(:attrs),
283
+ value: subtree(:value)) do
284
+ Utility.join_attr_value(attrs, value.flatten)
185
285
  end
186
286
 
187
- def self.raise_error!(open_tag, close_tag)
188
- message = "Please check your input."\
189
- " Opening tag is \"#{open_tag}\""\
190
- " and closing tag is \"#{close_tag}\""
191
- raise Plurimath::Math::Error.new(message)
287
+ rule(attributes: subtree(:attrs),
288
+ value: sequence(:value)) do
289
+ Utility.join_attr_value(
290
+ attrs.is_a?(Hash) ? nil : attrs,
291
+ value.flatten,
292
+ )
192
293
  end
193
294
  end
194
295
  end
@@ -10,7 +10,7 @@ module Plurimath
10
10
  end
11
11
 
12
12
  def to_formula
13
- Plurimath::Mathml::Parser.new(text).parse
13
+ Parser.new(text).parse
14
14
  end
15
15
  end
16
16
  end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "transform"
4
+ module Plurimath
5
+ class Omml
6
+ class Parser
7
+ attr_accessor :text
8
+
9
+ def initialize(text)
10
+ @text = text
11
+ end
12
+
13
+ def parse
14
+ nodes = Ox.load(text, strip_namespace: true)
15
+ @hash = { sequence: parse_nodes(nodes.nodes) }
16
+ nodes = JSON.parse(@hash.to_json, symbolize_names: true)
17
+ Math::Formula.new(
18
+ Transform.new.apply(
19
+ nodes,
20
+ ),
21
+ )
22
+ end
23
+
24
+ def parse_nodes(nodes)
25
+ nodes.map do |node|
26
+ if node.is_a?(String)
27
+ node
28
+ elsif !node.attributes.empty?
29
+ {
30
+ node.name => {
31
+ attributes: node.attributes,
32
+ value: parse_nodes(node.nodes),
33
+ },
34
+ }
35
+ else
36
+ { node.name => parse_nodes(node.nodes) }
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end