plurimath 0.2.1 → 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 (110) 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/.hound.yml +5 -0
  5. data/.rubocop.yml +8 -0
  6. data/AsciiMath-Supported-Data.adoc +1994 -274
  7. data/Gemfile +2 -0
  8. data/Latex-Supported-Data.adoc +1875 -1868
  9. data/MathML-Supported-Data.adoc +280 -263
  10. data/README.adoc +22 -20
  11. data/lib/plurimath/asciimath/constants.rb +186 -141
  12. data/lib/plurimath/asciimath/parse.rb +104 -39
  13. data/lib/plurimath/asciimath/parser.rb +3 -1
  14. data/lib/plurimath/asciimath/transform.rb +1074 -238
  15. data/lib/plurimath/html/parse.rb +1 -1
  16. data/lib/plurimath/latex/constants.rb +3228 -1432
  17. data/lib/plurimath/latex/parse.rb +106 -83
  18. data/lib/plurimath/latex/parser.rb +11 -4
  19. data/lib/plurimath/latex/transform.rb +354 -99
  20. data/lib/plurimath/math/base.rb +15 -0
  21. data/lib/plurimath/math/formula.rb +90 -13
  22. data/lib/plurimath/math/function/bar.rb +35 -1
  23. data/lib/plurimath/math/function/base.rb +25 -4
  24. data/lib/plurimath/math/function/binary_function.rb +101 -19
  25. data/lib/plurimath/math/function/cancel.rb +8 -0
  26. data/lib/plurimath/math/function/ceil.rb +3 -0
  27. data/lib/plurimath/math/function/color.rb +15 -5
  28. data/lib/plurimath/math/function/f.rb +8 -0
  29. data/lib/plurimath/math/function/fenced.rb +95 -8
  30. data/lib/plurimath/math/function/floor.rb +15 -0
  31. data/lib/plurimath/math/function/font_style/bold.rb +19 -0
  32. data/lib/plurimath/math/function/font_style/double_struck.rb +19 -0
  33. data/lib/plurimath/math/function/font_style/fraktur.rb +19 -0
  34. data/lib/plurimath/math/function/font_style/italic.rb +37 -0
  35. data/lib/plurimath/math/function/font_style/monospace.rb +19 -0
  36. data/lib/plurimath/math/function/font_style/normal.rb +37 -0
  37. data/lib/plurimath/math/function/font_style/sans-serif.rb +19 -0
  38. data/lib/plurimath/math/function/font_style/script.rb +19 -0
  39. data/lib/plurimath/math/function/font_style.rb +18 -5
  40. data/lib/plurimath/math/function/frac.rb +33 -3
  41. data/lib/plurimath/math/function/g.rb +7 -0
  42. data/lib/plurimath/math/function/hat.rb +12 -0
  43. data/lib/plurimath/math/function/inf.rb +21 -0
  44. data/lib/plurimath/math/function/int.rb +23 -2
  45. data/lib/plurimath/math/function/left.rb +25 -1
  46. data/lib/plurimath/math/function/lim.rb +40 -2
  47. data/lib/plurimath/math/function/limits.rb +9 -0
  48. data/lib/plurimath/math/function/log.rb +55 -4
  49. data/lib/plurimath/math/function/longdiv.rb +12 -0
  50. data/lib/plurimath/math/function/mbox.rb +31 -0
  51. data/lib/plurimath/math/function/menclose.rb +46 -0
  52. data/lib/plurimath/math/function/merror.rb +12 -0
  53. data/lib/plurimath/math/function/mod.rb +19 -4
  54. data/lib/plurimath/math/function/msgroup.rb +37 -0
  55. data/lib/plurimath/math/function/msline.rb +12 -0
  56. data/lib/plurimath/math/function/multiscript.rb +19 -0
  57. data/lib/plurimath/math/function/norm.rb +17 -1
  58. data/lib/plurimath/math/function/obrace.rb +17 -0
  59. data/lib/plurimath/math/function/oint.rb +2 -2
  60. data/lib/plurimath/math/function/over.rb +12 -5
  61. data/lib/plurimath/math/function/overset.rb +34 -5
  62. data/lib/plurimath/math/function/phantom.rb +28 -0
  63. data/lib/plurimath/math/function/power.rb +27 -9
  64. data/lib/plurimath/math/function/power_base.rb +109 -11
  65. data/lib/plurimath/math/function/prod.rb +25 -4
  66. data/lib/plurimath/math/function/right.rb +22 -2
  67. data/lib/plurimath/math/function/root.rb +23 -1
  68. data/lib/plurimath/math/function/rule.rb +33 -0
  69. data/lib/plurimath/math/function/scarries.rb +12 -0
  70. data/lib/plurimath/math/function/scarry.rb +12 -0
  71. data/lib/plurimath/math/function/sqrt.rb +23 -1
  72. data/lib/plurimath/math/function/stackrel.rb +27 -0
  73. data/lib/plurimath/math/function/substack.rb +7 -0
  74. data/lib/plurimath/math/function/sum.rb +50 -2
  75. data/lib/plurimath/math/function/sup.rb +3 -0
  76. data/lib/plurimath/math/function/table/align.rb +5 -5
  77. data/lib/plurimath/math/function/table/array.rb +25 -6
  78. data/lib/plurimath/math/function/table/bmatrix.rb +18 -7
  79. data/lib/plurimath/math/function/table/matrix.rb +13 -5
  80. data/lib/plurimath/math/function/table/multline.rb +5 -5
  81. data/lib/plurimath/math/function/table/pmatrix.rb +5 -5
  82. data/lib/plurimath/math/function/table/split.rb +5 -5
  83. data/lib/plurimath/math/function/table/vmatrix.rb +5 -6
  84. data/lib/plurimath/math/function/table.rb +185 -27
  85. data/lib/plurimath/math/function/td.rb +22 -9
  86. data/lib/plurimath/math/function/ternary_function.rb +74 -9
  87. data/lib/plurimath/math/function/text.rb +36 -11
  88. data/lib/plurimath/math/function/tr.rb +23 -4
  89. data/lib/plurimath/math/function/ubrace.rb +17 -0
  90. data/lib/plurimath/math/function/ul.rb +29 -0
  91. data/lib/plurimath/math/function/unary_function.rb +81 -8
  92. data/lib/plurimath/math/function/underline.rb +12 -0
  93. data/lib/plurimath/math/function/underover.rb +107 -0
  94. data/lib/plurimath/math/function/underset.rb +39 -0
  95. data/lib/plurimath/math/function/vec.rb +7 -1
  96. data/lib/plurimath/math/number.rb +5 -5
  97. data/lib/plurimath/math/symbol.rb +51 -12
  98. data/lib/plurimath/math/unicode.rb +11 -0
  99. data/lib/plurimath/math.rb +7 -3
  100. data/lib/plurimath/mathml/constants.rb +224 -147
  101. data/lib/plurimath/mathml/parser.rb +24 -8
  102. data/lib/plurimath/mathml/transform.rb +249 -153
  103. data/lib/plurimath/omml/parser.rb +24 -4
  104. data/lib/plurimath/omml/transform.rb +219 -157
  105. data/lib/plurimath/utility.rb +342 -20
  106. data/lib/plurimath/version.rb +1 -1
  107. metadata +21 -6
  108. data/.github/workflows/test.yml +0 -33
  109. data/lib/plurimath/mathml/parse.rb +0 -68
  110. data/lib/plurimath/omml/constants.rb +0 -154
