kumi-parser 0.0.15 → 0.0.16

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: 1d86288cacf8d5e80d38541472d08b58ff202a7ec04efd0689c3b2698480fde1
4
- data.tar.gz: 86088f162d87519650cb0e6473176962967f292479bafb71973294bf723a4752
3
+ metadata.gz: b7c82cf28e39c53592ff6acb03772bc9d346716cb1dee414f4d1bce450629b9e
4
+ data.tar.gz: e9464f66ff1aae2b9d38770bdf1c9fe9d96eef114838eaec532a4408f87b8435
5
5
  SHA512:
6
- metadata.gz: 5ab143e2e5a1f3e2e84c3ebb1a23283d4c24ce727dd4a4145d0beac7415e823bb0a0ce29711a8354010c662402f0ecaea7da0a254b8a352f200dee3bcae7fa61
7
- data.tar.gz: 76abe4b2565162a1b49421de36355bf011aa444ca3372bfb3b42ff4361e50959079103b2f85b704c17ffe06ee689c3dc39f45359fe84cd165590a82c9e74982c
6
+ metadata.gz: a4902e5502a0298fd6f9f24a9f80701910f641fa8098917d40cf0daa84f0845861c1f97aebd940bd704d213d1bce91fc1ad6971796bef76bfb2f5382aee60840
7
+ data.tar.gz: 512f5f4b80d7be91c543e1ae4f85c95835f9b52e2eb5768b4b55d4f69f27e17e640392851f3e2ee1b40003254d6160e533559f24a8e7546951b4d507c5d55950
@@ -398,6 +398,9 @@ module Kumi
398
398
  when :lbracket
399
399
  parse_array_literal
400
400
 
401
+ when :left_brace
402
+ parse_hash_literal
403
+
401
404
  when :fn
402
405
  # expect_token(:fn)
403
406
  parse_function_call
@@ -520,6 +523,57 @@ module Kumi
520
523
  Kumi::Syntax::ArrayExpression.new(elements, loc: start_token.location)
521
524
  end
522
525
 
526
+ def parse_hash_literal
527
+ start_token = expect_token(:left_brace)
528
+ skip_comments_and_newlines
529
+ pairs = []
530
+
531
+ # Handle empty hash: {}
532
+ unless current_token.type == :right_brace
533
+ pairs << parse_hash_pair
534
+ skip_comments_and_newlines
535
+
536
+ while current_token.type == :comma
537
+ advance
538
+ skip_comments_and_newlines
539
+ # Allow trailing comma
540
+ break if current_token.type == :right_brace
541
+
542
+ pairs << parse_hash_pair
543
+ skip_comments_and_newlines
544
+ end
545
+ end
546
+
547
+ expect_token(:right_brace)
548
+ Kumi::Syntax::HashExpression.new(pairs, loc: start_token.location)
549
+ end
550
+
551
+ def parse_hash_pair
552
+ key_token_type = current_token.type
553
+ key = case key_token_type
554
+ when :label, :string
555
+ value = current_token.value.to_sym if key_token_type == :label
556
+ advance
557
+ Kumi::Syntax::Literal.new(value, loc: current_token.location)
558
+ else
559
+ raise_parse_error("Hash keys must be symbols (:key) or strings (\"key\"), got #{current_token.type}")
560
+ end
561
+
562
+ skip_comments_and_newlines
563
+
564
+ case current_token.type
565
+ when :arrow
566
+ advance
567
+ else
568
+ raise_parse_error("Expected '=>' in hash pair") unless key_token_type == :label
569
+ end
570
+
571
+ skip_comments_and_newlines
572
+ value = parse_expression
573
+
574
+ [key, value]
575
+ end
576
+
523
577
  def convert_literal_value(token)
524
578
  case token.type
525
579
  when :integer then token.value.gsub('_', '').to_i
@@ -34,7 +34,7 @@ module Kumi
34
34
  else
35
35
  consume_operator_or_punctuation
36
36
  end
37
- when /[a-zA-Z_]/ then consume_identifier_or_keyword
37
+ when /[a-zA-Z_]/ then consume_identifier_or_label_or_keyword
38
38
  when ':' then consume_symbol_or_colon
39
39
  else
40
40
  consume_operator_or_punctuation
@@ -158,26 +158,34 @@ module Kumi
158
158
  @tokens << Token.new(token_type, number_str, location, Kumi::Parser::TOKEN_METADATA[token_type])
159
159
  end
160
160
 
161
- def consume_identifier_or_keyword
161
+ def consume_identifier_or_label_or_keyword
162
162
  start_column = @column
163
- identifier = consume_while { |c| c.match?(/[a-zA-Z0-9_]/) }
163
+ identifier_or_label_name = consume_while { |c| c.match?(/[a-zA-Z0-9_]/) }
164
+ location = Kumi::Syntax::Location.new(file: @source_file, line: @line, column: start_column)
165
+
166
+ # Check if the next character is a colon
167
+ if current_char == ':'
168
+ # It's a hash key or a label (e.g., `name:`)
169
+ advance # consume the colon
170
+ add_token(:label, identifier_or_label_name, Kumi::Parser::TOKEN_METADATA[:label])
171
+ return
172
+ end
173
+
174
+ # If it's not a label, proceed to check for keywords and identifiers
175
+ # The logic below is adapted from your original `consume_identifier_or_keyword` method
164
176
 
165
177
  # Check if it's a constant (e.g., Float::INFINITY)
