unitsml 0.4.7 → 0.6.0

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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +8 -0
  3. data/.github/workflows/release.yml +7 -1
  4. data/.rubocop.yml +18 -0
  5. data/.rubocop_todo.yml +498 -0
  6. data/Gemfile +16 -11
  7. data/Rakefile +5 -3
  8. data/bin/console +4 -3
  9. data/docs/README.adoc +106 -4
  10. data/lib/unitsml/dimension.rb +49 -35
  11. data/lib/unitsml/errors/base_error.rb +8 -0
  12. data/lib/unitsml/errors/plurimath_load_error.rb +1 -1
  13. data/lib/unitsml/errors.rb +8 -0
  14. data/lib/unitsml/extender.rb +21 -16
  15. data/lib/unitsml/fenced.rb +97 -0
  16. data/lib/unitsml/fenced_numeric.rb +13 -0
  17. data/lib/unitsml/formula.rb +46 -33
  18. data/lib/unitsml/intermediate_exp_rules.rb +76 -0
  19. data/lib/unitsml/model/dimension.rb +4 -14
  20. data/lib/unitsml/model/dimension_quantities/quantity.rb +2 -0
  21. data/lib/unitsml/model/dimension_quantities.rb +17 -0
  22. data/lib/unitsml/model/prefix.rb +4 -8
  23. data/lib/unitsml/model/prefixes/name.rb +5 -4
  24. data/lib/unitsml/model/prefixes/symbol.rb +3 -2
  25. data/lib/unitsml/model/prefixes.rb +10 -0
  26. data/lib/unitsml/model/quantities/name.rb +4 -3
  27. data/lib/unitsml/model/quantities.rb +9 -0
  28. data/lib/unitsml/model/quantity.rb +5 -7
  29. data/lib/unitsml/model/unit.rb +4 -9
  30. data/lib/unitsml/model/units/enumerated_root_unit.rb +1 -0
  31. data/lib/unitsml/model/units/name.rb +4 -3
  32. data/lib/unitsml/model/units/root_units.rb +3 -2
  33. data/lib/unitsml/model/units/symbol.rb +2 -1
  34. data/lib/unitsml/model/units/system.rb +4 -3
  35. data/lib/unitsml/model/units.rb +13 -0
  36. data/lib/unitsml/model.rb +15 -0
  37. data/lib/unitsml/namespace.rb +8 -0
  38. data/lib/unitsml/number.rb +79 -0
  39. data/lib/unitsml/parse.rb +30 -38
  40. data/lib/unitsml/parser.rb +27 -13
  41. data/lib/unitsml/prefix.rb +17 -17
  42. data/lib/unitsml/sqrt.rb +3 -3
  43. data/lib/unitsml/transform.rb +143 -50
  44. data/lib/unitsml/unit.rb +67 -37
  45. data/lib/unitsml/unitsdb/dimension.rb +14 -20
  46. data/lib/unitsml/unitsdb/dimension_quantity.rb +2 -6
  47. data/lib/unitsml/unitsdb/dimensions.rb +3 -9
  48. data/lib/unitsml/unitsdb/prefix_reference.rb +23 -0
  49. data/lib/unitsml/unitsdb/prefixes.rb +17 -5
  50. data/lib/unitsml/unitsdb/quantities.rb +4 -4
  51. data/lib/unitsml/unitsdb/unit.rb +21 -0
  52. data/lib/unitsml/unitsdb/units.rb +19 -18
  53. data/lib/unitsml/unitsdb.rb +14 -5
  54. data/lib/unitsml/utility.rb +133 -103
  55. data/lib/unitsml/version.rb +3 -1
  56. data/lib/unitsml.rb +71 -35
  57. data/unitsdb/Gemfile +6 -0
  58. data/unitsdb/LICENSE.md +53 -0
  59. data/unitsdb/README.adoc +1253 -0
  60. data/unitsdb/RELEASE-NOTES.adoc +269 -0
  61. data/unitsdb/dimensions.yaml +1607 -602
  62. data/unitsdb/prefixes.yaml +842 -301
  63. data/unitsdb/quantities.yaml +3706 -2458
  64. data/unitsdb/scales.yaml +97 -0
  65. data/unitsdb/schemas/README.md +159 -0
  66. data/unitsdb/schemas/dimensions-schema.yaml +153 -0
  67. data/unitsdb/schemas/prefixes-schema.yaml +155 -0
  68. data/unitsdb/schemas/quantities-schema.yaml +117 -0
  69. data/unitsdb/schemas/scales-schema.yaml +106 -0
  70. data/unitsdb/schemas/unit_systems-schema.yaml +116 -0
  71. data/unitsdb/schemas/units-schema.yaml +215 -0
  72. data/unitsdb/spec/units_spec.rb +13 -10
  73. data/unitsdb/unit_systems.yaml +77 -15
  74. data/unitsdb/units.yaml +13517 -9974
  75. data/unitsdb/validate_schemas.rb +203 -0
  76. data/unitsml.gemspec +4 -1
  77. metadata +47 -7
  78. data/lib/unitsml/error.rb +0 -8
  79. data/unitsdb/docs/README.adoc +0 -12
  80. data/unitsdb/docs/navigation.adoc +0 -7
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unitsml
4
+ module IntermediateExpRules
5
+ include Parslet
6
+
7
+ # Rules for slashed number
8
+ rule(:slashed_number_int_exp) do
9
+ slashed_number | (opening_paren >> slashed_number_named_int_exp.as(:int_exp) >> closing_paren)
10
+ end
11
+ rule(:slashed_number_named_int_exp) do
12
+ (opening_paren.as(:open_paren) >> slashed_number_int_exp >> closing_paren.as(:close_paren)) |
13
+ slashed_number_int_exp
14
+ end
15
+
16
+ # Rules for prefixes_units
17
+ rule(:wrapper_prefixes_units_value) { int_exp_prefixes_units | prefixes_units_int_exp }
18
+
19
+ rule(:extended_prefixed_units) { extender >> spaces? >> prefixes_units_int_exp.as(:sequence) }
20
+
21
+ rule(:int_exp_prefixes_units) do
22
+ opening_paren >> spaces? >> named_int_exp_prefixes_units.as(:int_exp) >> spaces? >> closing_paren
23
+ end
24
+
25
+ rule(:implicit_extended) do
26
+ prefixes_units.as(:first_set) >> spaces.as(:extender) >> prefixes_units.as(:second_set) |
27
+ int_exp_prefixes_units.as(:first_int_exp_set) >> spaces? >> int_exp_prefixes_units.as(:second_int_exp_set) |
28
+ prefixes_units.as(:first_set) >> spaces? >> int_exp_prefixes_units.as(:second_int_exp_set) |
29
+ int_exp_prefixes_units.as(:first_int_exp_set) >> spaces? >> prefixes_units.as(:second_set)
30
+ end
31
+
32
+ rule(:prefixes_units_int_exp) do
33
+ implicit_extended.as(:implicit_extended) >> spaces? >> prefixes_units_int_exp.as(:sequence).maybe |
34
+ implicit_extended.as(:implicit_extended) >> spaces? >> extender >> spaces? >> prefixes_units_int_exp.as(:sequence).maybe |
35
+ int_exp_prefixes_units >> spaces? >> extender >> spaces? >> prefixes_units_int_exp.as(:sequence).maybe |
36
+ prefixes_units >> spaces? >> extender >> spaces? >> prefixes_units_int_exp.as(:sequence).maybe |
37
+ int_exp_prefixes_units >> prefixes_units_int_exp.as(:sequence).maybe |
38
+ prefixes_units >> prefixes_units_int_exp.as(:sequence).maybe
39
+ end
40
+
41
+ rule(:prefixes_units_named_int_exp) do
42
+ opening_paren.as(:open_paren) >> spaces? >> wrapper_prefixes_units_value.as(:int_exp) >> spaces? >> closing_paren.as(:close_paren)
43
+ end
44
+
45
+ rule(:named_int_exp_prefixes_units) do
46
+ prefixes_units_named_int_exp.as(:int_exp) >> (prefixes_units_int_exp | extended_prefixed_units).maybe |
47
+ prefixes_units_int_exp
48
+ end
49
+
50
+ # Rules for dimension_rules
51
+ rule(:dimension_rules_int_exp) do
52
+ dimension_rules.as(:first_set) >> spaces.as(:extender) >> dimension_rules.as(:second_set) >> dimension_rules_int_exp.maybe |
53
+ dimension_rules.as(:first_set) >> spaces? >> int_exp_dimension_rules.as(:second_int_exp_set) >> dimension_rules_int_exp.maybe |
54
+ int_exp_dimension_rules.as(:first_int_exp_set) >> spaces? >> dimension_rules.as(:second_set) >> dimension_rules_int_exp.maybe |
55
+ int_exp_dimension_rules.as(:first_int_exp_set) >> spaces? >> int_exp_dimension_rules.as(:second_int_exp_set) >> dimension_rules_int_exp.maybe |
56
+ int_exp_dimension_rules |
57
+ dimension_rules
58
+ end
59
+
60
+ rule(:int_exp_dimension_rules) do
61
+ opening_paren >> dimension_rules_named_exp.as(:int_exp) >> closing_paren >> extended_dimension_rules.maybe
62
+ end
63
+
64
+ rule(:extended_dimension_rules) { spaces? >> extender >> spaces? >> dimension_rules_int_exp.as(:sequence) }
65
+ rule(:dimension_rules_named_exp) do
66
+ ((opening_paren.as(:open_paren) >> dimension_rules_int_exp.as(:int_exp) >> closing_paren.as(:close_paren)).as(:int_exp) >> spaces? >> (dimension_rules_int_exp | extended_dimension_rules).as(:sequence).maybe) |
67
+ dimension_rules_int_exp
68
+ end
69
+
70
+ # Rules for dimensions
71
+ rule(:sqrt_dimensions) { sqrt >> opening_paren >> dimension_rules_int_exp.as(:sqrt) >> closing_paren }
72
+
73
+ # Rules for sequence
74
+ rule(:sqrt_sequence) { sqrt >> opening_paren >> prefixes_units_int_exp.as(:sqrt) >> closing_paren }
75
+ end
76
+ end
@@ -1,19 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "unitsml/model/dimension_quantities/quantity"
4
- require "unitsml/model/dimension_quantities/length"
5
- require "unitsml/model/dimension_quantities/mass"
6
- require "unitsml/model/dimension_quantities/time"
7
- require "unitsml/model/dimension_quantities/electric_current"
8
- require "unitsml/model/dimension_quantities/thermodynamic_temperature"
9
- require "unitsml/model/dimension_quantities/amount_of_substance"
10
- require "unitsml/model/dimension_quantities/luminous_intensity"
11
- require "unitsml/model/dimension_quantities/plane_angle"
12
-
13
3
  module Unitsml
