plurimath 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +36 -0
  3. data/.rubocop.yml +2 -0
  4. data/lib/plurimath/asciimath/constants.rb +308 -0
  5. data/lib/plurimath/asciimath/parse.rb +87 -0
  6. data/lib/plurimath/asciimath/parser.rb +24 -0
  7. data/lib/plurimath/asciimath/transform.rb +304 -0
  8. data/lib/plurimath/asciimath.rb +16 -0
  9. data/lib/plurimath/html.rb +15 -0
  10. data/lib/plurimath/latex/constants.rb +1963 -0
  11. data/lib/plurimath/latex/parse.rb +105 -0
  12. data/lib/plurimath/latex/parser.rb +24 -0
  13. data/lib/plurimath/latex/transform.rb +298 -0
  14. data/lib/plurimath/latex.rb +15 -0
  15. data/lib/plurimath/math/formula.rb +43 -0
  16. data/lib/plurimath/math/function/abs.rb +12 -0
  17. data/lib/plurimath/math/function/arccos.rb +12 -0
  18. data/lib/plurimath/math/function/arcsin.rb +12 -0
  19. data/lib/plurimath/math/function/arctan.rb +12 -0
  20. data/lib/plurimath/math/function/bar.rb +16 -0
  21. data/lib/plurimath/math/function/base.rb +30 -0
  22. data/lib/plurimath/math/function/binary_function.rb +53 -0
  23. data/lib/plurimath/math/function/cancel.rb +12 -0
  24. data/lib/plurimath/math/function/ceil.rb +12 -0
  25. data/lib/plurimath/math/function/color.rb +23 -0
  26. data/lib/plurimath/math/function/cos.rb +12 -0
  27. data/lib/plurimath/math/function/cosh.rb +12 -0
  28. data/lib/plurimath/math/function/cot.rb +12 -0
  29. data/lib/plurimath/math/function/coth.rb +12 -0
  30. data/lib/plurimath/math/function/csc.rb +12 -0
  31. data/lib/plurimath/math/function/csch.rb +12 -0
  32. data/lib/plurimath/math/function/ddot.rb +12 -0
  33. data/lib/plurimath/math/function/deg.rb +12 -0
  34. data/lib/plurimath/math/function/det.rb +12 -0
  35. data/lib/plurimath/math/function/dim.rb +12 -0
  36. data/lib/plurimath/math/function/dot.rb +12 -0
  37. data/lib/plurimath/math/function/exp.rb +12 -0
  38. data/lib/plurimath/math/function/f.rb +12 -0
  39. data/lib/plurimath/math/function/fenced.rb +22 -0
  40. data/lib/plurimath/math/function/floor.rb +12 -0
  41. data/lib/plurimath/math/function/font_style.rb +45 -0
  42. data/lib/plurimath/math/function/frac.rb +23 -0
  43. data/lib/plurimath/math/function/g.rb +12 -0
  44. data/lib/plurimath/math/function/gcd.rb +12 -0
  45. data/lib/plurimath/math/function/glb.rb +12 -0
  46. data/lib/plurimath/math/function/hat.rb +12 -0
  47. data/lib/plurimath/math/function/hom.rb +12 -0
  48. data/lib/plurimath/math/function/inf.rb +18 -0
  49. data/lib/plurimath/math/function/int.rb +17 -0
  50. data/lib/plurimath/math/function/ker.rb +12 -0
  51. data/lib/plurimath/math/function/lcm.rb +12 -0
  52. data/lib/plurimath/math/function/left.rb +23 -0
  53. data/lib/plurimath/math/function/lg.rb +12 -0
  54. data/lib/plurimath/math/function/lim.rb +23 -0
  55. data/lib/plurimath/math/function/liminf.rb +12 -0
  56. data/lib/plurimath/math/function/limits.rb +19 -0
  57. data/lib/plurimath/math/function/limsup.rb +12 -0
  58. data/lib/plurimath/math/function/ln.rb +12 -0
  59. data/lib/plurimath/math/function/log.rb +23 -0
  60. data/lib/plurimath/math/function/lub.rb +12 -0
  61. data/lib/plurimath/math/function/max.rb +12 -0
  62. data/lib/plurimath/math/function/min.rb +12 -0
  63. data/lib/plurimath/math/function/mod.rb +23 -0
  64. data/lib/plurimath/math/function/norm.rb +15 -0
  65. data/lib/plurimath/math/function/obrace.rb +12 -0
  66. data/lib/plurimath/math/function/oint.rb +17 -0
  67. data/lib/plurimath/math/function/overset.rb +23 -0
  68. data/lib/plurimath/math/function/power.rb +30 -0
  69. data/lib/plurimath/math/function/power_base.rb +26 -0
  70. data/lib/plurimath/math/function/prod.rb +23 -0
  71. data/lib/plurimath/math/function/root.rb +22 -0
  72. data/lib/plurimath/math/function/sec.rb +12 -0
  73. data/lib/plurimath/math/function/sech.rb +12 -0
  74. data/lib/plurimath/math/function/sin.rb +12 -0
  75. data/lib/plurimath/math/function/sinh.rb +12 -0
  76. data/lib/plurimath/math/function/sqrt.rb +16 -0
  77. data/lib/plurimath/math/function/stackrel.rb +12 -0
  78. data/lib/plurimath/math/function/substack.rb +18 -0
  79. data/lib/plurimath/math/function/sum.rb +23 -0
  80. data/lib/plurimath/math/function/sup.rb +12 -0
  81. data/lib/plurimath/math/function/table.rb +42 -0
  82. data/lib/plurimath/math/function/tan.rb +12 -0
  83. data/lib/plurimath/math/function/tanh.rb +12 -0
  84. data/lib/plurimath/math/function/td.rb +27 -0
  85. data/lib/plurimath/math/function/ternary_function.rb +42 -0
  86. data/lib/plurimath/math/function/text.rb +32 -0
  87. data/lib/plurimath/math/function/tilde.rb +12 -0
  88. data/lib/plurimath/math/function/tr.rb +25 -0
  89. data/lib/plurimath/math/function/ubrace.rb +12 -0
  90. data/lib/plurimath/math/function/ul.rb +12 -0
  91. data/lib/plurimath/math/function/unary_function.rb +41 -0
  92. data/lib/plurimath/math/function/underover.rb +12 -0
  93. data/lib/plurimath/math/function/underset.rb +12 -0
  94. data/lib/plurimath/math/function/vec.rb +12 -0
  95. data/lib/plurimath/math/function.rb +3 -0
  96. data/lib/plurimath/math/number.rb +29 -0
  97. data/lib/plurimath/math/symbol.rb +34 -0
  98. data/lib/plurimath/math.rb +51 -0
  99. data/lib/plurimath/mathml/constants.rb +327 -0
  100. data/lib/plurimath/mathml/parse.rb +63 -0
  101. data/lib/plurimath/mathml/parser.rb +25 -0
  102. data/lib/plurimath/mathml/transform.rb +195 -0
  103. data/lib/plurimath/mathml.rb +16 -0
  104. data/lib/plurimath/omml.rb +15 -0
  105. data/lib/plurimath/unicode.rb +15 -0
  106. data/lib/plurimath/unitsml.rb +11 -0
  107. data/lib/plurimath/version.rb +3 -1
  108. data/lib/plurimath.rb +3 -5
  109. data/plurimath.gemspec +3 -3
  110. metadata +129 -11
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "unicode"
4
+ require_relative "asciimath"
5
+ require_relative "omml"
6
+ require_relative "mathml"
7
+ require_relative "html"
8
+ require_relative "latex"
9
+ require_relative "unitsml"
10
+ require_relative "math/formula"
11
+ require_relative "math/function"
12
+ require_relative "math/number"
13
+ require_relative "math/symbol"
14
+ require_relative "asciimath/parser"
15
+ require_relative "mathml/parser"
16
+ require_relative "latex/parser"
17
+ module Plurimath
18
+ module Math
19
+ class Error < StandardError; end
20
+
21
+ VALID_TYPES = {
22
+ unicode: Unicode,
23
+ asciimath: Asciimath,
24
+ omml: Omml,
25
+ mathml: Mathml,
26
+ html: Html,
27
+ latex: Latex,
28
+ }.freeze
29
+
30
+ def parse(text, type)
31
+ raise_error! unless valid_type?(type)
32
+
33
+ klass = VALID_TYPES[type.to_sym]
34
+ klass.new(text).to_formula
35
+ end
36
+
37
+ private
38
+
39
+ def raise_error!
40
+ raise Plurimath::Math::Error, Error.new("Type is not valid, "\
41
+ "please enter string or symbol")
42
+ end
43
+
44
+ def valid_type?(type)
45
+ (type.is_a?(Symbol) || type.is_a?(String)) &&
46
+ VALID_TYPES.key?(type.to_sym)
47
+ end
48
+
49
+ module_function :parse, :raise_error!, :valid_type?
50
+ end
51
+ end
@@ -0,0 +1,327 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plurimath
4
+ class Mathml
5
+ class Constants
6
+ UNICODE_SYMBOLS = {
7
+ "&#x3B1;": "alpha",
8
+ "&#x3B2;": "beta",
9
+ "&#x3B3;": "gamma",
10
+ "&#x393;": "Gamma",
11
+ "&#x3B4;": "delta",
12
+ "&#x394;": "Delta",
13
+ "&#x2206;": "Delta",
14
+ "&#x3B5;": "epsilon",
15
+ "&#x25b;": "varepsilon",
16
+ "&#x3B6;": "zeta",
17
+ "&#x3B7;": "eta",
18
+ "&#x3B8;": "theta",
19
+ "&#x398;": "Theta",
20
+ "&#x3D1;": "vartheta",
21
+ "&#x3B9;": "iota",
22
+ "&#x3BA;": "kappa",
23
+ "&#x3BB;": "lambda",
24
+ "&#x39B;": "Lambda",
25
+ "&#x3BC;": "mu",
26
+ "&#x3BD;": "nu",
27
+ "&#x3BE;": "xi",
28
+ "&#x39E;": "Xi",
29
+ "&#x3C0;": "pi",
30
+ "&#x3A0;": "Pi",
31
+ "&#x3C1;": "rho",
32
+ "&#x3C2;": "beta",
33
+ "&#x3C3;": "sigma",
34
+ "&#x3A3;": "Sigma",
35
+ "&#x3C4;": "tau",
36
+ "&#x3C5;": "upsilon",
37
+ "&#x3C6;": "phi",
38
+ "&#x3A6;": "Phi",
39
+ "&#x3D5;": "varphi",
40
+ "&#x3C7;": "chi",
41
+ "&#x3C8;": "psi",
42
+ "&#x3A8;": "Psi",
43
+ "&#x3C9;": "omega",
44
+ "&#x3A9;": "omega",
45
+ "&#x22C5;": "dot",
46
+ "&#x2219;": "*",
47
+ "&#xB7;": ".",
48
+ "&#x2217;": "**",
49
+ "&#x22C6;": "***",
50
+ "&#xD7;": "xx",
51
+ "&#x22C9;": "|><",
52
+ "&#x22CA;": "><|",
53
+ "&#x22C8;": "|><|",
54
+ "&#xF7;": "-:",
55
+ "&#x2218;": "@",
56
+ "&#x2295;": "o+",
57
+ "&#x2A01;": "o+",
58
+ "&#x2297;": "ox",
59
+ "&#x2299;": " ",
60
+ "&#x2211;": "sum",
61
+ "&#x220F;": "prod",
62
+ "&#x220f;": "prod",
63
+ "&#x2227;": "^^",
64
+ "&#x22C0;": "^^^",
65
+ "&#x2228;": "vv",
66
+ "&#x22c1;": "vvv",
67
+ "&#x2229;": "nn",
68
+ "&#x22C2;": "nnn",
69
+ "&#x222A;": "cup",
70
+ "&#x22C3;": "uuu",
71
+ "&#x2260;": "!=",
72
+ "&#x2264;": "<=",
73
+ "&#x2265;": ">=",
74
+ "&#x227A;": "-<",
75
+ "&#x227B;": ">-",
76
+ "&#x2AAF;": "-<=",
77
+ "&#x2AB0;": " >-=",
78
+ "&#x2208;": "in",
79
+ "&#x2209;": "!in",
80
+ "&#x2282;": "sub",
81
+ "&#x2283;": "sup",
82
+ "&#x2286;": "sube",
83
+ "&#x2287;": "supe",
84
+ "&#x2261;": "-=",
85
+ "&#x2245;": "~=",
86
+ "&#x2248;": "~~",
87
+ "&#x221D;": "prop",
88
+ "&#xAC;": "not",
89
+ "&#x2200;": "AA",
90
+ "&#x2203;": "EE",
91
+ "&#x22A5;": "_|_",
92
+ "&#x22A4;": "TT",
93
+ "&#x22A2;": "|--",
94
+ "&#x22A8;": "|==",
95
+ "&#x2329;": "(:",
96
+ "&#x232A;": ":)",
97
+ "&#x27E8;": "<<",
98
+ "&#x27E9;": ">>",
99
+ "&#x222B;": "int",
100
+ "&#x222E;": "oint",
101
+ "&#x2202;": "del",
102
+ "&#x2207;": "grad",
103
+ "&#xB1;": "+-",
104
+ "&#x2205;": "O/",
105
+ "&#x221E;": "oo",
106
+ "&#x2135;": "aleph",
107
+ "&#x2234;": ":.",
108
+ "&#x2235;": ":'",
109
+ "&#x2220;": "/_",
110
+ "&#x25B3;": "/_\\",
111
+ "&#x2032;": "'",
112
+ "&#xA0;&#xA0;": "quad",
113
+ "&#xA0;&#xA0;&#xA0;&#xA0;": "qquad",
114
+ "&#x2322;": "frown",
115
+ "&#x22EF;": "cdots",
116
+ "&#x22EE;": "vdots",
117
+ "&#x22F1;": "ddots",
118
+ "&#x22C4;": "diamond",
119
+ "&#x25A1;": "square",
120
+ "&#x230A;": "|__",
121
+ "&#x230B;": "__|",
122
+ "&#x2308;": "|~",
123
+ "&#x2309;": "~|",
124
+ "&#x2102;": "CC",
125
+ "&#x2115;": "NN",
126
+ "&#x211A;": "QQ",
127
+ "&#x211D;": "RR",
128
+ "&#x2124;": "ZZ",
129
+ "&#x2191;": "uarr",
130
+ "&#x2193;": "darr",
131
+ "&#x2190;": "larr",
132
+ "&#x2194;": "harr",
133
+ "&#x21D2;": "rArr",
134
+ "&#x21D0;": "lArr",
135
+ "&#x21D4;": "hArr",
136
+ "&#x2192;": "->",
137
+ "&#x21A3;": ">->",
138
+ "&#x21A0;": "->>",
139
+ "&#x2916;": ">->>",
140
+ "&#x21A6;": "|->",
141
+ "&#x2026;": "...",
142
+ "&#x2212;": "-",
143
+ "&#x2061;": "",
144
+ "&#x23DE;": "obrace",
145
+ "&#x23DF;": "ubrace",
146
+ }.freeze
147
+ SYMBOLS = {
148
+ "|": "|",
149
+ "/": "//",
150
+ "\\": "\\\\",
151
+ "~": "tilde",
152
+ "(": "(",
153
+ ")": ")",
154
+ "(:": "(:",
155
+ ":)": ":)",
156
+ "{": "{",
157
+ "}": "}",
158
+ "{:": "{:",
159
+ ":}": ":}",
160
+ "]": "]",
161
+ "[": "[",
162
+ "=": "=",
163
+ "+": "+",
164
+ "-": "-",
165
+ }.freeze
166
+ CLASSES = %w[
167
+ mathfrak
168
+ underset
169
+ stackrel
170
+ overset
171
+ mathcal
172
+ arccos
173
+ arcsin
174
+ arctan
175
+ mathsf
176
+ mathbb
177
+ mathbf
178
+ mathtt
179
+ ubrace
180
+ obrace
181
+ cancel
182
+ tilde
183
+ floor
184
+ color
185
+ frac
186
+ root
187
+ oint
188
+ ceil
189
+ ddot
190
+ coth
191
+ csch
192
+ sech
193
+ sinh
194
+ tanh
195
+ cosh
196
+ sqrt
197
+ norm
198
+ text
199
+ prod
200
+ sec
201
+ int
202
+ sin
203
+ tan
204
+ cos
205
+ sum
206
+ exp
207
+ gcd
208
+ glb
209
+ lcm
210
+ lub
211
+ cot
212
+ csc
213
+ det
214
+ dim
215
+ max
216
+ min
217
+ abs
218
+ bar
219
+ dot
220
+ hat
221
+ vec
222
+ mod
223
+ log
224
+ ul
225
+ ln
226
+ f
227
+ g
228
+ ].freeze
229
+ TAGS = %i[
230
+ annotation-xml
231
+ annotation_xml
232
+ mmultiscripts
233
+ maligngroup
234
+ malignmark
235
+ annotation
236
+ munderover
237
+ mscarries
238
+ semantics
239
+ mphantom
240
+ mlongdiv
241
+ menclose
242
+ mscarry
243
+ msubsup
244
+ mpadded
245
+ maction
246
+ msgroup
247
+ mfenced
248
+ merror
249
+ munder
250
+ mtable
251
+ mstyle
252
+ mstack
253
+ mspace
254
+ msline
255
+ mfrac
256
+ mover
257
+ msrow
258
+ mroot
259
+ msqrt
260
+ msup
261
+ msub
262
+ mrow
263
+ math
264
+ mtr
265
+ mtd
266
+ ms
267
+ mi
268
+ mo
269
+ mn
270
+ ].freeze
271
+ BINARY_CLASSES = %i[
272
+ underset
273
+ stackrel
274
+ overset
275
+ color
276
+ prod
277
+ frac
278
+ root
279
+ oint
280
+ int
281
+ sum
282
+ mod
283
+ log
284
+ ].freeze
285
+ FONT_CLASSES = %i[
286
+ fraktur
287
+ sans-serif
288
+ monospace
289
+ script
290
+ double-struck
291
+ bold
292
+ ].freeze
293
+ FONT_TYPES = {
294
+ :bb=>"bold",
295
+ :fr=>"fraktur",
296
+ :cc=>"script",
297
+ :sf=>"sans-serif",
298
+ :tt=>"monospace",
299
+ :mbf=>"bold",
300
+ :mit=>"italic",
301
+ :mtt=>"monospace",
302
+ :Bbb=>"double-struck",
303
+ :bbb=>"double-struck",
304
+ :mscr=>"mathbb",
305
+ :mfrak=>"fraktur",
306
+ :msans=>"sans-serif",
307
+ :mbfit=>"bold italic",
308
+ :mathbf=>"bold",
309
+ :mathit=>"italic",
310
+ :mathds=>"mathbb",
311
+ :mathrm=>"mathrm",
312
+ :mathtt=>"monospace",
313
+ :mathsf=>"sans-serif",
314
+ :mathbb=>"double-struck",
315
+ :mbfsans=>"bold sans-serif",
316
+ :mathcal=>"script",
317
+ :mathbold=>"bold",
318
+ :mathfrak=>"fraktur",
319
+ :mathbfit=>"bold italic",
320
+ :mathsfbf=>"sans-serif bold",
321
+ :mathsfit=>"sans-serif italic",
322
+ :mbfitsans=>"bold italic sans-serif",
323
+ :mathsfbfit=>"sans-serif bold italic",
324
+ }.freeze
325
+ end
326
+ end
327
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "parslet"
4
+ module Plurimath
5
+ class Mathml
6
+ class Parse < Parslet::Parser
7
+ rule(:parse_record) do
8
+ array_to_expression(Constants::CLASSES).as(:class) |
9
+ array_to_expression(Constants::UNICODE_SYMBOLS.keys).as(:symbol) |
10
+ array_to_expression(Constants::SYMBOLS.keys).as(:symbol) |
11
+ match["a-zA-Z"].repeat(1).as(:text) |
12
+ match(/[0-9]/).repeat(1).as(:number) |
13
+ str("")
14
+ end
15
+
16
+ rule(:tag) { (parse_tag(:open) >> iteration.as(:iteration) >> parse_tag(:close)).as(:tag) | parse_text_tag.as(:tag) }
17
+
18
+ rule(:sequence) { (tag >> sequence.as(:sequence)) | tag }
19
+
20
+ rule(:iteration) { (sequence >> iteration.as(:iteration)) | parse_record }
21
+
22
+ rule(:expression) { parse_tag(:open) >> iteration.as(:iteration) >> parse_tag(:close) }
23
+
24
+ root :expression
25
+
26
+ def array_to_expression(array, name = nil)
27
+ initial_type = array.first.class
28
+ array.reduce do |expr, tag|
29
+ expr = str_to_expression(expr, name) if expr.is_a?(initial_type)
30
+ expr | str_to_expression(tag, name)
31
+ end
32
+ end
33
+
34
+ def str_to_expression(string, name)
35
+ return str(string) if name.nil?
36
+
37
+ str(string).as(name)
38
+ end
39
+
40
+ def parse_tag(opts)
41
+ tag = str("<")
42
+ tag = tag >> str("/") if opts == :close
43
+ tag = tag >> array_to_expression(Constants::TAGS, opts)
44
+ tag = tag >> attributes.as(:attributes) if opts == :open
45
+ tag >> str(">")
46
+ end
47
+
48
+ def attributes
49
+ (match["a-zA-Z"].repeat.as(:name) >>
50
+ str("=") >> quoted_string).repeat
51
+ end
52
+
53
+ def quoted_string
54
+ (str('"') >> match("[^\"]").repeat.as(:value) >> str('"')) |
55
+ (str("'") >> match("[^\']").repeat.as(:value) >> str("'"))
56
+ end
57
+
58
+ def parse_text_tag
59
+ str("<mtext>") >> match("[^<]").repeat.as(:quoted_text) >> str("</mtext>")
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "parse"
4
+ require_relative "constants"
5
+ require_relative "transform"
6
+ module Plurimath
7
+ class Mathml
8
+ class Parser
9
+ attr_accessor :text
10
+
11
+ def initialize(text)
12
+ @text = text.gsub("\n", "").gsub(" ", "")
13
+ end
14
+
15
+ def parse
16
+ tree_t = Plurimath::Mathml::Parse.new.parse(text)
17
+ formula = Plurimath::Mathml::Transform.new.apply(tree_t)
18
+ formula = [formula] unless formula.is_a?(Array) || formula.nil?
19
+ return if formula.nil?
20
+
21
+ Plurimath::Math::Formula.new(formula)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,195 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plurimath
4
+ class Mathml
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}]")
19
+ end
20
+ Plurimath::Math::Function::Text.new(text)
21
+ end
22
+
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
33
+ end
34
+
35
+ rule(
36
+ tag: sequence(:tag),
37
+ sequence: simple(:sequence),
38
+ iteration: simple(:iteration),
39
+ ) do
40
+ Plurimath::Math::Formula.new(tag + [sequence])
41
+ end
42
+
43
+ rule(
44
+ tag: simple(:tag),
45
+ sequence: simple(:sequence),
46
+ iteration: simple(:iteration),
47
+ ) do
48
+ [tag, sequence]
49
+ end
50
+
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
56
+ end
57
+
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
63
+ end
64
+
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
70
+ end
71
+
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])
78
+ else
79
+ Plurimath::Math::Symbol.new(decoded_symbol)
80
+ end
81
+ end
82
+
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
90
+ end
91
+ end
92
+
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)
101
+ 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
106
+ end
107
+ end
108
+
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)
162
+ end
163
+ else
164
+ iteration
165
+ end
166
+ end
167
+
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
175
+
176
+ if iteration.to_s.include?("Function")
177
+ iteration
178
+ else
179
+ [iteration.to_s.empty? ? nil : iteration]
180
+ end
181
+ end
182
+
183
+ def self.get_class(text)
184
+ Object.const_get("Plurimath::Math::Function::#{text.to_s.capitalize}")
185
+ end
186
+
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)
192
+ end
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "math"
4
+ module Plurimath
5
+ class Mathml
6
+ attr_accessor :text
7
+
8
+ def initialize(text)
9
+ @text = text
10
+ end
11
+
12
+ def to_formula
13
+ Plurimath::Mathml::Parser.new(text).parse
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plurimath
4
+ class Omml
5
+ attr_accessor :text
6
+
7
+ def initialize(text)
8
+ @text = text
9
+ end
10
+
11
+ def to_formula
12
+ # TODO: Will be implemented soon
13
+ end
14
+ end
15
+ end