lutaml-lml 0.3.3 → 0.3.5

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/exe/lutaml-lml-lsp +11 -0
  3. data/lib/lutaml/lml/cli.rb +166 -17
  4. data/lib/lutaml/lml/data_processor/attribute_processing.rb +4 -2
  5. data/lib/lutaml/lml/data_processor/value_declaration_processing.rb +1 -0
  6. data/lib/lutaml/lml/data_processor.rb +8 -1
  7. data/lib/lutaml/lml/diagnostic.rb +149 -0
  8. data/lib/lutaml/lml/document_builder.rb +63 -21
  9. data/lib/lutaml/lml/format/adapter/standard_adapter.rb +22 -23
  10. data/lib/lutaml/lml/formatter/canonical.rb +736 -0
  11. data/lib/lutaml/lml/formatter.rb +2 -0
  12. data/lib/lutaml/lml/grammar/lml.artifact.json +2946 -2512
  13. data/lib/lutaml/lml/grammar/lml.parg +47 -9
  14. data/lib/lutaml/lml/grammar.rb +13 -0
  15. data/lib/lutaml/lml/import_resolver.rb +13 -4
  16. data/lib/lutaml/lml/lsp/conversions.rb +78 -0
  17. data/lib/lutaml/lml/lsp/keywords.rb +43 -0
  18. data/lib/lutaml/lml/lsp/server.rb +378 -0
  19. data/lib/lutaml/lml/lsp/store.rb +68 -0
  20. data/lib/lutaml/lml/lsp/transport.rb +53 -0
  21. data/lib/lutaml/lml/lsp.rb +16 -0
  22. data/lib/lutaml/lml/model_compiler/serialization_mappings.rb +36 -10
  23. data/lib/lutaml/lml/model_compiler.rb +25 -2
  24. data/lib/lutaml/lml/models/association.rb +3 -0
  25. data/lib/lutaml/lml/models/constraint.rb +3 -0
  26. data/lib/lutaml/lml/models/data_type.rb +3 -0
  27. data/lib/lutaml/lml/models/diagram.rb +3 -0
  28. data/lib/lutaml/lml/models/document.rb +10 -3
  29. data/lib/lutaml/lml/models/enum.rb +4 -1
  30. data/lib/lutaml/lml/models/instance.rb +3 -0
  31. data/lib/lutaml/lml/models/instance_collection.rb +3 -0
  32. data/lib/lutaml/lml/models/member_field.rb +2 -0
  33. data/lib/lutaml/lml/models/namespace.rb +2 -0
  34. data/lib/lutaml/lml/models/operation.rb +4 -1
  35. data/lib/lutaml/lml/models/package.rb +3 -0
  36. data/lib/lutaml/lml/models/primitive_type.rb +6 -3
  37. data/lib/lutaml/lml/models/serialization_mapping.rb +2 -0
  38. data/lib/lutaml/lml/models/top_element_attribute.rb +6 -0
  39. data/lib/lutaml/lml/models/uml_class.rb +6 -0
  40. data/lib/lutaml/lml/models/value.rb +3 -0
  41. data/lib/lutaml/lml/pipeline.rb +25 -8
  42. data/lib/lutaml/lml/positioned.rb +13 -0
  43. data/lib/lutaml/lml/preprocessor.rb +44 -13
  44. data/lib/lutaml/lml/quoting.rb +60 -0
  45. data/lib/lutaml/lml/source_position.rb +20 -0
  46. data/lib/lutaml/lml/symbol_index.rb +200 -0
  47. data/lib/lutaml/lml/transform.rb +49 -2
  48. data/lib/lutaml/lml/validator.rb +134 -21
  49. data/lib/lutaml/lml/version.rb +1 -1
  50. data/lib/lutaml/lml.rb +18 -1
  51. metadata +18 -4
@@ -10,14 +10,7 @@ module Lutaml
10
10
  class StandardAdapter < Document
11
11
  TYPE_KEY = "__type__"
12
12
 
13
- # The grammar's `word` rule is [A-Za-z0-9_] only (lml.parg) and
14
- # `variable = quoted_string / 1*word` — a bare value is a run of
15
- # word characters and nothing else. Anything else (a dash, a
16
- # space, a digit-leading date...) commits the value parser to
17
- # `number` or fails re-parsing, so it must be emitted quoted.
18
- # This predicate is the single source of truth for the emit
19
- # side; the parse side is pinned by the grammar itself.
20
- BARE_WORD = /\A\w+\z/
13
+ include Lutaml::Lml::Quoting
21
14
 
22
15
  def self.parse(data, _options = {})
23
16
  return data if data.is_a?(Hash)
@@ -78,13 +71,7 @@ module Lutaml
78
71
  end
79
72
 
80
73
  def format_key(key)
81
- key = key.to_s
82
- return key if key.match?(BARE_WORD)
83
-
84
- # Same escaping as quote_value: a key may contain any
85
- # character, and the emitted form must re-parse (issue #78).
86
- escaped = key.gsub('\\') { |bs| bs * 2 }.gsub('"') { |q| "\\#{q}" }
87
- "\"#{escaped}\""
74
+ quote_scalar(key)
88
75
  end
89
76
 
90
77
  def format_value(prefix, key, value, indent)
@@ -96,7 +83,9 @@ module Lutaml
96
83
  format_array(prefix, key, value, indent)
97
84
  when Hash
98
85
  format_nested(prefix, key, value, indent)
99
- when TrueClass, FalseClass, Integer, Float
86
+ when Float
87
+ "#{prefix}#{key} = #{number_scalar(value)}"
88
+ when TrueClass, FalseClass, Integer
100
89
  "#{prefix}#{key} = #{value}"
101
90
  else
102
91
  "#{prefix}#{key} = #{quote_value(value)}"
@@ -144,17 +133,27 @@ module Lutaml
144
133
  end
145
134
 
146
135
  def quote_value(val)
136
+ return number_scalar(val) if val.is_a?(Float)
147
137
  return val.to_s if val.is_a?(Numeric) || val.is_a?(TrueClass) || val.is_a?(FalseClass)
148
138
 
139
+ # RS 3001 §String values: escape backslash and double quote;
140
+ # every value is representable in double quotes. A bare word
141
+ # is only safe when the parser reads it back as the same
142
+ # string — `null`, booleans, and digit-leading tokens are
143
+ # data literals (and digit-led words do not re-parse).
149
144
  str = val.to_s
150
- return str if str.match?(BARE_WORD)
145
+ return str if safe_bare_string?(str)
151
146
 
152
- # RS 3001 §String values: escape backslash and double quote;
153
- # every value is representable in double quotes.
154
- # gsub replacement strings re-interpret backslash pairs, so
155
- # the backslash doubling uses the block form.
156
- escaped = str.gsub('\\') { |bs| bs * 2 }.gsub('"') { |q| "\\#{q}" }
157
- "\"#{escaped}\""
147
+ quote_always(str)
148
+ end
149
+
150
+ private
151
+
152
+ def safe_bare_string?(str)
153
+ return false unless str.match?(Lutaml::Lml::Quoting::BARE_WORD)
154
+ return false if str.match?(/\A(?:true|false|null)\z/)
155
+
156
+ !str.match?(/\A\d/)
158
157
  end
159
158
  end
160
159
  end