14
4
  module Model
15
5
  class Dimension < Lutaml::Model::Serializable
16
- attribute :id, :string
6
+ attribute :id, :xml_id
17
7
  attribute :length, DimensionQuantities::Length
18
8
  attribute :mass, DimensionQuantities::Mass
19
9
  attribute :time, DimensionQuantities::Time
@@ -24,10 +14,10 @@ module Unitsml
24
14
  attribute :plane_angle, DimensionQuantities::PlaneAngle
25
15
 
26
16
  xml do
27
- root "Dimension"
28
- namespace Unitsml::UNITSML_NS
17
+ namespace ::Unitsml::Namespace
18
+ element 'Dimension'
29
19
 
30
- map_attribute :id, to: :id, namespace: nil, prefix: "xml"
20
+ map_attribute :id, to: :id
31
21
  map_element :Length, to: :length
32
22
  map_element :Mass, to: :mass
33
23
  map_element :Time, to: :time
@@ -8,6 +8,8 @@ module Unitsml
8
8
  attribute :power_numerator, :string
9
9
 
10
10
  xml do
11
+ namespace ::Unitsml::Namespace
12
+
11
13
  map_attribute :symbol, to: :symbol
12
14
  map_attribute :powerNumerator, to: :power_numerator
13
15
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unitsml
4
+ module Model
5
+ module DimensionQuantities
6
+ autoload :AmountOfSubstance, "#{__dir__}/dimension_quantities/amount_of_substance"
7
+ autoload :ElectricCurrent, "#{__dir__}/dimension_quantities/electric_current"
8
+ autoload :Length, "#{__dir__}/dimension_quantities/length"
9
+ autoload :LuminousIntensity, "#{__dir__}/dimension_quantities/luminous_intensity"
10
+ autoload :Mass, "#{__dir__}/dimension_quantities/mass"
11
+ autoload :PlaneAngle, "#{__dir__}/dimension_quantities/plane_angle"
12
+ autoload :Quantity, "#{__dir__}/dimension_quantities/quantity"
13
+ autoload :ThermodynamicTemperature, "#{__dir__}/dimension_quantities/thermodynamic_temperature"
14
+ autoload :Time, "#{__dir__}/dimension_quantities/time"
15
+ end
16
+ end
17
+ end
@@ -1,25 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "unitsml/model/prefixes/name"
4
- require "unitsml/model/prefixes/symbol"
5
-
6
-
7
3
  module Unitsml
