parsanol 1.3.97 → 1.3.98

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf07ff87918523715b0dbc598966de71f896c18b8988733fd43061013a85b981
4
- data.tar.gz: 2e43a8c0c226ac58a329c1f676d845a5222e9048ff4a13d9f8fc2ce977bdb2f8
3
+ metadata.gz: 141dfea6902c1018accd9962fc346017dbb8d070303323df0d98e5f16bf12516
4
+ data.tar.gz: ec3ae0172d80d7c6c84743376958fb2ceb7dffd9072afbfe641fcf4e0267e079
5
5
  SHA512:
6
- metadata.gz: 8c905fbaaa68c14eb9d577cb77cc3ad74af1659c6e7fbdb859716701684ba3a20cddb239483893dd636e27cb46da0dc49629b63df31b19d6589c2bc3c643512c
7
- data.tar.gz: 924495ccc4452ca647644cf99a702d649abadba866d70b5ee96d3e0bac672500c55512e5d2c48336e616a992f05164b082c4f163fed591a541b8139fe262d844
6
+ metadata.gz: 40e41398c910b644fe3be0a7042d0a2ed763e2e622d61e98d3efa01d5bf74301c2adc61dbfdd689f99987c6677a7737402d97f013050b4cd6080c3706ee656b9
7
+ data.tar.gz: 46e233a13a96163779eb6eca5d07687cc6fe9c7fbd3e88c81e20d2af9aa43939ddca682e1210b3d2e5cc5b1555c2660aad8cecc01d9ff45f0adc25b6d0fc9ff7
data/Cargo.lock CHANGED
@@ -307,9 +307,9 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
307
307
 
308
308
  [[package]]
309
309
  name = "parsanol"
310
- version = "0.18.9"
310
+ version = "0.18.10"
311
311
  source = "registry+https://github.com/rust-lang/crates.io-index"