@@ -4,48 +4,32 @@ require "parslet"
4
4
  module Plurimath
5
5
  class Latex
6
6
  class Parse < Parslet::Parser
7
- rule(:base) { str("_") }
8
- rule(:power) { str("^") }
9
- rule(:slash) { str("\\") }
10
- rule(:unary) { slash >> unary_classes }
11
- rule(:ending) { (slash >> str("end") >> intermediate_exp).as(:ending) }
12
- rule(:binary) { slash >> binary_classes }
13
-
14
- rule(:array_args) { (str("{") >> expression >> str("}")).as(:args) }
7
+ rule(:base) { str("_") }
8
+ rule(:power) { str("^") }
9
+ rule(:slash) { str("\\") }
15
10
  rule(:under_over) { slash >> underover_classes }
11
+ rule(:array_args) { (str("{") >> expression.as(:args) >> str("}")) }
16
12
 
17
- rule(:begining) do
18
- (slash >> str("begin") >> intermediate_exp).as(:begining)
13
+ rule(:optional_args) do
14
+ (str("[") >> intermediate_exp.maybe.as(:options) >> str("]")).maybe
19
15
  end
20
16
 
21
- rule(:symbols) do
22
- arr_to_expression(Constants::SYMBOLS.keys, :symbols)
17
+ rule(:begining) do
18
+ (slash >> str("begin") >> (str("{") >> symbol_text_or_integer >> str("*").as(:asterisk).maybe >> str("}")) >> optional_args)
23
19
  end