8
4
  module Model
9
5
  class Prefix < Lutaml::Model::Serializable
10
6
  attribute :name, Prefixes::Name
11
- attribute :id, :string
7
+ attribute :id, :xml_id
12
8
  attribute :symbol, Prefixes::Symbol, collection: true
13
9
  attribute :prefix_base, :string
14
10
  attribute :prefix_power, :string
15
11
 
16
12
  xml do
17
- root "Prefix"
18
- namespace Unitsml::UNITSML_NS
13
+ namespace ::Unitsml::Namespace
14
+ element 'Prefix'
19
15
 
20
16
  map_attribute :prefixBase, to: :prefix_base
21
17
  map_attribute :prefixPower, to: :prefix_power
22
- map_attribute :id, to: :id, namespace: nil, prefix: "xml"
18
+ map_attribute :id, to: :id
23
19
  map_element :PrefixName, to: :name
24
20
  map_element :PrefixSymbol, to: :symbol
25
21
  end
@@ -2,15 +2,16 @@
2
2
 
3
3
  module Unitsml
4
4
  module Model
5
- class Prefixes
5
+ module Prefixes
6
6
  class Name < Lutaml::Model::Serializable
7
- attribute :lang, :string, default: -> { "en" }
7
+ attribute :lang, :xml_lang, default: -> { 'en' }
8
8
  attribute :content, :string