166
- if identifier == 'Float' && current_char == ':' && peek_char == ':'
178
+ if identifier_or_label_name == 'Float' && current_char == ':' && peek_char == ':'
167
179
  advance # consume first :
168
180
  advance # consume second :
169
181
  constant_name = consume_while { |c| c.match?(/[a-zA-Z0-9_]/) }
170
- full_constant = "#{identifier}::#{constant_name}"
171
-
172
- location = Kumi::Syntax::Location.new(file: @source_file, line: @line, column: start_column)
173
- @tokens << Token.new(:constant, full_constant, location, Kumi::Parser::TOKEN_METADATA[:constant])
182
+ full_constant = "#{identifier_or_label_name}::#{constant_name}"
183
+ add_token(:constant, full_constant, Kumi::Parser::TOKEN_METADATA[:constant])
174
184
  return
175
185
  end
176
186
 
177
- location = Kumi::Syntax::Location.new(file: @source_file, line: @line, column: start_column)
178
-
179
187
  # Check if it's a keyword
180
- if keyword_type = Kumi::Parser::KEYWORDS[identifier]
188
+ if keyword_type = Kumi::Parser::KEYWORDS[identifier_or_label_name]
181
189
  metadata = Kumi::Parser::TOKEN_METADATA[keyword_type].dup
182
190
 
183
191
  # Update context based on keyword
@@ -189,30 +197,26 @@ module Kumi
189
197
  closed_context = @context_stack.pop if @context_stack.length > 1
190
198
  metadata[:closes_context] = closed_context
191
199
  end
192
-
193
- @tokens << Token.new(keyword_type, identifier, location, metadata)
200
+ add_token(keyword_type, identifier_or_label_name, metadata)
194
201
  return
195
202
  end
196
203
 
197
204
  # Check if its a function sugar
198
- if Kumi::Parser::FUNCTION_SUGAR[identifier]
205
+ if Kumi::Parser::FUNCTION_SUGAR[identifier_or_label_name]
199
206
  metadata = Kumi::Parser::TOKEN_METADATA[:function_sugar].dup
200
- @tokens << Token.new(:function_sugar, identifier, location, metadata)
207
+ add_token(:function_sugar, identifier_or_label_name, metadata)
201
208
  return
202
209
  end
203
210
 
204
- # Otherwise is an Idenfier
211
+ # Otherwise is an Identifier
205
212
  metadata = Kumi::Parser::TOKEN_METADATA[:identifier].dup
206
-
207
- # Add context-specific metadata
208
213
  case current_context
209
214
  when :input
210
215
  metadata[:context] = :input_declaration
211
216
  when :schema
212
217
  metadata[:context] = :schema_body
213
218
  end
214
-
215
- @tokens << Token.new(:identifier, identifier, location, metadata)
219
+ add_token(:identifier, identifier_or_label_name, metadata)
216
220
  end
217
221
 
218
222
  def consume_symbol_or_colon
@@ -240,7 +244,12 @@ module Kumi
240
244
  # Handle multi-character operators
241
245
  case char
242
246
  when '='
243
- if peek_char == '='
247
+ if peek_char == '>'
248
+ advance
249
+ advance
250
+ location = Kumi::Syntax::Location.new(file: @source_file, line: @line, column: start_column)
251
+ @tokens << Token.new(:arrow, '=>', location, Kumi::Parser::TOKEN_METADATA[:arrow])
252
+ elsif peek_char == '='
244
253
  advance
245
254
  advance
246
255
  location = Kumi::Syntax::Location.new(file: @source_file, line: @line, column: start_column)
@@ -261,7 +261,6 @@ module Kumi
261
261
  arity: :binary,
262
262
  requires_boolean: true
263
263
  },
264
-
265
264
  # Literals with type information
266
265
  integer: {
267
266
  category: :literal,
@@ -283,7 +282,6 @@ module Kumi
283
282
  starts_expression: true,
284
283
  ast_class: 'Kumi::Syntax::Literal'
285
284
  },
286
-
287
285
  # Identifiers and references
288
286
  identifier: {
289
287
  category: :identifier,
@@ -344,6 +342,15 @@ module Kumi
344
342
  terminates_expression: true
345
343
  },
346
344
 
345
+ left_brace: {
346
+ category: :punctuation,
347
+ opens_scope: :hash
348
+ },
349
+ right_brace: {
350
+ category: :punctuation,
351
+ closes_scope: :hash
352
+ },
353
+
347
354
  # Special tokens
348
355
  newline: {
349
356
  category: :whitespace,
@@ -365,6 +372,8 @@ module Kumi
365
372
  ')' => :rparen,
366
373
  '[' => :lbracket,
367
374
  ']' => :rbracket,
375
+ '{' => :left_brace,
376
+ '}' => :right_brace,
368
377
  ',' => :comma,
369
378
  '.' => :dot,
370
379
  ':' => :colon,
@@ -374,7 +383,8 @@ module Kumi
374
383
  '/' => :divide,
375
384
  '%' => :modulo,
376
385
  '&' => :and,
377
- '|' => :or
386
+ '|' => :or,
387
+ '=>' => :arrow
378
388
  }.freeze
379
389
 
380
390
  FUNCTION_SUGAR = {
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Kumi
4
4
  module Parser
5
- VERSION = '0.0.15'
5
+ VERSION = '0.0.16'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kumi-parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.15
4
+ version: 0.0.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kumi Team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-09-02 00:00:00.000000000 Z
11
+ date: 2025-09-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kumi