24
20
 
25
- rule(:operators) do
26
- arr_to_expression(Constants::OPERATORS, :operant)
21
+ rule(:ending) do
22
+ (slash >> str("end") >> (str("{") >> symbol_text_or_integer >> str("*").maybe >> str("}"))).as(:ending)
27
23
  end
28
24
 
29
25
  rule(:numeric_values) do
30
26
  arr_to_expression(Constants::NUMERIC_VALUES, :numeric_values)
31
27
  end
32
28
 
33
- rule(:unary_classes) do
34
- arr_to_expression(Constants::UNARY_CLASSES, :unary)
35
- end
36
-
37
- rule(:binary_classes) do
38
- arr_to_expression(Constants::BINARY_CLASSES, :binary)
39
- end
40
-
41
29
  rule(:underover_classes) do
42
30
  arr_to_expression(Constants::UNDEROVER_CLASSES, :binary)
43
31
  end
44
32
 
45
- rule(:power_base_classes) do
46
- arr_to_expression(Constants::POWER_BASE_CLASSES, :binary)
47
- end
48
-
49
33
  rule(:math_operators_classes) do
50
34
  arr_to_expression(Constants::MATH_OPERATORS, :unary_functions)
51
35
  end
@@ -58,6 +42,10 @@ module Plurimath
58
42
  arr_to_expression(Constants::PARENTHESIS.values, :rparen)
59
43
  end
60
44
 
45
+ rule(:environment) do
46
+ arr_to_expression(Constants::MATRICES.keys, :environment)
47
+ end
48
+
61
49
  rule(:subscript) do
62
50
  intermediate_exp >> base >> intermediate_exp.as(:subscript)
63
51
  end
@@ -66,24 +54,13 @@ module Plurimath
66
54
  intermediate_exp >> power >> intermediate_exp.as(:supscript)
67
55
  end
68
56
 
69
- rule(:environment) do
70
- arr_to_expression(Constants::MATRICES.keys, :environment)
71
- end
72
-
73
- rule(:fonts) do
74
- arr_to_expression(Constants::FONT_STYLES, :fonts)
75
- end
76
-
77
57
  rule(:math_operators) do
78
- slash >> math_operators_classes >> str("\\limits")
79
- end
80
-
81
- rule(:left_right) do
82
- (str("\\left").as(:left) >> lparen >> expression.as(:expression) >> str("\\right").as(:right) >> rparen)
58
+ symbol_text_or_integer.as(:first_value) >> str("\\limits")
83
59
  end
84
60
 
85
61
  rule(:sqrt_arg) do