9
9
 
10
10
  xml do
11
- root "PrefixName"
11
+ element 'PrefixName'
12
+ namespace ::Unitsml::Namespace
12
13
 
13
- map_attribute :lang, to: :lang, namespace: nil, prefix: "xml", render_default: true
14
+ map_attribute :lang, to: :lang, render_default: true
14
15
  map_content to: :content
15
16
  end
16
17
  end
@@ -2,13 +2,14 @@
2
2
 
3
3
  module Unitsml
4
4
  module Model
5
- class Prefixes
5
+ module Prefixes
6
6
  class Symbol < Lutaml::Model::Serializable
7
7
  attribute :type, :string
8
8
  attribute :content, :string
9
9
 
10
10
  xml do
11
- root "PrefixSymbol"
11
+ element 'PrefixSymbol'
12
+ namespace ::Unitsml::Namespace
12
13
 
13
14
  map_attribute :type, to: :type
14
15
  map_content to: :content
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unitsml
4
+ module Model
5
+ module Prefixes
6
+ autoload :Name, "#{__dir__}/prefixes/name"
7
+ autoload :Symbol, "#{__dir__}/prefixes/symbol"
8
+ end
9
+ end
10
+ end
@@ -4,13 +4,14 @@ module Unitsml
4
4
  module Model