312
- checksum = "456a6ee7850bd50d2254b3232d537af2de447ea354a40a06a33904da899cd57b"
312
+ checksum = "54bbd6459639572bc085c504112bc9a4acbca47719736aebad19d9113549bdad"
313
313
  dependencies = [
314
314
  "ahash",
315
315
  "getrandom 0.3.4",
@@ -326,9 +326,9 @@ dependencies = [
326
326
 
327
327
  [[package]]
328
328
  name = "parsanol-derive"
329
- version = "0.18.9"
329
+ version = "0.18.10"
330
330
  source = "registry+https://github.com/rust-lang/crates.io-index"
331
- checksum = "280663d376aefe51ad6850535618f67fbb281d48f6ac024fad560ee39029ace1"
331
+ checksum = "40adc63c6d2afcd1b095518d55f0095c5c04445f46994592161f0fa60cf6331b"
332
332
  dependencies = [
333
333
  "proc-macro2",
334
334
  "quote",
@@ -178,8 +178,9 @@ module Parsanol
178
178
  when "capture"
179
179
  captures = Bindings.collect_captures(shape)
180
180
  mismatched = hash["expect"].reject do |key, value|
181
- actual = captures[key.to_sym]&.first
182
- !actual.nil? && Bindings.canonical(actual) == Bindings.canonical(value)
181
+ values = captures[key.to_sym]
182
+ values && !values.empty? &&
183
+ Bindings.canonical(values.first) == Bindings.canonical(value)
183
184
  end
184
185
  next if mismatched.empty?
185
186
 
@@ -64,7 +64,9 @@ module Parsanol
64
64
  count = group.map { |binding| captures[binding["capture"].to_sym].length }.max || 0
65
65
  return if count.zero?
66
66
 
67
- list = (out[prefix] ||= [])
67
+ # Field names are symbols everywhere else (scalar bindings, element
68
+ # fields); the array prefix must match or `example` lookups miss it.
69
+ list = (out[prefix.to_sym] ||= [])
68
70
  count.times do |index|
69
71
  element = {}
70
72
  group.each do |binding|
@@ -378,8 +378,9 @@ module Parsanol
378
378
  when :capture
379
379
  captures = Bindings.collect_captures(shape)
380
380
  mismatched = test.expect.reject do |key, value|
381
- actual = captures[key.to_sym]&.first
382
- !actual.nil? && Bindings.canonical(actual) == Bindings.canonical(value)
381
+ values = captures[key.to_sym]
382
+ values && !values.empty? &&
383
+ Bindings.canonical(values.first) == Bindings.canonical(value)
383
384
  end
384
385
  next if mismatched.empty?
385
386
 
@@ -23,7 +23,7 @@ module Parsanol
23
23
  | (?<arrow>->)
24
24
  | (?<num>\d+)
25
25
  | (?<ident>[A-Za-z_][A-Za-z0-9_]*)
26
- | (?<punct>[=\/()\[\]{}*!&:,.<])
26
+ | (?<punct>[=\/()\[\]{}*!&:,.<-])
27
27
  /x
28
28
 
29
29
  def initialize(text)
@@ -91,6 +91,8 @@ module Parsanol
91
91
  punct(":")
92
92
  expect_pairs[key.to_sym] = parse_test_value
93
93
  skip_newlines
94
+ advance if peek&.type == :punct && peek.value == ","
95
+ skip_newlines
94
96
  end
95
97
  punct("}")
96
98
  end
@@ -101,18 +103,84 @@ module Parsanol
101
103
  skip_newlines
102
104
  end
103
105
 
106
+ # Expectation values: strings, numbers, true/false/null, arrays, and
107
+ # nested objects. Nested structure is what pins array bindings,
108
+ # absent-optional nil, and flatten/merge results in the corpus;
109
+ # before this the test grammar only accepted scalars.
104
110
  def parse_test_value
105
- token = advance
111
+ token = peek
106
112
  case token&.type
107
- when :str then unquote(token.value)
108
- when :num then token.value.to_i
109
- when :ident
110
- raise ParseError, "expected true or false" unless %w[true false].include?(token.value)
113
+ when :str then unquote(advance.value)
114
+ when :num then parse_test_number
115
+ when :punct
116
+ case token.value
117
+ when "[" then parse_test_array
118
+ when "{" then parse_test_object
119
+ when "-"
120
+ advance
121
+ unless peek&.type == :num
122
+ raise ParseError, "expected a number after '-' in a test value"
123
+ end
111
124
 
112
- token.value == "true"
125
+ -parse_test_number
126
+ else
127
+ raise ParseError,
128
+ "expected a test value (string, number, true, false, null, array, object)"
129
+ end
130
+ when :ident
131
+ advance
132
+ case token.value
133
+ when "true" then true
134
+ when "false" then false
135
+ when "null" then nil
136
+ else
137
+ raise ParseError,
138
+ "expected true, false, or null, got #{token.value.inspect}"
139
+ end
113
140
  else
114
- raise ParseError, "expected a string, number, true or false"
141
+ raise ParseError,
142
+ "expected a test value (string, number, true, false, null, array, object)"
143
+ end
144
+ end
145
+
146
+ # The lexer emits integers only; a decimal is num "." num.
147
+ def parse_test_number
148
+ text = advance.value
149
+ if peek&.type == :punct && peek.value == "." && @tokens[@pos + 1]&.type == :num
150
+ advance
151
+ text = "#{text}.#{advance.value}"
115
152
  end
153
+ text.include?(".") ? Float(text) : Integer(text, 10)
154
+ end
155
+
156
+ def parse_test_array
157
+ punct("[")
158
+ values = []
159
+ skip_newlines
160
+ until peek&.type == :punct && peek.value == "]"
161
+ values << parse_test_value
162
+ skip_newlines
163
+ advance if peek&.type == :punct && peek.value == ","
164
+ skip_newlines
165
+ end
166
+ punct("]")
167
+ values
168
+ end
169
+
170
+ def parse_test_object
171
+ punct("{")
172
+ value = {}
173
+ skip_newlines
174
+ until peek&.type == :punct && peek.value == "}"
175
+ key = ident.value
176
+ punct(":")
177
+ value[key.to_sym] = parse_test_value
178
+ skip_newlines
179
+ advance if peek&.type == :punct && peek.value == ","
180
+ skip_newlines
181
+ end
182
+ punct("}")
183
+ value
116
184
  end
117
185
 
118
186
  def eof? = @pos >= @tokens.length
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "json"
4
+
3
5
  module Parsanol
4
6
  module PARG
5
7
  # F10 phase 2 (gate slice): every .parg source must parse under the parg
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Parsanol
4
- VERSION = "1.3.97"
4
+ VERSION = "1.3.98"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parsanol
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.97
4
+ version: 1.3.98
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.