86
- str("[").as(:lparen) >> (expression | str("")) >> str("]").as(:rparen)
62
+ (str("[").as(:lparen) >> intermediate_exp.repeat(1).as(:expression) >> str("]").as(:rparen)) |
63
+ (str("[").as(:lparen) >> str("]").as(:rparen))
87
64
  end
88
65
 
89
66
  rule(:limits) do
@@ -92,29 +69,27 @@ module Plurimath
92
69
  end
93
70
 
94
71
  rule(:symbol_class_commands) do
95
- (slash >> symbols) |
96
- (unary >> intermediate_exp.as(:first_value)).as(:unary_functions) |
97
- unary.as(:unary_functions) |
98
- binary |
72
+ (str("&#x") >> match["0-9a-fA-F"].repeat >> str(";")).as(:unicode_symbols) |
73
+ hash_to_expression(Constants::SYMBOLS) |
99
74
  under_over |
100
75
  environment |
101
- operators |
102
- numeric_values |
103
- (slash >> power_base_classes) |
104
- (slash >> fonts >> (binary_functions | intermediate_exp).as(:intermediate_exp))
76
+ numeric_values
105
77
  end
106
78
 
107
79
  rule(:symbol_text_or_integer) do
108
80
  symbol_class_commands |
109
- match["a-zA-Z"].repeat(1).as(:text) |
81
+ (slash >> math_operators_classes) |
82
+ match["a-zA-Z"].as(:symbols) |
110
83
  (str('"') >> match("[^\"]").repeat >> str('"')).as(:text) |
111
84
  match(/\d+(\.[0-9]+)|\d/).repeat(1).as(:number) |
112
- str("\\\\").as("\\\\")
85
+ str("\\\\").as("\\\\") |
86
+ (slash >> (lparen | rparen).as(:symbols)) |
87
+ lparen |
88
+ str("\\ ").as(:space)
113
89
  end
114
90
 
115
91
  rule(:intermediate_exp) do
116
- (lparen >> expression.as(:expression) >> rparen) |
117
- (lparen >> str("") >> rparen) |
92
+ (str("{") >> expression.maybe.as(:expression) >> str("}")) |
118
93
  symbol_text_or_integer
119
94
  end
120
95
 
@@ -126,73 +101,121 @@ module Plurimath
126
101
  end
127
102
 
128
103
  rule(:binary_functions) do
129
- (slash >> str("sqrt").as(:root) >> sqrt_arg.as(:first_value) >> intermediate_exp.as(:second_value)).as(:binary) |
130
- (slash >> str("sqrt").as(:sqrt) >> intermediate_exp.as(:intermediate_exp)).as(:binary) |
131
- (intermediate_exp.as(:first_value) >> under_over >> intermediate_exp.as(:second_value)).as(:under_over) |
132
- (binary >> intermediate_exp.as(:first_value) >> intermediate_exp.as(:second_value)).as(:binary)
104
+ (intermediate_exp.as(:first_value) >> under_over >> intermediate_exp.as(:second_value)).as(:under_over) |
105
+ (slash >> str("sqrt").as(:root) >> sqrt_arg.as(:first_value) >> intermediate_exp.as(:second_value)).as(:binary) |
106
+ (slash >> str("sqrt").as(:sqrt) >> intermediate_exp.as(:intermediate_exp)).as(:binary)
133
107
  end
134
108
 
135
109
  rule(:sequence) do
136
110
  limits.as(:limits) |
137
- (left_right.as(:left_right) >> power >> intermediate_exp.as(:supscript)) |
138
- (left_right.as(:left_right) >> base >> intermediate_exp.as(:subscript)) |
139
- left_right.as(:left_right) |
111
+ (binary_functions.as(:binary_functions) >> power >> sequence.as(:supscript)).as(:power) |
112
+ (binary_functions.as(:binary_functions) >> base >> sequence.as(:subscript)).as(:base) |
113
+ binary_functions |
114
+ (slash >> str("rule").as(:rule) >> sqrt_arg.maybe.as(:first_value) >> intermediate_exp.maybe.as(:second_value) >> intermediate_exp.maybe.as(:third_value)).as(:binary) |
140
115
  (over_class >> power >> intermediate_exp.as(:supscript)) |
