yarp 0.12.0 → 0.13.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 (115) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -8
  3. data/CONTRIBUTING.md +2 -2
  4. data/Makefile +5 -5
  5. data/README.md +11 -12
  6. data/config.yml +6 -2
  7. data/docs/build_system.md +21 -21
  8. data/docs/building.md +4 -4
  9. data/docs/configuration.md +25 -21
  10. data/docs/design.md +2 -2
  11. data/docs/encoding.md +17 -17
  12. data/docs/fuzzing.md +4 -4
  13. data/docs/heredocs.md +3 -3
  14. data/docs/mapping.md +94 -94
  15. data/docs/ripper.md +4 -4
  16. data/docs/ruby_api.md +11 -11
  17. data/docs/serialization.md +17 -16
  18. data/docs/testing.md +6 -6
  19. data/ext/prism/api_node.c +4725 -0
  20. data/ext/{yarp → prism}/api_pack.c +82 -82
  21. data/ext/{yarp → prism}/extconf.rb +13 -13
  22. data/ext/{yarp → prism}/extension.c +175 -168
  23. data/ext/prism/extension.h +18 -0
  24. data/include/prism/ast.h +1932 -0
  25. data/include/prism/defines.h +45 -0
  26. data/include/prism/diagnostic.h +231 -0
  27. data/include/{yarp/enc/yp_encoding.h → prism/enc/pm_encoding.h} +40 -40
  28. data/include/prism/node.h +41 -0
  29. data/include/prism/pack.h +141 -0
  30. data/include/{yarp → prism}/parser.h +143 -142
  31. data/include/prism/regexp.h +19 -0
  32. data/include/prism/unescape.h +48 -0
  33. data/include/prism/util/pm_buffer.h +51 -0
  34. data/include/{yarp/util/yp_char.h → prism/util/pm_char.h} +20 -20
  35. data/include/{yarp/util/yp_constant_pool.h → prism/util/pm_constant_pool.h} +26 -22
  36. data/include/{yarp/util/yp_list.h → prism/util/pm_list.h} +21 -21
  37. data/include/prism/util/pm_memchr.h +14 -0
  38. data/include/{yarp/util/yp_newline_list.h → prism/util/pm_newline_list.h} +11 -11
  39. data/include/prism/util/pm_state_stack.h +24 -0
  40. data/include/{yarp/util/yp_string.h → prism/util/pm_string.h} +20 -20
  41. data/include/prism/util/pm_string_list.h +25 -0
  42. data/include/{yarp/util/yp_strpbrk.h → prism/util/pm_strpbrk.h} +7 -7
  43. data/include/prism/version.h +4 -0
  44. data/include/prism.h +82 -0
  45. data/lib/prism/compiler.rb +465 -0
  46. data/lib/prism/debug.rb +157 -0
  47. data/lib/{yarp/desugar_visitor.rb → prism/desugar_compiler.rb} +4 -2
  48. data/lib/prism/dispatcher.rb +2051 -0
  49. data/lib/prism/dsl.rb +750 -0
  50. data/lib/{yarp → prism}/ffi.rb +66 -67
  51. data/lib/{yarp → prism}/lex_compat.rb +40 -43
  52. data/lib/{yarp/mutation_visitor.rb → prism/mutation_compiler.rb} +3 -3
  53. data/lib/{yarp → prism}/node.rb +2012 -2593
  54. data/lib/prism/node_ext.rb +55 -0
  55. data/lib/prism/node_inspector.rb +68 -0
  56. data/lib/{yarp → prism}/pack.rb +1 -1
  57. data/lib/{yarp → prism}/parse_result/comments.rb +1 -1
  58. data/lib/{yarp → prism}/parse_result/newlines.rb +1 -1
  59. data/lib/prism/parse_result.rb +266 -0
  60. data/lib/{yarp → prism}/pattern.rb +14 -14
  61. data/lib/{yarp → prism}/ripper_compat.rb +5 -5
  62. data/lib/{yarp → prism}/serialize.rb +12 -7
  63. data/lib/prism/visitor.rb +470 -0
  64. data/lib/prism.rb +64 -0
  65. data/lib/yarp.rb +2 -614
  66. data/src/diagnostic.c +213 -208
  67. data/src/enc/pm_big5.c +52 -0
  68. data/src/enc/pm_euc_jp.c +58 -0
  69. data/src/enc/{yp_gbk.c → pm_gbk.c} +16 -16
  70. data/src/enc/pm_shift_jis.c +56 -0
  71. data/src/enc/{yp_tables.c → pm_tables.c} +69 -69
  72. data/src/enc/{yp_unicode.c → pm_unicode.c} +40 -40
  73. data/src/enc/pm_windows_31j.c +56 -0
  74. data/src/node.c +1293 -1233
  75. data/src/pack.c +247 -247
  76. data/src/prettyprint.c +1479 -1479
  77. data/src/{yarp.c → prism.c} +5205 -5083
  78. data/src/regexp.c +132 -132
  79. data/src/serialize.c +1121 -1121
  80. data/src/token_type.c +169 -167
  81. data/src/unescape.c +106 -87
  82. data/src/util/pm_buffer.c +103 -0
  83. data/src/util/{yp_char.c → pm_char.c} +72 -72
  84. data/src/util/{yp_constant_pool.c → pm_constant_pool.c} +85 -64
  85. data/src/util/{yp_list.c → pm_list.c} +10 -10
  86. data/src/util/{yp_memchr.c → pm_memchr.c} +6 -4
  87. data/src/util/{yp_newline_list.c → pm_newline_list.c} +21 -21
  88. data/src/util/{yp_state_stack.c → pm_state_stack.c} +4 -4
  89. data/src/util/{yp_string.c → pm_string.c} +38 -38
  90. data/src/util/pm_string_list.c +29 -0
  91. data/src/util/{yp_strncasecmp.c → pm_strncasecmp.c} +1 -1
  92. data/src/util/{yp_strpbrk.c → pm_strpbrk.c} +8 -8
  93. data/yarp.gemspec +68 -59
  94. metadata +70 -61
  95. data/ext/yarp/api_node.c +0 -4728
  96. data/ext/yarp/extension.h +0 -18
  97. data/include/yarp/ast.h +0 -1929
  98. data/include/yarp/defines.h +0 -45
  99. data/include/yarp/diagnostic.h +0 -226
  100. data/include/yarp/node.h +0 -42
  101. data/include/yarp/pack.h +0 -141
  102. data/include/yarp/regexp.h +0 -19
  103. data/include/yarp/unescape.h +0 -44
  104. data/include/yarp/util/yp_buffer.h +0 -51
  105. data/include/yarp/util/yp_memchr.h +0 -14
  106. data/include/yarp/util/yp_state_stack.h +0 -24
  107. data/include/yarp/util/yp_string_list.h +0 -25
  108. data/include/yarp/version.h +0 -4
  109. data/include/yarp.h +0 -82
  110. data/src/enc/yp_big5.c +0 -52
  111. data/src/enc/yp_euc_jp.c +0 -58
  112. data/src/enc/yp_shift_jis.c +0 -56
  113. data/src/enc/yp_windows_31j.c +0 -56
  114. data/src/util/yp_buffer.c +0 -101
  115. data/src/util/yp_string_list.c +0 -29