5
5
  module Quantities
6
6
  class Name < Lutaml::Model::Serializable
7
- attribute :lang, :string, default: -> { "en-US" }
7
+ attribute :lang, :xml_lang, default: -> { 'en' }
8
8
  attribute :content, :string
9
9
 
10
10
  xml do
11
- root "QuantityName"
11
+ element 'QuantityName'
12
+ namespace ::Unitsml::Namespace
12
13
 
13
- map_attribute :lang, to: :lang, namespace: nil, prefix: "xml", render_default: true
14
+ map_attribute :lang, to: :lang, render_default: true
14
15
  map_content to: :content
15
16
  end
16
17
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unitsml
4
+ module Model
5
+ module Quantities
6
+ autoload :Name, "#{__dir__}/quantities/name"
7
+ end
8
+ end
9
+ end
@@ -1,20 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "unitsml/model/quantities/name"
4
-
5
3
  module Unitsml
6
4
  module Model
7
5
  class Quantity < Lutaml::Model::Serializable
8
- attribute :id, :string
6
+ attribute :id, :xml_id
9
7
  attribute :name, Quantities::Name, collection: true
10
- attribute :quantity_type, :string, default: -> { "base" }
8
+ attribute :quantity_type, :string, default: -> { 'base' }
11
9
  attribute :dimension_url, :string
12
10
 
13
11
  xml do
14
- root "Quantity"
15
- namespace Unitsml::UNITSML_NS
12
+ namespace ::Unitsml::Namespace
13
+ element 'Quantity'
16
14
 
17
- map_attribute :id, to: :id, namespace: nil, prefix: "xml"
15
+ map_attribute :id, to: :id
18
16
  map_attribute :quantityType, to: :quantity_type, render_default: true
19
17
  map_attribute :dimensionURL, to: :dimension_url
20
18
  map_element :QuantityName, to: :name
@@ -1,14 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "unitsml/model/units/name"
4
- require "unitsml/model/units/symbol"
5
- require "unitsml/model/units/system"
6
- require "unitsml/model/units/root_units"
7
-
8
3
  module Unitsml
9
4
  module Model
10
5
  class Unit < Lutaml::Model::Serializable
11
- attribute :id, :string
6
+ attribute :id, :xml_id
12
7
  attribute :name, Units::Name
13
8
  attribute :dimension_url, :string
14
9
  attribute :symbol, Units::Symbol, collection: true
@@ -16,11 +11,11 @@ module Unitsml
16
11
  attribute :root_units, Units::RootUnits
17
12
 
18
13
  xml do
19
- root "Unit"
20
- namespace Unitsml::UNITSML_NS
14
+ namespace ::Unitsml::Namespace
15
+ element 'Unit'
21
16
 
22
17
  map_attribute :dimensionURL, to: :dimension_url
23
- map_attribute :id, to: :id, namespace: nil, prefix: "xml"
18
+ map_attribute :id, to: :id
24
19
  map_element :UnitSystem, to: :system
25
20
  map_element :UnitName, to: :name
26
21
  map_element :UnitSymbol, to: :symbol
@@ -9,6 +9,7 @@ module Unitsml
9
9
  attribute :power_numerator, :string
10
10
 
11
11
  xml do
12
+ namespace ::Unitsml::Namespace
12
13
  map_attribute :unit, to: :unit
13
14
  map_attribute :prefix, to: :prefix
14
15
  map_attribute :powerNumerator, to: :power_numerator
@@ -5,13 +5,14 @@ module Unitsml
5
5
  module Units
6
6
  class Name < Lutaml::Model::Serializable
7
7
  attribute :name, :string