141
116
  (over_class >> base >> intermediate_exp.as(:subscript)) |
142
117
  over_class |
143
- (slash >> str("mbox") >> lparen.capture(:paren) >> read_text >> rparen).as(:unary_functions) |
144
- (slash >> str("substack").as(:substack) >> lparen >> expression.as(:substack_value) >> rparen) |
118
+ (left_right.as(:left_right) >> power >> intermediate_exp.as(:supscript)) |
119
+ (left_right.as(:left_right) >> base >> intermediate_exp.as(:subscript)) |
120
+ left_right.as(:left_right) |
121
+ (slash >> str("substack").as(:substack) >> intermediate_exp) |
145
122
  (begining >> array_args >> expression.as(:table_data) >> ending).as(:environment) |
146
123
  (begining >> expression.as(:table_data) >> ending).as(:environment) |
147
124
  (slash >> environment >> intermediate_exp).as(:table_data) |
148
125
  power_base |
149
- binary_functions |
126
+ (rparen >> (base >> sequence.as(:subscript)).maybe >> power >> sequence.as(:supscript)).as(:power_base) |
127
+ (rparen >> (power >> sequence.as(:supscript)) >> base >> sequence.as(:subscript)).as(:power_base) |
128
+ rparen |
150
129
  intermediate_exp
151
130
  end
152
131
 
153
- rule(:left_right_over) do
154
- (str("\\left").as(:left) >>
155
- lparen >>
156
- expression.repeat.as(:dividend) >>
157
- str("\\over") >>
158
- expression.repeat.as(:divisor) >>
159
- str("\\right").as(:right) >>
160
- rparen)
132
+ rule(:left_right) do
133
+ (
134
+ str("\\left").as(:left) >> lparen.maybe >>
135
+ (
136
+ (expression.repeat.as(:dividend) >> str("\\over") >> expression.repeat.as(:divisor)) |
137
+ expression.as(:expression).maybe
138
+ ) >>
139
+ str("\\right").as(:right).maybe >> (rparen | str(".").maybe)
140
+ )
161
141
  end
162
142
 
163
143
  rule(:over_class) do
164
144
  (
165
145
  (str("{") >> expression.repeat.as(:dividend) >> str("\\over") >> expression.repeat.as(:divisor) >> str("}")) |
166
- (left_right_over.as(:left_right).as(:power) >> power >> intermediate_exp) |
167
- (left_right_over.as(:left_right).as(:base) >> base >> intermediate_exp) |
168
- left_right_over.as(:left_right)
146
+ (left_right.as(:left_right).as(:power) >> power >> intermediate_exp) |
147
+ (left_right.as(:left_right).as(:base) >> base >> intermediate_exp)
169
148
  ).as(:over)
170
149
  end
171
150
 
172
151
  rule(:iteration) do
173
- (sequence.as(:sequence) >> expression.as(:expression)) | sequence
152
+ (sequence.as(:sequence) >> expression.as(:expression)) |
153
+ sequence
174
154
  end
175
155
 
176
- rule(:expression) { (iteration >> expression) | iteration }
156
+ rule(:expression) do
157
+ (iteration >> expression) |
158
+ iteration |
159
+ ((iteration.as(:dividend) >> str("\\over") >> iteration.as(:divisor)) >> expression.repeat)
160
+ end
177
161
 
178
162
  root :expression
179
163
 
180
- def arr_to_expression(array, name = nil)
164
+ def arr_to_expression(array, name)
165
+ @@new_hash ||= {}
181
166
  type = array.first.class
182
- array.reduce do |expression, expr_string|
183
- name = name || expr_string.to_sym || expression.to_sym
167
+ @@new_hash[name] ||= array.reduce do |expression, expr_string|
184
168
  expression = str(expression).as(name) if expression.is_a?(type)
