plurimath 0.11.11 → 0.11.13
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.
- checksums.yaml +4 -4
- data/.github/workflows/dependent-tests.yml +7 -0
- data/.github/workflows/shared-testsuite.yml +24 -0
- data/.gitmodules +3 -0
- data/.rspec-opal +3 -0
- data/Gemfile +18 -0
- data/README.adoc +297 -3
- data/docs/catalog.adoc +73 -0
- data/docs/uncertainty-asciimath-tree.md +92 -0
- data/docs/uncertainty.adoc +522 -0
- data/lib/plurimath/asciimath/parse.rb +43 -226
- data/lib/plurimath/asciimath/parser.rb +58 -1
- data/lib/plurimath/asciimath/slice_adapter.rb +138 -0
- data/lib/plurimath/asciimath/transform.rb +218 -0
- data/lib/plurimath/asciimath.rb +1 -0
- data/lib/plurimath/catalog/entry.rb +109 -0
- data/lib/plurimath/catalog/validation.rb +109 -0
- data/lib/plurimath/catalog.rb +96 -0
- data/lib/plurimath/cli/convert.rb +40 -0
- data/lib/plurimath/cli/helpers.rb +49 -0
- data/lib/plurimath/cli/render.rb +64 -0
- data/lib/plurimath/cli.rb +55 -57
- data/lib/plurimath/documentation.rb +99 -0
- data/lib/plurimath/errors/ambiguous_decimal_error.rb +19 -0
- data/lib/plurimath/errors/invalid_uncertainty.rb +18 -0
- data/lib/plurimath/errors/missing_dependency_error.rb +23 -0
- data/lib/plurimath/errors/rendering_failed.rb +17 -0
- data/lib/plurimath/errors/rendering_unavailable.rb +25 -0
- data/lib/plurimath/errors/unsupported_render_format.rb +18 -0
- data/lib/plurimath/errors/unsupported_semantic_tree_error.rb +12 -0
- data/lib/plurimath/errors.rb +5 -0
- data/lib/plurimath/math/evaluation/evaluator.rb +48 -0
- data/lib/plurimath/math/evaluation/expression_parser.rb +29 -20
- data/lib/plurimath/math/formula/class_tree.rb +92 -0
- data/lib/plurimath/math/formula.rb +43 -2
- data/lib/plurimath/math/function/abs.rb +6 -0
- data/lib/plurimath/math/function/arccos.rb +6 -0
- data/lib/plurimath/math/function/arcsin.rb +6 -0
- data/lib/plurimath/math/function/arctan.rb +6 -0
- data/lib/plurimath/math/function/arg.rb +20 -0
- data/lib/plurimath/math/function/bar.rb +6 -0
- data/lib/plurimath/math/function/base.rb +6 -0
- data/lib/plurimath/math/function/binary_function.rb +4 -0
- data/lib/plurimath/math/function/cancel.rb +6 -0
- data/lib/plurimath/math/function/ceil.rb +6 -0
- data/lib/plurimath/math/function/color.rb +12 -0
- data/lib/plurimath/math/function/cos.rb +6 -0
- data/lib/plurimath/math/function/cosh.rb +6 -0
- data/lib/plurimath/math/function/cot.rb +6 -0
- data/lib/plurimath/math/function/coth.rb +6 -0
- data/lib/plurimath/math/function/csc.rb +6 -0
- data/lib/plurimath/math/function/csch.rb +6 -0
- data/lib/plurimath/math/function/ddot.rb +6 -0
- data/lib/plurimath/math/function/deg.rb +6 -0
- data/lib/plurimath/math/function/det.rb +6 -0
- data/lib/plurimath/math/function/dim.rb +6 -0
- data/lib/plurimath/math/function/dot.rb +6 -0
- data/lib/plurimath/math/function/exp.rb +6 -0
- data/lib/plurimath/math/function/fenced.rb +6 -0
- data/lib/plurimath/math/function/floor.rb +6 -0
- data/lib/plurimath/math/function/font_style/bold-fraktur.rb +6 -0
- data/lib/plurimath/math/function/font_style/bold-italic.rb +6 -0
- data/lib/plurimath/math/function/font_style/bold-sans-serif.rb +6 -0
- data/lib/plurimath/math/function/font_style/bold-script.rb +6 -0
- data/lib/plurimath/math/function/font_style/bold.rb +6 -0
- data/lib/plurimath/math/function/font_style/double_struck.rb +6 -0
- data/lib/plurimath/math/function/font_style/fraktur.rb +6 -0
- data/lib/plurimath/math/function/font_style/italic.rb +6 -0
- data/lib/plurimath/math/function/font_style/monospace.rb +6 -0
- data/lib/plurimath/math/function/font_style/normal.rb +6 -0
- data/lib/plurimath/math/function/font_style/sans-serif-bold-italic.rb +6 -0
- data/lib/plurimath/math/function/font_style/sans-serif-italic.rb +6 -0
- data/lib/plurimath/math/function/font_style/sans-serif.rb +6 -0
- data/lib/plurimath/math/function/font_style/script.rb +6 -0
- data/lib/plurimath/math/function/font_style.rb +4 -0
- data/lib/plurimath/math/function/frac.rb +6 -0
- data/lib/plurimath/math/function/gcd.rb +6 -0
- data/lib/plurimath/math/function/glb.rb +12 -0
- data/lib/plurimath/math/function/hat.rb +6 -0
- data/lib/plurimath/math/function/hom.rb +6 -0
- data/lib/plurimath/math/function/inf.rb +6 -0
- data/lib/plurimath/math/function/int.rb +7 -1
- data/lib/plurimath/math/function/intent.rb +35 -0
- data/lib/plurimath/math/function/ker.rb +6 -0
- data/lib/plurimath/math/function/lcm.rb +12 -0
- data/lib/plurimath/math/function/lg.rb +6 -0
- data/lib/plurimath/math/function/lim.rb +6 -0
- data/lib/plurimath/math/function/liminf.rb +6 -0
- data/lib/plurimath/math/function/limits.rb +6 -0
- data/lib/plurimath/math/function/limsup.rb +6 -0
- data/lib/plurimath/math/function/ln.rb +6 -0
- data/lib/plurimath/math/function/log.rb +6 -0
- data/lib/plurimath/math/function/longdiv.rb +6 -0
- data/lib/plurimath/math/function/lub.rb +6 -0
- data/lib/plurimath/math/function/max.rb +6 -0
- data/lib/plurimath/math/function/mbox.rb +6 -0
- data/lib/plurimath/math/function/menclose.rb +19 -0
- data/lib/plurimath/math/function/merror.rb +22 -0
- data/lib/plurimath/math/function/min.rb +6 -0
- data/lib/plurimath/math/function/mlabeledtr.rb +23 -0
- data/lib/plurimath/math/function/mod.rb +6 -0
- data/lib/plurimath/math/function/msgroup.rb +20 -0
- data/lib/plurimath/math/function/multiscript.rb +6 -0
- data/lib/plurimath/math/function/nary.rb +11 -0
- data/lib/plurimath/math/function/norm.rb +6 -0
- data/lib/plurimath/math/function/obrace.rb +6 -0
- data/lib/plurimath/math/function/oint.rb +7 -1
- data/lib/plurimath/math/function/over.rb +6 -0
- data/lib/plurimath/math/function/overleftrightarrow.rb +6 -0
- data/lib/plurimath/math/function/overset.rb +6 -0
- data/lib/plurimath/math/function/phantom.rb +6 -0
- data/lib/plurimath/math/function/power.rb +6 -0
- data/lib/plurimath/math/function/power_base.rb +6 -0
- data/lib/plurimath/math/function/prod.rb +7 -1
- data/lib/plurimath/math/function/right.rb +1 -1
- data/lib/plurimath/math/function/root.rb +6 -0
- data/lib/plurimath/math/function/rule.rb +20 -0
- data/lib/plurimath/math/function/scarries.rb +20 -0
- data/lib/plurimath/math/function/sec.rb +6 -0
- data/lib/plurimath/math/function/sech.rb +6 -0
- data/lib/plurimath/math/function/semantics.rb +20 -0
- data/lib/plurimath/math/function/sin.rb +6 -0
- data/lib/plurimath/math/function/sinh.rb +6 -0
- data/lib/plurimath/math/function/sqrt.rb +6 -0
- data/lib/plurimath/math/function/stackrel.rb +6 -0
- data/lib/plurimath/math/function/substack.rb +6 -0
- data/lib/plurimath/math/function/sum.rb +7 -1
- data/lib/plurimath/math/function/sup.rb +6 -0
- data/lib/plurimath/math/function/table/align.rb +6 -0
- data/lib/plurimath/math/function/table/array.rb +6 -0
- data/lib/plurimath/math/function/table/bmatrix.rb +6 -0
- data/lib/plurimath/math/function/table/cases.rb +6 -0
- data/lib/plurimath/math/function/table/eqarray.rb +6 -0
- data/lib/plurimath/math/function/table/matrix.rb +6 -0
- data/lib/plurimath/math/function/table/multline.rb +6 -0
- data/lib/plurimath/math/function/table/pmatrix.rb +6 -0
- data/lib/plurimath/math/function/table/split.rb +6 -0
- data/lib/plurimath/math/function/table/vmatrix.rb +6 -0
- data/lib/plurimath/math/function/table.rb +10 -0
- data/lib/plurimath/math/function/tan.rb +6 -0
- data/lib/plurimath/math/function/tanh.rb +6 -0
- data/lib/plurimath/math/function/ternary_function.rb +4 -0
- data/lib/plurimath/math/function/text.rb +6 -0
- data/lib/plurimath/math/function/tilde.rb +6 -0
- data/lib/plurimath/math/function/ubrace.rb +6 -0
- data/lib/plurimath/math/function/ul.rb +6 -0
- data/lib/plurimath/math/function/unary_function.rb +4 -0
- data/lib/plurimath/math/function/uncertainty.rb +655 -0
- data/lib/plurimath/math/function/underover.rb +6 -0
- data/lib/plurimath/math/function/underset.rb +6 -0
- data/lib/plurimath/math/function/vec.rb +6 -0
- data/lib/plurimath/math/function.rb +1 -0
- data/lib/plurimath/math/renderer.rb +95 -0
- data/lib/plurimath/math/semantic_tree.rb +331 -0
- data/lib/plurimath/math/symbols/symbol.rb +12 -5
- data/lib/plurimath/math.rb +26 -0
- data/lib/plurimath/mathml/translator.rb +32 -0
- data/lib/plurimath/mathml/uncertainty_marker.rb +118 -0
- data/lib/plurimath/omml/translator.rb +68 -0
- data/lib/plurimath/omml/utility.rb +9 -1
- data/lib/plurimath/symbol_documentation.rb +57 -0
- data/lib/plurimath/unicode_math/parsing_rules/common_rules.rb +2 -1
- data/lib/plurimath/unicode_math/parsing_rules/masked.rb +3 -0
- data/lib/plurimath/unicode_math/transform.rb +64 -3
- data/lib/plurimath/unicode_math/utility.rb +38 -0
- data/lib/plurimath/version.rb +1 -1
- data/lib/plurimath.rb +3 -0
- data/plurimath.gemspec +3 -1
- data/scripts/replay_asciimath_corpus.rb +611 -0
- metadata +30 -4
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../mathml/uncertainty_marker"
|
|
4
|
+
|
|
3
5
|
module Plurimath
|
|
4
6
|
class Omml
|
|
5
7
|
class Translator
|
|
@@ -261,9 +263,75 @@ module Plurimath
|
|
|
261
263
|
end
|
|
262
264
|
|
|
263
265
|
def box_to_plurimath(node)
|
|
266
|
+
children = ordered_omml_children(first_omml_child(node.e))
|
|
267
|
+
marker = uncertainty_marker_text(children.first)
|
|
268
|
+
return box_to_uncertainty(marker, children.drop(1)) if marker
|
|
269
|
+
|
|
264
270
|
omml_argument_value(node.e)
|
|
265
271
|
end
|
|
266
272
|
|
|
273
|
+
# An m:box whose first child is a hidden m:phant holding an
|
|
274
|
+
# uncertainty marker (plurimath#493). The marker is authoritative; the
|
|
275
|
+
# visible content is regenerated on output, so only the inner m:box
|
|
276
|
+
# holding the unit is read.
|
|
277
|
+
def box_to_uncertainty(marker, visible)
|
|
278
|
+
Mathml::UncertaintyMarker.build(marker) do
|
|
279
|
+
units = visible.select { |child| omml_class?(child, "CTBox") }
|
|
280
|
+
if units.length > 1
|
|
281
|
+
raise Errors::InvalidUncertainty.new(
|
|
282
|
+
"marker #{marker.inspect}: more than one m:box could hold the unit",
|
|
283
|
+
)
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
unit = units.first && box_to_plurimath(units.first)
|
|
287
|
+
unit.nil? || unit.is_a?(Math::Formula) ? unit : Math::Formula.new([unit])
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def uncertainty_marker_text(phantom)
|
|
292
|
+
return unless omml_class?(phantom, "CTPhant") && hidden_phantom?(phantom)
|
|
293
|
+
|
|
294
|
+
text = phantom_run_text(phantom)
|
|
295
|
+
text if Mathml::UncertaintyMarker.marker?(text)
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# The text of a phantom made only of runs, or nil. A phantom whose
|
|
299
|
+
# leading runs spell a marker but which also holds anything other than
|
|
300
|
+
# runs is a malformed marker: it raises rather than being read as
|
|
301
|
+
# ordinary content.
|
|
302
|
+
def phantom_run_text(phantom)
|
|
303
|
+
children = ordered_omml_children(first_omml_child(phantom.e))
|
|
304
|
+
runs = children.take_while { |child| omml_class?(child, "CTR") }
|
|
305
|
+
text = runs.map { |run| run_text(run) }.join
|
|
306
|
+
return text if runs.any? && runs.length == children.length
|
|
307
|
+
|
|
308
|
+
reject_mixed_phantom(text)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def reject_mixed_phantom(text)
|
|
312
|
+
return unless Mathml::UncertaintyMarker.marker?(text)
|
|
313
|
+
|
|
314
|
+
raise Errors::InvalidUncertainty.new(
|
|
315
|
+
"marker #{text.inspect}: the hidden m:phant must hold only m:r runs",
|
|
316
|
+
)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def hidden_phantom?(phantom)
|
|
320
|
+
show = first_omml_child(first_omml_child(phantom.phant_pr)&.show)
|
|
321
|
+
show && %w[0 false off].include?(show.val.to_s)
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def run_text(run)
|
|
325
|
+
ordered_omml_children(run).filter_map do |child|
|
|
326
|
+
child.content.to_s if omml_class?(child, "CTText")
|
|
327
|
+
end.join
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def omml_class?(node, name)
|
|
331
|
+
!node.nil? && !node.is_a?(String) &&
|
|
332
|
+
Lutaml::Model::Utils.base_class_name(node.class.name) == name
|
|
333
|
+
end
|
|
334
|
+
|
|
267
335
|
def word_run_properties_to_plurimath(node)
|
|
268
336
|
word_run_font(node)
|
|
269
337
|
end
|
|
@@ -10,6 +10,14 @@ module Plurimath
|
|
|
10
10
|
class Utility < Plurimath::Utility
|
|
11
11
|
extend Plurimath::Mathml::FunctionTokenResolver
|
|
12
12
|
|
|
13
|
+
# A run whose whole text is a number: digits with an optional
|
|
14
|
+
# decimal part. OMML has no <mn>/<mi> split, so the run's text
|
|
15
|
+
# decides. A mixed run such as "2x" stays text, "1,5" stays a
|
|
16
|
+
# symbol (list or decimal is ambiguous), and a signed run such as
|
|
17
|
+
# "-1" stays a symbol: the shared testsuite expects that for
|
|
18
|
+
# superscripts like sin^-1, and to_omml writes the sign as its own run.
|
|
19
|
+
NUMBER_RUN = /\A[[:digit:]]+(?:\.[[:digit:]]+)?\z/
|
|
20
|
+
|
|
13
21
|
class << self
|
|
14
22
|
def valid_class(object)
|
|
15
23
|
text = object.extract_class_name_from_text
|
|
@@ -88,7 +96,7 @@ module Plurimath
|
|
|
88
96
|
text = filter_values(text) unless text.is_a?(String)
|
|
89
97
|
return text if text.is_a?(Math::Core)
|
|
90
98
|
|
|
91
|
-
if text.
|
|
99
|
+
if text.match?(NUMBER_RUN)
|
|
92
100
|
Math::Number.new(text)
|
|
93
101
|
elsif text.match?(/[a-zA-Z]/)
|
|
94
102
|
Math::Function::Text.new(text, lang: :omml)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Plurimath
|
|
4
|
+
# Per-symbol metadata for the catalog (see Plurimath::Catalog), extended into
|
|
5
|
+
# Symbols::Symbol. Symbols are documented differently from functions: a symbol
|
|
6
|
+
# is an atomic glyph with no arguments, so it needs no hand-authored
|
|
7
|
+
# description, reference, or example — its four renderings ARE its
|
|
8
|
+
# documentation. Everything here is derived, so every concrete symbol is
|
|
9
|
+
# catalogued without per-class declarations. (Functions, by contrast, each
|
|
10
|
+
# explain themselves via the separate Plurimath::Documentation.)
|
|
11
|
+
module SymbolDocumentation
|
|
12
|
+
# Slug for the /symbols/<name>/ page and YAML filename: Alpha -> "alpha".
|
|
13
|
+
def catalog_name
|
|
14
|
+
name.split("::").last.downcase
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def catalog_type
|
|
18
|
+
:symbol
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def catalog_kind
|
|
22
|
+
:symbol
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def catalog_arity
|
|
26
|
+
nil
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# The glyph itself, wrapped in a Formula for rendering.
|
|
30
|
+
def example_formula
|
|
31
|
+
Math::Formula.new([new])
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Anonymous subclasses have no stable catalog name and are excluded.
|
|
35
|
+
# Catalogued when the symbol is a concrete glyph — i.e. not one of the
|
|
36
|
+
# abstract bases (Symbol, Paren), which exist only to be subclassed. Checked
|
|
37
|
+
# by identity rather than by rendering: cheaper across the ~1,459 symbols and
|
|
38
|
+
# independent of which formats a given glyph happens to serialize to.
|
|
39
|
+
def documented?
|
|
40
|
+
!name.nil? && ![Math::Symbols::Symbol, Math::Symbols::Paren].include?(self)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# The YAML-ready entry: the glyph's name, type, and rendering in each format.
|
|
44
|
+
# Leaner than a function entry — a symbol carries no description or reference.
|
|
45
|
+
def catalog_entry
|
|
46
|
+
limitations = if const_defined?(:CATALOG_FORMAT_LIMITATIONS, false)
|
|
47
|
+
const_get(:CATALOG_FORMAT_LIMITATIONS, false)
|
|
48
|
+
else
|
|
49
|
+
{}
|
|
50
|
+
end
|
|
51
|
+
Catalog::Entry.build(
|
|
52
|
+
name: catalog_name, type: catalog_type, kind: catalog_kind,
|
|
53
|
+
arity: catalog_arity, formula: example_formula, limitations: limitations
|
|
54
|
+
)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -56,7 +56,8 @@ module Plurimath
|
|
|
56
56
|
(str("\\") >> custom_fonts.as(:unicoded_font_class) >> str("H").as(:symbol)) |
|
|
57
57
|
(str("\\") >> str("mitBbb").as(:unicoded_font_class) >> match(/D|d|e|i|j/).as(:symbol)) |
|
|
58
58
|
(op_fonts >> match["A-Za-z"].as(:symbol)) |
|
|
59
|
-
(op_alphanumeric_fonts >> (match["A-Za-z"].as(:symbol) | match("[0-9]").as(:number)))
|
|
59
|
+
(op_alphanumeric_fonts >> (match["A-Za-z"].as(:symbol) | match("[0-9]").as(:number))) |
|
|
60
|
+
((op_fonts | op_alphanumeric_fonts) >> parsing_text)
|
|
60
61
|
end
|
|
61
62
|
|
|
62
63
|
rule(:unary_arg_functions) do
|
|
@@ -35,8 +35,11 @@ module Plurimath
|
|
|
35
35
|
rule(:root_symbols) do
|
|
36
36
|
str("⒭") | str("√") | str("\\root") | str("\\surd")
|
|
37
37
|
end
|
|
38
|
+
# The middle form takes content of several terms, e.g. ⓐ(unit \mupkg);
|
|
39
|
+
# `expression` alone stops after the first term (plurimath#493).
|
|
38
40
|
rule(:arg_function) do
|
|
39
41
|
(str("ⓐ").as(:arg) >> str("(") >> a_ascii.as(:arg_arguments).maybe >> space? >> expression.as(:first_value).maybe >> str(")")) |
|
|
42
|
+
(str("ⓐ").as(:arg) >> str("(") >> a_ascii.as(:arg_arguments) >> space? >> masked_recursive_value.as(:first_value) >> space? >> str(")")) |
|
|
40
43
|
(str("ⓐ").as(:arg) >> a_ascii.as(:arg_arguments).maybe >> space? >> expression.as(:first_value).maybe)
|
|
41
44
|
end
|
|
42
45
|
|
|
@@ -233,6 +233,13 @@ module Plurimath
|
|
|
233
233
|
Utility.symbols_class((unicode || symbol), lang: :unicodemath)
|
|
234
234
|
end
|
|
235
235
|
|
|
236
|
+
# \mup"g" is how a font over text is written (e.g. a unit read from
|
|
237
|
+
# OMML, plurimath#493).
|
|
238
|
+
rule(font_class: simple(:fonts),
|
|
239
|
+
text: simple(:text)) do
|
|
240
|
+
Utility::FONT_STYLES[fonts.to_sym].new(Math::Function::Text.new(text))
|
|
241
|
+
end
|
|
242
|
+
|
|
236
243
|
rule(font_class: simple(:fonts),
|
|
237
244
|
symbol: simple(:symbol)) do
|
|
238
245
|
Utility::FONT_STYLES[fonts.to_sym].new(
|
|
@@ -530,6 +537,18 @@ module Plurimath
|
|
|
530
537
|
[Utility.symbols_class(symbol, lang: :unicodemath), exp]
|
|
531
538
|
end
|
|
532
539
|
|
|
540
|
+
rule(combined_symbols: simple(:combined_symbols),
|
|
541
|
+
expr: simple(:expr)) do
|
|
542
|
+
symbol = Constants::COMBINING_SYMBOLS[combined_symbols.to_sym] || combined_symbols
|
|
543
|
+
[Utility.symbols_class(symbol, lang: :unicodemath), expr]
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
rule(combined_symbols: simple(:combined_symbols),
|
|
547
|
+
expr: sequence(:expr)) do
|
|
548
|
+
symbol = Constants::COMBINING_SYMBOLS[combined_symbols.to_sym] || combined_symbols
|
|
549
|
+
[Utility.symbols_class(symbol, lang: :unicodemath)] + expr
|
|
550
|
+
end
|
|
551
|
+
|
|
533
552
|
rule(operator: simple(:operator),
|
|
534
553
|
sub_script: simple(:sub_script)) do
|
|
535
554
|
[Utility.symbols_class(operator, lang: :unicodemath), sub_script]
|
|
@@ -960,7 +979,7 @@ module Plurimath
|
|
|
960
979
|
rule(intent: simple(:intent),
|
|
961
980
|
intent_expr: simple(:expr)) do
|
|
962
981
|
intent_string = expr.parameter_two.shift
|
|
963
|
-
|
|
982
|
+
Utility.intent_or_uncertainty(
|
|
964
983
|
Utility.filter_values(expr.parameter_two),
|
|
965
984
|
intent_string,
|
|
966
985
|
)
|
|
@@ -2218,12 +2237,30 @@ module Plurimath
|
|
|
2218
2237
|
)
|
|
2219
2238
|
end
|
|
2220
2239
|
|
|
2240
|
+
# Any other ⓐ shape has no Arg reading; fail here rather than leave
|
|
2241
|
+
# the raw parse tree inside the Formula. Parslet tries later rules
|
|
2242
|
+
# first, so these catch-alls must stay above the Arg rules below.
|
|
2243
|
+
rule(arg: simple(:arg)) { Utility.unsupported_arg! }
|
|
2244
|
+
rule(arg: simple(:arg), arg_arguments: simple(:args)) { Utility.unsupported_arg! }
|
|
2245
|
+
rule(arg: simple(:arg), first_value: subtree(:first_value)) { Utility.unsupported_arg! }
|
|
2246
|
+
rule(arg: simple(:arg),
|
|
2247
|
+
arg_arguments: simple(:args),
|
|
2248
|
+
first_value: subtree(:first_value)) { Utility.unsupported_arg! }
|
|
2249
|
+
|
|
2221
2250
|
rule(arg: simple(:arg),
|
|
2222
2251
|
arg_arguments: simple(:args),
|
|
2223
2252
|
first_value: simple(:first_value)) do
|
|
2224
2253
|
Math::Function::Arg.new(first_value, args)
|
|
2225
2254
|
end
|
|
2226
2255
|
|
|
2256
|
+
# ⓐ(unit \mupkg) reads its content as several nodes; keep them together
|
|
2257
|
+
# so the argument (e.g. an uncertainty unit, plurimath#493) is not lost.
|
|
2258
|
+
rule(arg: simple(:arg),
|
|
2259
|
+
arg_arguments: simple(:args),
|
|
2260
|
+
first_value: sequence(:first_value)) do
|
|
2261
|
+
Math::Function::Arg.new(Math::Formula.new(first_value), args)
|
|
2262
|
+
end
|
|
2263
|
+
|
|
2227
2264
|
rule(whole: simple(:whole),
|
|
2228
2265
|
decimal: simple(:decimal),
|
|
2229
2266
|
fractional: simple(:fractional)) do
|
|
@@ -3585,6 +3622,30 @@ module Plurimath
|
|
|
3585
3622
|
)
|
|
3586
3623
|
end
|
|
3587
3624
|
|
|
3625
|
+
rule(open_paren: simple(:open_paren),
|
|
3626
|
+
text: simple(:text),
|
|
3627
|
+
operand: sequence(:operand),
|
|
3628
|
+
exp: simple(:exp),
|
|
3629
|
+
close_paren: simple(:close_paren)) do
|
|
3630
|
+
Math::Function::Fenced.new(
|
|
3631
|
+
open_paren.is_a?(Slice) ? Utility.symbols_class(open_paren, lang: :unicodemath) : open_paren,
|
|
3632
|
+
[Math::Function::Text.new(text)] + operand + [exp],
|
|
3633
|
+
close_paren.is_a?(Slice) ? Utility.symbols_class(close_paren, lang: :unicodemath) : close_paren,
|
|
3634
|
+
)
|
|
3635
|
+
end
|
|
3636
|
+
|
|
3637
|
+
rule(open_paren: simple(:open_paren),
|
|
3638
|
+
text: simple(:text),
|
|
3639
|
+
operand: sequence(:operand),
|
|
3640
|
+
exp: sequence(:exp),
|
|
3641
|
+
close_paren: simple(:close_paren)) do
|
|
3642
|
+
Math::Function::Fenced.new(
|
|
3643
|
+
open_paren.is_a?(Slice) ? Utility.symbols_class(open_paren, lang: :unicodemath) : open_paren,
|
|
3644
|
+
[Math::Function::Text.new(text)] + operand + exp,
|
|
3645
|
+
close_paren.is_a?(Slice) ? Utility.symbols_class(close_paren, lang: :unicodemath) : close_paren,
|
|
3646
|
+
)
|
|
3647
|
+
end
|
|
3648
|
+
|
|
3588
3649
|
rule(nary_class: simple(:nary_class),
|
|
3589
3650
|
mask: simple(:mask),
|
|
3590
3651
|
sub: simple(:sub),
|
|
@@ -3871,7 +3932,7 @@ module Plurimath
|
|
|
3871
3932
|
intent_arguments: simple(:args),
|
|
3872
3933
|
first_value: simple(:value),
|
|
3873
3934
|
close_paren: simple(:close_paren)) do
|
|
3874
|
-
|
|
3935
|
+
Utility.intent_or_uncertainty(value, args)
|
|
3875
3936
|
end
|
|
3876
3937
|
|
|
3877
3938
|
rule(intent: simple(:intent),
|
|
@@ -3879,7 +3940,7 @@ module Plurimath
|
|
|
3879
3940
|
intent_arguments: simple(:args),
|
|
3880
3941
|
first_value: sequence(:value),
|
|
3881
3942
|
close_paren: simple(:close_paren)) do
|
|
3882
|
-
|
|
3943
|
+
Utility.intent_or_uncertainty(Utility.filter_values(value), args)
|
|
3883
3944
|
end
|
|
3884
3945
|
|
|
3885
3946
|
rule(paren_open_prefix: simple(:open_paren),
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../mathml/uncertainty_marker"
|
|
4
|
+
|
|
3
5
|
module Plurimath
|
|
4
6
|
class UnicodeMath
|
|
5
7
|
# UnicodeMath-specific helpers extracted from Plurimath::Utility (code-quality
|
|
@@ -7,6 +9,42 @@ module Plurimath
|
|
|
7
9
|
# UnicodeMath files keep resolving here and inherit the generic helpers.
|
|
8
10
|
class Utility < Plurimath::Utility
|
|
9
11
|
class << self
|
|
12
|
+
# ⓘ("marker" content) is a measurement uncertainty (plurimath#493)
|
|
13
|
+
# when the marker uses one of its concept names; any other intent
|
|
14
|
+
# stays a Function::Intent. The marker is authoritative, so only the
|
|
15
|
+
# ⓐ(unit ...) argument of the content is read.
|
|
16
|
+
def intent_or_uncertainty(content, intent)
|
|
17
|
+
marker = intent.is_a?(Math::Function::Text) ? intent.parameter_one : intent.to_s
|
|
18
|
+
unless Mathml::UncertaintyMarker.marker?(marker)
|
|
19
|
+
return Math::Function::Intent.new(content, intent)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
Mathml::UncertaintyMarker.build(marker) do
|
|
23
|
+
uncertainty_unit(content, marker)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def uncertainty_unit(content, marker)
|
|
28
|
+
values = content.is_a?(Math::Formula) ? content.value : Array(content)
|
|
29
|
+
units = values.select do |value|
|
|
30
|
+
value.is_a?(Math::Function::Arg) &&
|
|
31
|
+
value.parameter_two.is_a?(Math::Symbols::Symbol) &&
|
|
32
|
+
value.parameter_two.value == "unit"
|
|
33
|
+
end
|
|
34
|
+
if units.length > 1
|
|
35
|
+
raise Errors::InvalidUncertainty.new(
|
|
36
|
+
"marker #{marker.inspect}: more than one ⓐ(unit ...) argument",
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
unit = units.first&.parameter_one
|
|
41
|
+
unit.nil? || unit.is_a?(Math::Formula) ? unit : Math::Formula.new([unit])
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def unsupported_arg!
|
|
45
|
+
raise ArgumentError, "ⓐ needs a name and content, as in ⓐ(name content)"
|
|
46
|
+
end
|
|
47
|
+
|
|
10
48
|
def unicode_accents(accents, lang: :unicodemath)
|
|
11
49
|
if accents.is_a?(Math::Function::BinaryFunction)
|
|
12
50
|
accents
|
data/lib/plurimath/version.rb
CHANGED
data/lib/plurimath.rb
CHANGED
|
@@ -8,9 +8,12 @@ require "plurimath/xml_engine"
|
|
|
8
8
|
module Plurimath
|
|
9
9
|
autoload :Asciimath, "plurimath/asciimath"
|
|
10
10
|
autoload :BaseNumberPrefix, "plurimath/base_number_prefix"
|
|
11
|
+
autoload :Catalog, "plurimath/catalog"
|
|
11
12
|
autoload :Cli, "plurimath/cli" unless RUBY_ENGINE == "opal"
|
|
12
13
|
autoload :Configuration, "plurimath/configuration"
|
|
13
14
|
autoload :Deprecation, "plurimath/deprecation"
|
|
15
|
+
autoload :Documentation, "plurimath/documentation"
|
|
16
|
+
autoload :SymbolDocumentation, "plurimath/symbol_documentation"
|
|
14
17
|
autoload :Error, "plurimath/errors/error"
|
|
15
18
|
autoload :ConfigurationError, "plurimath/errors/configuration_error"
|
|
16
19
|
autoload :DeprecationError, "plurimath/errors/deprecation_error"
|
data/plurimath.gemspec
CHANGED
|
@@ -27,9 +27,11 @@ Gem::Specification.new do |spec|
|
|
|
27
27
|
spec.bindir = "exe"
|
|
28
28
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
29
29
|
spec.require_paths = ["lib"]
|
|
30
|
+
# amath comes from the Gemfile (GitHub) until it is published; then:
|
|
31
|
+
# spec.add_dependency "amath", "~> 0.1"
|
|
30
32
|
spec.add_dependency "bigdecimal"
|
|
31
33
|
spec.add_dependency "htmlentities"
|
|
32
|
-
spec.add_dependency "lutaml-model", "~> 0.8.
|
|
34
|
+
spec.add_dependency "lutaml-model", "~> 0.8.155"
|
|
33
35
|
spec.add_dependency "mml", "~> 2.4.2"
|
|
34
36
|
spec.add_dependency "omml", "~> 0.2.5"
|
|
35
37
|
spec.add_dependency "ostruct"
|