8
- attribute :lang, :string, default: -> { "en" }
8
+ attribute :lang, :xml_lang, default: -> { 'en' }
9
9
 
10
10
  xml do
11
- root "UnitName"
11
+ element 'UnitName'
12
+ namespace ::Unitsml::Namespace
12
13
 
13
14
  map_content to: :name
14
- map_attribute :lang, to: :lang, namespace: nil, prefix: "xml", render_default: true
15
+ map_attribute :lang, to: :lang, render_default: true
15
16
  end
16
17
  end
17
18
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "unitsml/model/units/enumerated_root_unit"
4
-
5
3
  module Unitsml
6
4
  module Model
7
5
  module Units
@@ -9,6 +7,9 @@ module Unitsml
9
7
  attribute :enumerated_root_unit, EnumeratedRootUnit, collection: true
10
8
 
11
9
  xml do
10
+ element 'RootUnits'
11
+ namespace ::Unitsml::Namespace
12
+
12
13
  map_element :EnumeratedRootUnit, to: :enumerated_root_unit
13
14
  end
14
15
  end
@@ -8,7 +8,8 @@ module Unitsml
8
8
  attribute :content, :string
9
9
 
10
10
  xml do
11
- root "UnitSymbol"
11
+ element 'UnitSymbol'
12
+ namespace ::Unitsml::Namespace
12
13
 
13
14
  map_attribute :type, to: :type
14
15
  map_content to: :content, with: { from: :content_from_xml, to: :content_to_xml }
@@ -6,14 +6,15 @@ module Unitsml
6
6
  class System < Lutaml::Model::Serializable
7
7
  attribute :name, :string
8
8
  attribute :type, :string
9
- attribute :lang, :string, default: -> { "en-US" }
9
+ attribute :lang, :xml_lang, default: -> { 'en' }
10
10
 
11
11
  xml do
12
- root "UnitSystem"
12
+ element 'UnitSystem'
13
+ namespace ::Unitsml::Namespace
13
14
 
14
15
  map_attribute :name, to: :name
15
16
  map_attribute :type, to: :type
16
- map_attribute :lang, to: :lang, namespace: nil, prefix: "xml", render_default: true
17
+ map_attribute :lang, to: :lang, render_default: true
17
18
  end
18
19
  end