data/lib/yarp.rb CHANGED
@@ -1,616 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module YARP
4
- # This represents a source of Ruby code that has been parsed. It is used in
5
- # conjunction with locations to allow them to resolve line numbers and source
6
- # ranges.
7
- class Source
8
- attr_reader :source, :offsets
9
-
10
- def initialize(source, offsets = compute_offsets(source))
11
- @source = source
12
- @offsets = offsets
13
- end
14
-
15
- def slice(offset, length)
16
- source.byteslice(offset, length)
17
- end
18
-
19
- def line(value)
20
- offsets.bsearch_index { |offset| offset > value } || offsets.length
21
- end
22
-
23
- def line_offset(value)
24
- offsets[line(value) - 1]
25
- end
26
-
27
- def column(value)
28
- value - offsets[line(value) - 1]
29
- end
30
-
31
- private
32
-
33
- def compute_offsets(code)
34
- offsets = [0]
35
- code.b.scan("\n") { offsets << $~.end(0) }
36
- offsets
37
- end
38
- end
39
-
40
- # This represents a location in the source.
41
- class Location
42
- # A Source object that is used to determine more information from the given
43
- # offset and length.
44
- protected attr_reader :source
45
-
46
- # The byte offset from the beginning of the source where this location
47
- # starts.
48
- attr_reader :start_offset
49
-
50
- # The length of this location in bytes.
51
- attr_reader :length
52
-
53
- # The list of comments attached to this location
54
- attr_reader :comments
55
-
56
- def initialize(source, start_offset, length)
57
- @source = source
58
- @start_offset = start_offset
59
- @length = length
60
- @comments = []
61
- end
62
-
63
- # Create a new location object with the given options.
64
- def copy(**options)
65
- Location.new(
66
- options.fetch(:source) { source },
67
- options.fetch(:start_offset) { start_offset },
68
- options.fetch(:length) { length }
69
- )
70
- end
71
-
72
- # Returns a string representation of this location.
73
- def inspect
74
- "#<YARP::Location @start_offset=#{@start_offset} @length=#{@length}>"
75
- end
76
-
77
- # The source code that this location represents.
78
- def slice
79
- source.slice(start_offset, length)
80
- end
81
-
82
- # The byte offset from the beginning of the source where this location ends.
83
- def end_offset
84
- start_offset + length
85
- end
86
-
87
- # The line number where this location starts.
88
- def start_line
89
- source.line(start_offset)
90
- end
91
-
92
- # The content of the line where this location starts before this location.
93
- def start_line_slice
94
- offset = source.line_offset(start_offset)
95
- source.slice(offset, start_offset - offset)
96
- end
97
-
98
- # The line number where this location ends.
99
- def end_line
100
- source.line(end_offset - 1)
101
- end
102
-
103
- # The column number in bytes where this location starts from the start of
104
- # the line.
105
- def start_column
106
- source.column(start_offset)
107
- end
108
-
109
- # The column number in bytes where this location ends from the start of the
110
- # line.
111
- def end_column
112
- source.column(end_offset)
113
- end
114
-
115
- def deconstruct_keys(keys)
116
- { start_offset: start_offset, end_offset: end_offset }
117
- end
118
-
119
- def pretty_print(q)
120
- q.text("(#{start_offset}...#{end_offset})")
121
- end
122
-
123
- def ==(other)
124
- other.is_a?(Location) &&
125
- other.start_offset == start_offset &&
126
- other.end_offset == end_offset
127
- end
128
-
129
- # Returns a new location that stretches from this location to the given
130
- # other location. Raises an error if this location is not before the other
131
- # location or if they don't share the same source.
132
- def join(other)
133
- raise "Incompatible sources" if source != other.source
134
- raise "Incompatible locations" if start_offset > other.start_offset
135
-
136
- Location.new(source, start_offset, other.end_offset - start_offset)
137
- end
138
-
139
- def self.null
140
- new(0, 0)
141
- end
142
- end
143
-
144
- # This represents a comment that was encountered during parsing.
145
- class Comment
146
- TYPES = [:inline, :embdoc, :__END__]
147
-
148
- attr_reader :type, :location
149
-
150
- def initialize(type, location)
151
- @type = type
152
- @location = location
153
- end
154
-
155
- def deconstruct_keys(keys)
156
- { type: type, location: location }
157
- end
158
-
159
- # Returns true if the comment happens on the same line as other code and false if the comment is by itself
160
- def trailing?
161
- type == :inline && !location.start_line_slice.strip.empty?
162
- end
163
-
164
- def inspect
165
- "#<YARP::Comment @type=#{@type.inspect} @location=#{@location.inspect}>"
166
- end
167
- end
168
-
169
- # This represents an error that was encountered during parsing.
170
- class ParseError
171
- attr_reader :message, :location
172
-
173
- def initialize(message, location)
174
- @message = message
175
- @location = location
176
- end
177
-
178
- def deconstruct_keys(keys)
179
- { message: message, location: location }
180
- end
181
-
182
- def inspect
183
- "#<YARP::ParseError @message=#{@message.inspect} @location=#{@location.inspect}>"
184
- end
185
- end
186
-
187
- # This represents a warning that was encountered during parsing.
188
- class ParseWarning
189
- attr_reader :message, :location
190
-
191
- def initialize(message, location)
192
- @message = message
193
- @location = location
194
- end
195
-
196
- def deconstruct_keys(keys)
197
- { message: message, location: location }
198
- end
199
-
200
- def inspect
201
- "#<YARP::ParseWarning @message=#{@message.inspect} @location=#{@location.inspect}>"
202
- end
203
- end
204
-
205
- # A class that knows how to walk down the tree. None of the individual visit
206
- # methods are implemented on this visitor, so it forces the consumer to
207
- # implement each one that they need. For a default implementation that
208
- # continues walking the tree, see the Visitor class.
209
- class BasicVisitor
210
- def visit(node)
211
- node&.accept(self)
212
- end
213
-
214
- def visit_all(nodes)
215
- nodes.map { |node| visit(node) }
216
- end
217
-
218
- def visit_child_nodes(node)
219
- visit_all(node.child_nodes)
220
- end
221
- end
222
-
223
- class Visitor < BasicVisitor
224
- end
225
-
226
- # This represents the result of a call to ::parse or ::parse_file. It contains
227
- # the AST, any comments that were encounters, and any errors that were
228
- # encountered.
229
- class ParseResult
230
- attr_reader :value, :comments, :errors, :warnings, :source
231
-
232
- def initialize(value, comments, errors, warnings, source)
233
- @value = value
234
- @comments = comments
235
- @errors = errors
236
- @warnings = warnings
237
- @source = source
238
- end
239
-
240
- def deconstruct_keys(keys)
241
- { value: value, comments: comments, errors: errors, warnings: warnings }
242
- end
243
-
244
- def success?
245
- errors.empty?
246
- end
247
-
248
- def failure?
249
- !success?
250
- end
251
- end
252
-
253
- # This represents a token from the Ruby source.
254
- class Token
255
- attr_reader :type, :value, :location
256
-
257
- def initialize(type, value, location)
258
- @type = type
259
- @value = value
260
- @location = location
261
- end
262
-
263
- def deconstruct_keys(keys)
264
- { type: type, value: value, location: location }
265
- end
266
-
267
- def pretty_print(q)
268
- q.group do
269
- q.text(type.to_s)
270
- self.location.pretty_print(q)
271
- q.text("(")
272
- q.nest(2) do
273
- q.breakable("")
274
- q.pp(value)
275
- end
276
- q.breakable("")
277
- q.text(")")
278
- end
279
- end
280
-
281
- def ==(other)
282
- other.is_a?(Token) &&
283
- other.type == type &&
284
- other.value == value
285
- end
286
- end
287
-
288
- # This represents a node in the tree.
289
- class Node
290
- attr_reader :location
291
-
292
- def newline?
293
- @newline ? true : false
294
- end
295
-
296
- def set_newline_flag(newline_marked)
297
- line = location.start_line
298
- unless newline_marked[line]
299
- newline_marked[line] = true
300
- @newline = true
301
- end
302
- end
303
-
304
- # Slice the location of the node from the source.
305
- def slice
306
- location.slice
307
- end
308
-
309
- def pretty_print(q)
310
- q.text(inspect.chomp)
311
- end
312
- end
313
-
314
- # This object is responsible for generating the output for the inspect method
315
- # implementations of child nodes.
316
- class NodeInspector
317
- attr_reader :prefix, :output
318
-
319
- def initialize(prefix = "")
320
- @prefix = prefix
321
- @output = +""
322
- end
323
-
324
- # Appends a line to the output with the current prefix.
325
- def <<(line)
326
- output << "#{prefix}#{line}"
327
- end
328
-
329
- # This generates a string that is used as the header of the inspect output
330
- # for any given node.
331
- def header(node)
332
- output = +"@ #{node.class.name.split("::").last} ("
333
- output << "location: (#{node.location.start_offset}...#{node.location.end_offset})"
334
- output << ", newline: true" if node.newline?
335
- output << ")\n"
336
- output
337
- end
338
-
339
- # Generates a string that represents a list of nodes. It handles properly
340
- # using the box drawing characters to make the output look nice.
341
- def list(prefix, nodes)
342
- output = +"(length: #{nodes.length})\n"
343
- last_index = nodes.length - 1
344
-
345
- nodes.each_with_index do |node, index|
346
- pointer, preadd = (index == last_index) ? ["└── ", " "] : ["├── ", "│ "]
347
- node_prefix = "#{prefix}#{preadd}"
348
- output << node.inspect(NodeInspector.new(node_prefix)).sub(node_prefix, "#{prefix}#{pointer}")
349
- end
350
-
351
- output
352
- end
353
-
354
- # Generates a string that represents a location field on a node.
355
- def location(value)
356
- if value
357
- "(#{value.start_offset}...#{value.end_offset}) = #{value.slice.inspect}"
358
- else
359
- "∅"
360
- end
361
- end
362
-
363
- # Generates a string that represents a child node.
364
- def child_node(node, append)
365
- node.inspect(child_inspector(append)).delete_prefix(prefix)
366
- end
367
-
368
- # Returns a new inspector that can be used to inspect a child node.
369
- def child_inspector(append)
370
- NodeInspector.new("#{prefix}#{append}")
371
- end
372
-
373
- # Returns the output as a string.
374
- def to_str
375
- output
376
- end
377
- end
378
-
379
- # Load the serialized AST using the source as a reference into a tree.
380
- def self.load(source, serialized)
381
- Serialize.load(source, serialized)
382
- end
383
-
384
- # This module is used for testing and debugging and is not meant to be used by
385
- # consumers of this library.
386
- module Debug
387
- class ISeq
388
- attr_reader :parts
389
-
390
- def initialize(parts)
391
- @parts = parts
392
- end
393
-
394
- def type
395
- parts[0]
396
- end
397
-
398
- def local_table
399
- parts[10]
400
- end
401
-
402
- def instructions
403
- parts[13]
404
- end
405
-
406
- def each_child
407
- instructions.each do |instruction|
408
- # Only look at arrays. Other instructions are line numbers or
409
- # tracepoint events.
410
- next unless instruction.is_a?(Array)
411
-
412
- instruction.each do |opnd|
413
- # Only look at arrays. Other operands are literals.
414
- next unless opnd.is_a?(Array)
415
-
416
- # Only look at instruction sequences. Other operands are literals.
417
- next unless opnd[0] == "YARVInstructionSequence/SimpleDataFormat"
418
-
419
- yield ISeq.new(opnd)
420
- end
421
- end
422
- end
423
- end
424
-
425
- # For the given source, compiles with CRuby and returns a list of all of the
426
- # sets of local variables that were encountered.
427
- def self.cruby_locals(source)
428
- verbose = $VERBOSE
429
- $VERBOSE = nil
430
-
431
- begin
432
- locals = []
433
- stack = [ISeq.new(RubyVM::InstructionSequence.compile(source).to_a)]
434
-
435
- while (iseq = stack.pop)
436
- if iseq.type != :once
437
- names = iseq.local_table
438
-
439
- # CRuby will push on a special local variable when there are keyword
440
- # arguments. We get rid of that here.
441
- names = names.grep_v(Integer)
442
-
443
- # For some reason, CRuby occasionally pushes this special local
444
- # variable when there are splat arguments. We get rid of that here.
445
- names = names.grep_v(:"#arg_rest")
446
-
447
- # Now push them onto the list of locals.
448
- locals << names
449
- end
450
-
451
- iseq.each_child { |child| stack << child }
452
- end
453
-
454
- locals
455
- ensure
456
- $VERBOSE = verbose
457
- end
458
- end
459
-
460
- # For the given source, parses with YARP and returns a list of all of the
461
- # sets of local variables that were encountered.
462
- def self.yarp_locals(source)
463
- locals = []
464
- stack = [YARP.parse(source).value]
465
-
466
- while (node = stack.pop)
467
- case node
468
- when BlockNode, DefNode, LambdaNode
469
- names = node.locals
470
-
471
- params = node.parameters
472
- params = params&.parameters unless node.is_a?(DefNode)
473
-
474
- # YARP places parameters in the same order that they appear in the
475
- # source. CRuby places them in the order that they need to appear
476
- # according to their own internal calling convention. We mimic that
477
- # order here so that we can compare properly.
478
- if params
479
- sorted = [
480
- *params.requireds.grep(RequiredParameterNode).map(&:name),
481
- *params.optionals.map(&:name),
482
- *((params.rest.name || :*) if params.rest && params.rest.operator != ","),
483
- *params.posts.grep(RequiredParameterNode).map(&:name),
484
- *params.keywords.reject(&:value).map(&:name),
485
- *params.keywords.select(&:value).map(&:name)
486
- ]
487
-
488
- # TODO: When we get a ... parameter, we should be pushing * and &
489
- # onto the local list. We don't do that yet, so we need to add them
490
- # in here.
491
- if params.keyword_rest.is_a?(ForwardingParameterNode)
492
- sorted.push(:*, :&, :"...")
493
- end
494
-
495
- # Recurse down the parameter tree to find any destructured
496
- # parameters and add them after the other parameters.
497
- param_stack = params.requireds.concat(params.posts).grep(RequiredDestructuredParameterNode).reverse
498
- while (param = param_stack.pop)
499
- case param
500
- when RequiredDestructuredParameterNode
501
- param_stack.concat(param.parameters.reverse)
502
- when RequiredParameterNode
503
- sorted << param.name
504
- when SplatNode
505
- sorted << param.expression.name if param.expression
506
- end
507
- end
508
-
509
- names = sorted.concat(names - sorted)
510
- end
511
-
512
- locals << names
513
- when ClassNode, ModuleNode, ProgramNode, SingletonClassNode
514
- locals << node.locals
515
- when ForNode
516
- locals << []
517
- when PostExecutionNode
518
- locals.push([], [])
519
- when InterpolatedRegularExpressionNode
520
- locals << [] if node.once?
521
- end
522
-
523
- stack.concat(node.child_nodes.compact)
524
- end
525
-
526
- locals
527
- end
528
-
529
- def self.newlines(source)
530
- YARP.parse(source).source.offsets
531
- end
532
-
533
- def self.parse_serialize_file(filepath)
534
- parse_serialize_file_metadata(filepath, [filepath.bytesize, filepath.b, 0].pack("LA*L"))
535
- end
536
- end
537
-
538
- # Marking this as private so that consumers don't see it. It makes it a little
539
- # annoying for testing since you have to const_get it to access the methods,
540
- # but at least this way it's clear it's not meant for consumers.
541
- private_constant :Debug
542
- end
543
-
544
- require_relative "yarp/lex_compat"
545
- require_relative "yarp/mutation_visitor"
546
- require_relative "yarp/desugar_visitor"
547
- require_relative "yarp/node"
548
- require_relative "yarp/ripper_compat"
549
- require_relative "yarp/serialize"
550
- require_relative "yarp/pack"
551
- require_relative "yarp/pattern"
552
-
553
- require_relative "yarp/parse_result/comments"
554
- require_relative "yarp/parse_result/newlines"
555
-
556
- if RUBY_ENGINE == "ruby" and !ENV["YARP_FFI_BACKEND"]
557
- require "yarp/yarp"
558
- else
559
- require_relative "yarp/ffi"
560
- end
561
-
562
- # Reopening the YARP module after yarp/node is required so that constant
563
- # reflection APIs will find the constants defined in the node file before these.
564
- # This block is meant to contain extra APIs we define on YARP nodes that aren't
565
- # templated and are meant as convenience methods.
566
- module YARP
567
- class FloatNode < Node
568
- # Returns the value of the node as a Ruby Float.
569
- def value
570
- Float(slice)
571
- end
572
- end
573
-
574
- class ImaginaryNode < Node
575
- # Returns the value of the node as a Ruby Complex.
576
- def value
577
- Complex(0, numeric.value)
578
- end
579
- end
580
-
581
- class IntegerNode < Node
582
- # Returns the value of the node as a Ruby Integer.
583
- def value
584
- Integer(slice)
585
- end
586
- end
587
-
588
- class InterpolatedRegularExpressionNode < Node
589
- # Returns a numeric value that represents the flags that were used to create
590
- # the regular expression.
591
- def options
592
- o = flags & 0b111
593
- o |= Regexp::FIXEDENCODING if flags.anybits?(RegularExpressionFlags::EUC_JP | RegularExpressionFlags::WINDOWS_31J | RegularExpressionFlags::UTF_8)
594
- o |= Regexp::NOENCODING if flags.anybits?(RegularExpressionFlags::ASCII_8BIT)
595
- o
596
- end
597
- end
598
-
599
- class RationalNode < Node
600
- # Returns the value of the node as a Ruby Rational.
601
- def value
602
- Rational(slice.chomp("r"))
603
- end
604
- end
605
-
606
- class RegularExpressionNode < Node
607
- # Returns a numeric value that represents the flags that were used to create
608
- # the regular expression.
609
- def options
610
- o = flags & 0b111
611
- o |= Regexp::FIXEDENCODING if flags.anybits?(RegularExpressionFlags::EUC_JP | RegularExpressionFlags::WINDOWS_31J | RegularExpressionFlags::UTF_8)
612
- o |= Regexp::NOENCODING if flags.anybits?(RegularExpressionFlags::ASCII_8BIT)
613
- o
614
- end
615
- end
616
- end
3
+ require "prism"
4
+ YARP = Prism