loxxy 0.4.05 → 0.4.08

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36f3b49ca1158cd6922cb5ece2340f53efec793e5877a96f94aebc0eee34235d
4
- data.tar.gz: ade953da452fbf9ad6552e8dbfb035161c79c2bffcd0d531c4e79cf6d785c51c
3
+ metadata.gz: e7e447625d999f4b95129d7feff1586c6759cb929a8faaa82e3ecc94105d0268
4
+ data.tar.gz: 00a4801454ffd09b2d4e810fd15d0f9b40fea13f46e6d4eed7eba4cab8d35ebe
5
5
  SHA512:
6
- metadata.gz: bc0ff7ac6da9846a5a70ead053ceeee2eb390f778a70932392fcbe10ce70c7e147f11983baee96dc5aed924de492d744c3b6b61c8d03f389a74432a56b3916a5
7
- data.tar.gz: 40e36a53abc6ce121299952ff98f71175198271659f3a7dabf1cbd0f8e79bdc4c76242f47a4707c513f9ca63459bd4495d56de2287136cedb5cadac14ed4fca3
6
+ metadata.gz: 4a59f746cb7b8086ff3e1252c3fc0846229cb6927dcc4d62ad261c5e0c2fec4b1a75176cab6788cedb5c57a2fe9e7bec94d92d7dc63a2c455609a18761f78043
7
+ data.tar.gz: 66f72710a3f422e4431c88c44b56419f727711c1fbf339491f1fcb2f8f18edb0f4a21ce49a66ee4325ccf3b2576b0b94490d74f96c922a9d340d476e43660881
data/.rubocop.yml CHANGED
@@ -162,6 +162,9 @@ Lint/UnusedMethodArgument:
162
162
  Lint/UselessAccessModifier:
163
163
  Enabled: true
164
164
 
165
+ Lint/UselessRuby2Keywords: # new in 1.23
166
+ Enabled: true
167
+
165
168
  Lint/Void:
166
169
  Enabled: false
167
170
 
@@ -201,6 +204,9 @@ Metrics/ModuleLength:
201
204
  Metrics/PerceivedComplexity:
202
205
  Enabled: false
203
206
 
207
+ Naming/BlockForwarding: # new in 1.24
208
+ Enabled: true
209
+
204
210
  Naming/ConstantName:
205
211
  Enabled: false
206
212
 
@@ -427,6 +433,12 @@ Style/EndlessMethod:
427
433
  Style/ExplicitBlockArgument:
428
434
  Enabled: true
429
435
 
436
+ Style/FileRead: # new in 1.24
437
+ Enabled: true
438
+
439
+ Style/FileWrite: # new in 1.24
440
+ Enabled: true
441
+
430
442
  Style/GlobalStdStream:
431
443
  Enabled: true
432
444
 
@@ -438,12 +450,19 @@ Style/HashConversion:
438
450
 
439
451
  Style/HashLikeCase:
440
452
  Enabled: true
441
-
453
+
442
454
  Style/IfWithBooleanLiteralBranches:
443
455
  Enabled: true
456
+
457
+ Style/MapToHash: # new in 1.24
458
+ Enabled: true
459
+
460
+ Style/OpenStructUse: # new in 1.23
461
+ Enabled: true
444
462
 
445
463
  Style/OptionalBooleanParameter:
446
464
  Enabled: true
465
+
447
466
 
448
467
  Style/RedundantAssignment:
449
468
  Enabled: true