19
20
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unitsml
4
+ module Model
5
+ module Units
6
+ autoload :EnumeratedRootUnit, 'unitsml/model/units/enumerated_root_unit'
7
+ autoload :Name, 'unitsml/model/units/name'
8
+ autoload :RootUnits, 'unitsml/model/units/root_units'
9
+ autoload :Symbol, 'unitsml/model/units/symbol'
10
+ autoload :System, 'unitsml/model/units/system'
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unitsml
4
+ module Model
5
+ autoload :Dimension, "#{__dir__}/model/dimension"
6
+ autoload :DimensionQuantities, "#{__dir__}/model/dimension_quantities"
7
+ autoload :Namespace, "#{__dir__}/model/namespace"
8
+ autoload :Prefix, "#{__dir__}/model/prefix"
9
+ autoload :Prefixes, "#{__dir__}/model/prefixes"
10
+ autoload :Quantities, "#{__dir__}/model/quantities"
11
+ autoload :Quantity, "#{__dir__}/model/quantity"
12
+ autoload :Unit, "#{__dir__}/model/unit"
13
+ autoload :Units, "#{__dir__}/model/units"
14
+ end
15
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unitsml
4
+ class Namespace < Lutaml::Xml::Namespace
5
+ uri 'https://schema.unitsml.org/unitsml/1.0'
6
+ prefix_default 'unitsml'
7
+ end
8
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unitsml
4
+ class Number
5
+ include FencedNumeric
6
+
7
+ attr_accessor :value
8
+ alias raw_value value
9
+
10
+ def initialize(value)
11
+ @value = value
12
+ end
13
+
14
+ def ==(other)
15
+ self.class == other.class &&
16
+ value == other&.value
17
+ end
18
+
19
+ def to_mathml(_options)
20
+ matched_value = value&.match(/-?(.+)/)
21
+ mn_value = matched_value ? matched_value[1] : value
22
+ mn_tag = ::Mml::V4::Mn.new(value: mn_value)
23
+ value.start_with?('-') ? mrow_hash(mn_tag) : mn_hash(mn_tag)
24
+ end
25
+
26
+ def to_html(_options)
27
+ value.sub('-', '&#x2212;')
28
+ end
29
+
30
+ def to_latex(_options)
31
+ value
32
+ end
33
+
34
+ def to_asciimath(_options)
35
+ value
36
+ end
37
+
38
+ def to_unicode(_options)
39
+ value
40
+ end
41
+
42
+ def negative?
43
+ value.start_with?('-')
44
+ end
45
+
46
+ def update_negative_sign
47
+ self.value = if negative?
48
+ value.delete_prefix('-')
49
+ else
50
+ ['-', value].join
51
+ end
52
+ end
53
+
54
+ def float_to_display
55
+ return '' if value.nil?
56
+
57
+ value.to_f.round(1).to_s.sub(/\.0$/, '')
58
+ end
59
+
60
+ private
61
+
62
+ def mrow_hash(mn_tag)
63
+ {
64
+ method_name: :mrow,
65
+ value: ::Mml::V4::Mrow.new(
66
+ mo_value: [::Mml::V4::Mo.new(value: '&#x2212;')],
67
+ mn_value: [mn_tag]
68
+ )
69
+ }
70
+ end
71
+
72
+ def mn_hash(mn_tag)
73
+ {
74
+ method_name: :mn,
75
+ value: mn_tag
76
+ }
77
+ end
78
+ end
79
+ end
data/lib/unitsml/parse.rb CHANGED
@@ -1,55 +1,59 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "parslet"
4
- require "unitsml/unitsdb"
3
+ require 'parslet'
4
+
5
5
  module Unitsml
6
6
  class Parse < Parslet::Parser
7
- rule(:power) { str("^") >> intermediate_exp(slashed_number) }
8
- rule(:hyphen) { str("-") }
7
+ include IntermediateExpRules
8
+
9
+ rule(:sqrt) { str('sqrt') }
10
+ rule(:power) { str('^') >> slashed_number_int_exp.as(:power_numerator) }
11
+ rule(:hyphen) { str('-') }
9
12
  rule(:number) { hyphen.maybe >> match(/[0-9]/).repeat(1) }
13
+ rule(:spaces) { match(/\s/).repeat(1) }
14
+ rule(:spaces?) { spaces.maybe }
10
15
 
11
- rule(:extender) { (forward_slashes | str("*")).as(:extender) }
16
+ rule(:extender) { (forward_slashes | str('*')).as(:extender) }
12
17
  rule(:sequence) { single_letter_prefixes >> units | double_letter_prefixes >> units | units }
13
18
 
19
+ rule(:opening_paren) { str('(') }
20
+ rule(:closing_paren) { str(')') }
14
21
  rule(:unit_and_power) { units >> power.maybe }
15
22
  rule(:slashed_number) { (number >> (forward_slashes >> number).maybe).as(:integer) }
16
- rule(:forward_slashes) { str("//") | str("/") }
23
+ rule(:forward_slashes) { str('//') | str('/') }
24
+ rule(:dimension_rules) { (sqrt_dimensions | powered_dimensions) >> extended_dimension_rules.maybe }
25
+ rule(:powered_dimensions) { dimensions >> power.maybe }
17
26
 
18
27
  rule(:units) do
19
- @@filtered_units ||= arr_to_expression(Unitsdb.units.filtered, "units")
28
+ @@filtered_units ||= arr_to_expression(::Unitsml::Unitsdb.units.filtered, 'unit')
20
29
  end
21
30
 
22
31
  rule(:single_letter_prefixes) do
