plurimath 0.2.1 → 0.2.2

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/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)