data/CHANGELOG.md CHANGED
@@ -1,3 +1,33 @@
1
+ ## [0.4.08] - 2022-04-09
2
+ - Refactoring of the `Scanner` class.
3
+
4
+ ### Changed
5
+ - `Frontend::Scanner` class: major code refactoring.
6
+
7
+ ## [0.4.07] - 2021-11-21
8
+ - Minor fixes; dependency towards Rubies 3+ allowed...
9
+
10
+ ### Fixed
11
+ - File `loxxy.gemspec` dependency on Ruby version relaxed to support Ruby 3+
12
+ - File `resolver.rb` Fixed a typo in standard Lox error message.
13
+ - File `collide_with_paramaeter.lox` Fixed typo in error message.
14
+ - File `duplicate_local.lox` Fixed typo in error message.
15
+ - File `duplicate_parameter.lox` Fixed typo in error message.
16
+
17
+
18
+ ## [0.4.06] - 2021-11-01
19
+ - Code update to cope with `Rley` v.0.8.08 changes
20
+
21
+ ### Changed
22
+ - File `AST::AstBuilder` some `reduce_` to cope implementation change of ? quantifier
23
+ - Method `AST::LoxCallExpr#initialize` call to `Array#flatten` with argList argument
24
+ - File `loxxy.gemspec` dependency towards `rely` minimal version number is now `0.8.08`
25
+ - Some spec files updated after `rley` changes of ?, *, + quantifiers
26
+
27
+ ### Removed
28
+ - File `front_end/literal.rb`: obsolete
29
+
30
+
1
31
  ## [0.4.05] - 2021-10-10
2
32
  - Removal of `Literal` class, code restyling to please Rubocop 1.22
3
33
 
@@ -16,7 +46,7 @@
16
46
  - File `grammar.rb` use `match_closest` constraint from Rley to cope with dangling else statement
17
47
 
18
48
  ## [0.4.02] - 2021-09-10
19
- - Fixes in`AST::AstBuilder` class to cope with changes in Rley 0.8.03
49
+ - Fixes in`AST::AstBuilder` class to cope with changes in Rley 0.8.03
20
50
 
21
51
  ### Changed
22
52
  - File `loxxy.gemspec` forced dependency to Rley 0.8.03
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2020-2021 Dimitri Geshef
3
+ Copyright (c) 2020-2022 Dimitri Geshef
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -222,10 +222,8 @@ module Loxxy
222
222
  if test.nil? && update
223
223
  # when test expr is nil but update expr is not, then force test to be true
224
224
  test = LoxLiteralExpr.new(tokens[0].position, Datatype::True.instance)
225
- [init, test, update]
226
- else
227
- theChildren
228
225
  end
226
+ [init, test, update&.first]
229
227
  end
230
228
 
231
229
  # rule('forInitialization' => 'SEMICOLON')
@@ -234,8 +232,8 @@ module Loxxy
234
232
  end
235
233
 
236
234
  # rule('forTest' => 'expression? SEMICOLON')
237
- def reduce_for_test(_production, range, tokens, theChildren)
238
- return_first_child(range, tokens, theChildren)
235
+ def reduce_for_test(_production, _range, _tokens, theChildren)
236
+ theChildren[0]&.first
239
237
  end
240
238
 
241
239
  # rule('ifStmt' => 'IF ifCondition statement ELSE statement')
@@ -262,7 +260,8 @@ module Loxxy
262
260
 
263
261
  # rule('returnStmt' => 'RETURN expression? SEMICOLON')
264
262
  def reduce_return_stmt(_production, _range, tokens, theChildren)
265
- Ast::LoxReturnStmt.new(tokens[1].position, theChildren[1])
263
+ ret_expr = theChildren[1].nil? ? nil : theChildren[1].first
264
+ Ast::LoxReturnStmt.new(tokens[1].position, ret_expr)
266
265
  end
267
266
 
268
267
  # rule('whileStmt' => 'WHILE LEFT_PAREN expression RIGHT_PAREN statement').as ''
@@ -275,7 +274,7 @@ module Loxxy
275
274
  decls = nil
276
275
  if theChildren[1]
277
276
  pos = tokens[1].position
278
- decls = LoxSeqDecl.new(tokens[1].position, theChildren[1])
277
+ decls = LoxSeqDecl.new(pos, theChildren[1].flatten)
279
278
  else
280
279
  pos = tokens[0].position
281
280
  end
@@ -377,15 +376,16 @@ module Loxxy
377
376
  LoxSuperExpr.new(theChildren[0].token.position, theChildren[2].token.lexeme)
378
377
  end
379
378
 