23
- @@prefixes1 ||= arr_to_expression(Unitsdb.prefixes_by_size(1), "prefixes")
32
+ @@prefixes1 ||= arr_to_expression(::Unitsml::Unitsdb.prefixes_by_size(1), 'prefix')
24
33
  end
25
34
 
26
35
  rule(:double_letter_prefixes) do
27
- @@prefixes2 ||= arr_to_expression(Unitsdb.prefixes_by_size(2), "prefixes")
36
+ @@prefixes2 ||= arr_to_expression(::Unitsml::Unitsdb.prefixes_by_size(2), 'prefix')
28
37
  end
29
38
 
30
39
  rule(:dimensions) do
31
- @@dimensions ||= arr_to_expression(Unitsdb.dimensions.parsables.keys, "dimensions")
40
+ @@dimensions ||= arr_to_expression(::Unitsml::Unitsdb.dimensions.parsables.keys, 'dimension')
32
41
  end
33
42
 
34
43
  rule(:prefixes_units) do
35
- (sqrt(sequence) >> extend_exp(prefixes_units)) |
36
- (str("1").as(:units) >> extend_exp(prefixes_units)) |
37
- (unit_and_power >> extender >> intermediate_exp(prefixes_units).as(:sequence)) |
38
- unit_and_power |
39
- (single_letter_prefixes >> unit_and_power >> extender >> intermediate_exp(prefixes_units).as(:sequence)) |
40
- (single_letter_prefixes >> unit_and_power) |
41
- (double_letter_prefixes >> unit_and_power >> extender >> intermediate_exp(prefixes_units).as(:sequence)) |
42
- (double_letter_prefixes >> unit_and_power)
43
- end
44
-
45
- rule(:dimension_rules) do
46
- (sqrt(intermediate_exp(dimensions >> power.maybe)) >> extend_exp(dimension_rules)) |
47
- (dimensions >> power.maybe >> extend_exp(dimension_rules))
44
+ (sqrt_sequence >> extended_prefixed_units.maybe) |
45
+ (str('1').as(:unit) >> extended_prefixed_units.maybe) |
46
+ (unit_and_power >> extended_prefixed_units) |
47
+ unit_and_power >> (any.absent? | (extender | opening_paren | closing_paren | spaces).present?) |
48
+ (double_letter_prefixes >> unit_and_power >> extended_prefixed_units) |
49
+ (double_letter_prefixes >> unit_and_power) |
50
+ (single_letter_prefixes >> unit_and_power >> extended_prefixed_units) |
51
+ (single_letter_prefixes >> unit_and_power)
48
52
  end
49
53
 
50
54
  rule(:expression) do
51
- intermediate_exp(prefixes_units) |
52
- intermediate_exp(dimension_rules) |
55
+ prefixes_units_int_exp |
56
+ dimension_rules_int_exp |
53
57
  single_letter_prefixes >> hyphen |
54
58
  double_letter_prefixes >> hyphen
55
59
  end
@@ -57,23 +61,11 @@ module Unitsml
57
61
  root :expression
58
62
 
59
63
  def arr_to_expression(arr, file_name)
60
- array = arr&.flatten&.compact&.sort_by(&:length).reverse
64
+ array = arr&.flatten&.compact&.sort_by(&:length)&.reverse
61
65
  array&.reduce do |expression, expr_string|
62
66
  expression = str(expression).as(file_name.to_sym) if expression.is_a?(String)
63
67
  expression | str(expr_string).as(file_name.to_sym)
64
68
  end
65
69
  end
66
-
67
- def sqrt(rule)
68
- str("sqrt(") >> rule.as(:sqrt) >> str(")")
69
- end
70
-
71
- def extend_exp(rule)
72
- (extender >> intermediate_exp(rule).as(:sequence)).maybe
73
- end
74
-
75
- def intermediate_exp(rule)
76
- rule | (str("(") >> rule >> str(")"))
77
- end
78
70
  end
79
71
  end