185
169
  expression | str(expr_string).as(name)
186
170
  end
187
171
  end
188
172
 
189
- def read_text
190
- dynamic do |_sour, context|
191
- lparen = context.captures[:paren][:lparen].to_s
192
- rparen = Constants::PARENTHESIS[lparen]
193
- match("[^#{rparen}]").repeat.as(:mbox)
173
+ def hash_to_expression(hash)
174
+ @@expression ||= hash.reduce do |expression, (key, value)|
175
+ expression = dynamic_rules(expression.first, expression.last) if expression.is_a?(Array)
176
+ expression | dynamic_rules(key, value)
194
177
  end
195
178
  end
179
+
180
+ def dynamic_rules(expr, name)
181
+ first_value = str(expr.to_s)
182
+ case name
183
+ when :operant
184
+ (first_value.as(:operant) | (slashed_value(first_value, :symbols)))
185
+ when :symbols
186
+ slashed_value(first_value, :symbols)
187
+ when :unary
188
+ unary_rules(first_value)
189
+ when :fonts
190
+ (slashed_value(first_value, :fonts) >> (binary_functions | intermediate_exp).as(:intermediate_exp))
191
+ when :power_base
192
+ (slashed_value(first_value, :binary) >> dynamic_power_base).as(:power_base) |
193
+ (slashed_value(first_value, :binary))
194
+ when :underover
195
+ (slashed_value(first_value, :underover) >> dynamic_power_base) |
196
+ (slashed_value(first_value, :underover) >> intermediate_exp.maybe.as(:first_value) >> dynamic_power_base) |
197
+ (slashed_value(first_value, :underover))
198
+ when :binary
199
+ (slashed_value(first_value, :binary) >> intermediate_exp.as(:first_value) >> intermediate_exp.as(:second_value)).as(:binary)
200
+ end
201
+ end
202
+
203
+ def slashed_value(first_value, name = nil)
204
+ (slash >> first_value.as(name))
205
+ end
206
+
207
+ def unary_rules(first_value)
208
+ (slashed_value(first_value, :unary_functions) >> dynamic_power_base) |
209
+ (slashed_value(first_value, :unary) >> intermediate_exp.as(:first_value)).as(:unary_functions) |
210
+ (slashed_value(first_value, :unary))
211
+ end
212
+
213
+ def dynamic_power_base
214
+ (base >> intermediate_exp.as(:subscript) >> power >> intermediate_exp.as(:supscript)) |
215
+ (power >> intermediate_exp.as(:supscript) >> base >> intermediate_exp.as(:subscript)) |
216
+ (power >> intermediate_exp.as(:supscript)) |
217
+ (base >> intermediate_exp.as(:subscript))
218
+ end
196
219
  end
197
220
  end
198
221
  end
@@ -9,13 +9,20 @@ module Plurimath
9
9
  attr_accessor :text
10
10
 
11
11
  def initialize(text)
12
- @text = text.gsub(/\s/, "")
12
+ enti = HTMLEntities.new
13
+ text = enti.encode(enti.decode(text), :hexadecimal)
14
+ text = text
15
+ .gsub(/((?<!\\) )|\n+/, "")
16
+ .gsub(/\\\\ /, "\\\\\\\\")
17
+ .gsub(/&#x26;/, "&")
18
+ .gsub(/&#x22;/, "\"")
19
+ .gsub(/&#xa;/, "")
20
+ @text = text
13
21
  end
14
22
 
15
23
  def parse
16
- tree_t = Latex::Parse.new.parse(text)
17
- tree_t = JSON.parse(tree_t.to_json, symbolize_names: true)
18
- formula = Latex::Transform.new.apply(tree_t)
24
+ tree_t = Parse.new.parse(text)
25
+ formula = Transform.new.apply(tree_t)
19
26
  formula = [formula] unless formula.is_a?(Array)
20
27
 
21
28
  Math::Formula.new(formula)