380
- # rule('function' => 'IDENTIFIER LEFT_PAREN params_opt RIGHT_PAREN block').as 'function'
379
+ # rule('function' => 'IDENTIFIER LEFT_PAREN parameters? RIGHT_PAREN block').as 'function'
381
380
  def reduce_function(_production, _range, _tokens, theChildren)
382
381
  first_child = theChildren.first
383
382
  pos = first_child.token.position
384
- if theChildren[2] && theChildren[2].size > 255
383
+ params = theChildren[2] ? theChildren[2].flatten : []
384
+ if params.size > 255
385
385
  msg = "Can't have more than 255 parameters."
386
386
  raise Loxxy::SyntaxError, msg
387
387
  end
388
- LoxFunStmt.new(pos, first_child.token.lexeme, theChildren[2], theChildren[4])
388
+ LoxFunStmt.new(pos, first_child.token.lexeme, params, theChildren[4])
389
389
  end
390
390
 
391
391
  # rule('parameters' => 'IDENTIFIER (COMMA IDENTIFIER)*').as 'parameters'
@@ -399,7 +399,7 @@ module Loxxy
399
399
 
400
400
  # rule('arguments' => 'expression (COMMA expression)*')
401
401
  def reduce_arguments(_production, _range, _tokens, theChildren)
402
- return [theChildren[0]] unless theChildren[1]
402
+ return [theChildren[0]] if theChildren[1].empty?
403
403
 
404
404
  successors = theChildren[1].map(&:last)
405
405
  successors.unshift(theChildren[0])
@@ -244,7 +244,6 @@ module Loxxy
244
244
 
245
245
  # Let's proceed with the visit of subnodes
246
246
  subnodes.each { |a_node| a_node.accept(self) }
247
-
248
247
  broadcast(:after_subnodes, aParentNode, subnodes)
249
248
  end
250
249
 
@@ -12,7 +12,7 @@ module Loxxy
12
12
  # @param argList [Array<Loxxy::Ast::LoxNode>]
13
13
  def initialize(aPosition, argList)
14
14
  super(aPosition, [])
15
- @arguments = argList
15
+ @arguments = argList.flatten
16
16
  end
17
17
 
18
18
  define_accept # Add `accept` method as found in Visitor design pattern
@@ -6,7 +6,7 @@ module Loxxy
6
6
  module Ast
7
7
  class LoxReturnStmt < LoxCompoundExpr
8
8
  # @param aPosition [Rley::Lexical::Position] Position of the entry in the input stream.
9
- # @param anExpression [Ast::LoxNode] expression to return
9
+ # @param anExpression [Ast::LoxNode, NilClass] expression to return
10
10
  def initialize(aPosition, anExpression)
11
11
  expr = anExpression || Datatype::Nil.instance
12
12
  super(aPosition, [expr])
@@ -220,7 +220,7 @@ module Loxxy
220
220
  curr_scope = scopes.last
221
221
  # Oddly enough, Lox allows variable re-declaration at top-level
222
222
  if curr_scope.include?(aVarName)
223
- msg = "Error at '#{aVarName}': Already variable with this name in this scope."
223
+ msg = "Error at '#{aVarName}': Already a variable with this name in this scope."
224
224
  raise Loxxy::RuntimeError, msg
225
225
  elsif curr_scope.size == 255 && current_function != :none
226
226
  msg = "Error at '#{aVarName}': Too many local variables in function."
@@ -5,7 +5,7 @@ require 'rley' # Load the gem
5
5
  module Loxxy
6
6
  module FrontEnd
7
7
  ########################################
8
- # Grammar for Lox language
8
+ # Grammar for the Lox language
9
9
  # Authoritative grammar at:
10
10
  # https://craftinginterpreters.com/appendix-i.html
11
11
  builder = Rley::grammar_builder do
@@ -20,6 +20,15 @@ module Loxxy
20
20
  # Delimiters: e.g. parentheses '(', ')'
21
21
  # Separators: e.g. comma
22
22
  class Scanner
23
+ PATT_BLOCK_COMMENT_BEGIN = /\/\*/.freeze
24
+ PATT_BLOCK_COMMENT_END = /\*\//.freeze
25
+ PATT_COMPARISON = /[!=><]=?/.freeze
26
+ PATT_IDENTIFIER = /[a-zA-Z_][a-zA-Z_0-9]*/.freeze
27
+ PATT_LINE_COMMENT = /\/\/[^\r\n]*/.freeze
28
+ PATT_NEWLINE = /(?:\r\n)|\r|\n/.freeze
29
+ PATT_NUMBER = /\d+(?:\.\d+)?/.freeze
30
+ PATT_WHITESPACE = /[ \t\f]+/.freeze
31
+
23
32
  # @return [StringScanner] Low-level input scanner
24
33
  attr_reader(:scanner)
25
34
 
@@ -31,7 +40,7 @@ module Loxxy
31
40
 
32
41
  # One or two special character tokens.
33
42
  # These are enumerated in section 4.2.1 Token type
34
- @@lexeme2name = {
43
+ Lexeme2name = {
35
44
  '(' => 'LEFT_PAREN',
36
45
  ')' => 'RIGHT_PAREN',
37
46
  '{' => 'LEFT_BRACE',
@@ -77,16 +86,16 @@ module Loxxy
77
86
  # Constructor. Initialize a tokenizer for Lox input.
78
87
  # @param source [String] Lox text to tokenize.
79
88
  def initialize(source = nil)
80
- @scanner = StringScanner.new('')
81
- start_with(source) if source
89
+ reset
90
+ input = source || ''
91
+ @scanner = StringScanner.new(input)
82
92
  end
83
93
 
84
94
  # Reset the tokenizer and make the given text, the current input.
85
95
  # @param source [String] Lox text to tokenize.
86
96
  def start_with(source)
97
+ reset
87
98
  @scanner.string = source
88
- @lineno = 1
89
- @line_start = 0
90
99
  end
91
100
 
92
101
  # Scan the source and return an array of tokens.
@@ -99,39 +108,79 @@ module Loxxy
99
108
  end
100
109
  tok_sequence << build_token('EOF', nil)
101
110
 
102
- return tok_sequence
111
+ tok_sequence
103
112
  end
104
113
 
105
114
  private
106
115
 
107
- def _next_token
108
- skip_intertoken_spaces
109
- curr_ch = scanner.peek(1)
110
- return nil if curr_ch.nil? || curr_ch.empty?
116
+ def reset
117
+ @state = :default
118
+ @lineno = 1
119
+ @line_start = 0
120
+ end
111
121
 
122
+ def _next_token
123
+ nesting_level = 0
112
124
  token = nil
113
125
 
114
- if '(){},.;+-/*'.include? curr_ch
115
- # Single delimiter or separator character
116
- token = build_token(@@lexeme2name[curr_ch], scanner.getch)
117
- elsif (lexeme = scanner.scan(/[!=><]=?/))
118
- # One or two special character tokens
119
- token = build_token(@@lexeme2name[lexeme], lexeme)
120
- elsif scanner.scan(/"/) # Start of string detected...
121
- token = build_string_token
122
- elsif (lexeme = scanner.scan(/\d+(?:\.\d+)?/))
123
- token = build_token('NUMBER', lexeme)
124
- elsif (lexeme = scanner.scan(/[a-zA-Z_][a-zA-Z_0-9]*/))
125
- keyw = @@keywords[lexeme]
126
- tok_type = keyw ? keyw.upcase : 'IDENTIFIER'
127
- token = build_token(tok_type, lexeme)
128
- else # Unknown token
129
- col = scanner.pos - @line_start + 1
130
- _erroneous = curr_ch.nil? ? '' : scanner.scan(/./)
131
- raise ScanError, "Error: [line #{lineno}:#{col}]: Unexpected character."
132
- end
126
+ # Loop until end of input reached or token found
127
+ until token || scanner.eos?
128
+ if scanner.skip(PATT_NEWLINE)
129
+ next_line_scanned
130
+ next
131
+ end
133
132
 
134
- return token
133
+ case @state
134
+ when :default
135
+ next if scanner.skip(PATT_WHITESPACE) # Skip whitespaces
136
+
137
+ curr_ch = scanner.peek(1)
138
+
139
+ token = if scanner.skip(PATT_LINE_COMMENT)
140
+ next
141
+ elsif scanner.skip(PATT_BLOCK_COMMENT_BEGIN)
142
+ @state = :in_block_comment
143
+ nesting_level = 1
144
+ next
145
+ elsif '(){},.;+-/*'.include? curr_ch
146
+ # Single delimiter or separator character
147
+ build_token(Lexeme2name[curr_ch], scanner.getch)
148
+ elsif (lexeme = scanner.scan(PATT_COMPARISON))
149
+ # One or two special character tokens
150
+ build_token(Lexeme2name[lexeme], lexeme)
151
+ elsif scanner.scan(/"/) # Start of string detected...
152
+ build_string_token
153
+ elsif (lexeme = scanner.scan(PATT_NUMBER))
154
+ build_token('NUMBER', lexeme)
155
+ elsif (lexeme = scanner.scan(PATT_IDENTIFIER))
156
+ keyw = @@keywords[lexeme]
157
+ tok_type = keyw ? keyw.upcase : 'IDENTIFIER'
158
+ build_token(tok_type, lexeme)
159
+ else # Unknown token
160
+ col = scanner.pos - @line_start + 1
161
+ _erroneous = curr_ch.nil? ? '' : scanner.scan(/./)
162
+ raise ScanError, "Error: [line #{lineno}:#{col}]: Unexpected character."
163
+ end
164
+
165
+ when :in_block_comment
166
+ comment_part = scanner.scan_until(/(?:\/\*)|(?:\*\/)|(?:(?:\r\n)|\r|\n)/)
167
+ unterminated_comment unless comment_part
168
+
169
+ case scanner.matched
170
+ when PATT_NEWLINE
171
+ next_line_scanned
172
+ when PATT_BLOCK_COMMENT_END
173
+ nesting_level -= 1
174
+ @state = :default if nesting_level.zero?
175
+ when PATT_BLOCK_COMMENT_BEGIN
176
+ nesting_level += 1
177
+ end
178
+ next
179
+ end # case
180
+ end # until
181
+
182
+ unterminated_comment unless nesting_level.zero?
183
+ token
135
184
  end
136
185
 
137
186
  def build_token(aSymbolName, aLexeme)
@@ -214,56 +263,12 @@ module Loxxy
214
263
  Rley::Lexical::Literal.new(lox_string, lexeme, 'STRING', pos)
215
264
  end
216
265
 
217
- # Skip non-significant whitespaces and comments.
218
- # Advance the scanner until something significant is found.
219
- def skip_intertoken_spaces
220
- loop do
221
- ws_found = scanner.skip(/[ \t\f]+/) ? true : false
222
- nl_found = scanner.skip(/(?:\r\n)|\r|\n/)
223
- if nl_found
224
- ws_found = true
225
- next_line
226
- end
227
- cmt_found = false
228
- if scanner.scan(/\/(\/|\*)/)
229
- cmt_found = true
230
- case scanner.matched
231
- when '//'
232
- scanner.skip(/[^\r\n]*(?:(?:\r\n)|\r|\n)?/)
233
- next_line
234
- when '/*'
235
- skip_block_comment
236
- next
237
- end
238
- end
239
- break unless ws_found || cmt_found
240
- end
241
-
242
- scanner.pos
243
- end
244
-
245
- def skip_block_comment
246
- nesting_level = 1
247
- loop do
248
- comment_part = scanner.scan_until(/(?:\/\*)|(?:\*\/)|(?:(?:\r\n)|\r|\n)/)
249
- unless comment_part
250
- msg = "Unterminated '/* ... */' block comment on line #{lineno}"
251
- raise ScanError, msg
252
- end
253
-
254
- case scanner.matched
255
- when /(?:(?:\r\n)|\r|\n)/
256
- next_line
257
- when '*/'
258
- nesting_level -= 1
259
- break if nesting_level.zero?
260
- when '/*'
261
- nesting_level += 1
262
- end
263
- end
266
+ def unterminated_comment
267
+ msg = "Unterminated '/* ... */' block comment on line #{lineno}"
268
+ raise ScanError, msg
264
269
  end
265
270
 
266
- def next_line
271
+ def next_line_scanned
267
272
  @lineno += 1
268
273
  @line_start = scanner.pos
269
274
  end
data/lib/loxxy/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Loxxy
4
- VERSION = '0.4.05'
4
+ VERSION = '0.4.08'
5
5
  end
data/loxxy.gemspec CHANGED
@@ -48,7 +48,7 @@ Gem::Specification.new do |spec|
48
48
  DESCR_END
49
49
  spec.homepage = 'https://github.com/famished-tiger/loxxy'
50
50
  spec.license = 'MIT'
51
- spec.required_ruby_version = '~> 2.5'
51
+ spec.required_ruby_version = '>= 2.5'
52
52
 
53
53
  spec.bindir = 'bin'
54
54
  spec.executables = ['loxxy']
@@ -58,7 +58,7 @@ Gem::Specification.new do |spec|
58
58
  PkgExtending.pkg_documentation(spec)
59
59
 
60
60
  # Runtime dependencies
61
- spec.add_dependency 'rley', '~> 0.8.06'
61
+ spec.add_dependency 'rley', '~> 0.8.08'
62
62
 
63
63
  # Development dependencies
64
64
  spec.add_development_dependency 'bundler', '~> 2.0'
@@ -28,7 +28,7 @@ module Loxxy
28
28
  expect(aParseTree.root.symbol.name).to eq('program')
29
29
  (decls, eof) = aParseTree.root.subnodes
30
30
  expect(decls).to be_kind_of(Rley::PTree::NonTerminalNode)
31
- expect(decls.symbol.name).to eq('declaration_star')
31
+ expect(decls.symbol.name).to eq('rep_declaration_star')
32
32
  expect(decls.subnodes).to be_empty
33
33
  expect(eof).to be_kind_of(Rley::PTree::TerminalNode)
34
34
  expect(eof.symbol.name).to eq('EOF')
@@ -76,9 +76,9 @@ LOX_END
76
76
  expect(root.symbol.name).to eq('program')
77
77
  (decls, eof) = root.subnodes
78
78
  expect(decls).to be_kind_of(Rley::PTree::NonTerminalNode)
79
- expect(decls.symbol.name).to eq('declaration_star')
79
+ expect(decls.symbol.name).to eq('rep_declaration_star')
80
80
  expect(decls.subnodes[0]).to be_kind_of(Rley::PTree::NonTerminalNode)
81
- expect(decls.subnodes[0].symbol.name).to eq('declaration_star')
81
+ expect(decls.subnodes[0].symbol.name).to eq('rep_declaration_star')
82
82
  expect(decls.subnodes[1]).to be_kind_of(Rley::PTree::NonTerminalNode)
83
83
  expect(decls.subnodes[1].symbol.name).to eq('declaration')
84
84
  statement = decls.subnodes[1].subnodes[0]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: loxxy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.05
4
+ version: 0.4.08
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitri Geshef
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-10 00:00:00.000000000 Z
11
+ date: 2022-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rley
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.8.06
19
+ version: 0.8.08
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.8.06
26
+ version: 0.8.08
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -170,7 +170,7 @@ require_paths:
170
170
  - lib
171
171
  required_ruby_version: !ruby/object:Gem::Requirement
172
172
  requirements:
173
- - - "~>"
173
+ - - ">="
174
174
  - !ruby/object:Gem::Version
175
175
  version: '2.5'
176
176
  required_rubygems_version: !ruby/object:Gem::Requirement
@@ -179,7 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
181
  requirements: []
182
- rubygems_version: 3.1.4
182
+ rubygems_version: 3.3.3
183
183
  signing_key:
184
184
  specification_version: 4
185
185
  summary: An implementation of the Lox programming language.