jruby-prism-parser 0.23.0.pre.SNAPSHOT-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +401 -0
  3. data/CODE_OF_CONDUCT.md +76 -0
  4. data/CONTRIBUTING.md +62 -0
  5. data/LICENSE.md +7 -0
  6. data/Makefile +101 -0
  7. data/README.md +98 -0
  8. data/config.yml +2902 -0
  9. data/docs/build_system.md +91 -0
  10. data/docs/configuration.md +64 -0
  11. data/docs/cruby_compilation.md +27 -0
  12. data/docs/design.md +53 -0
  13. data/docs/encoding.md +121 -0
  14. data/docs/fuzzing.md +88 -0
  15. data/docs/heredocs.md +36 -0
  16. data/docs/javascript.md +118 -0
  17. data/docs/local_variable_depth.md +229 -0
  18. data/docs/mapping.md +117 -0
  19. data/docs/parser_translation.md +34 -0
  20. data/docs/parsing_rules.md +19 -0
  21. data/docs/releasing.md +98 -0
  22. data/docs/ripper.md +36 -0
  23. data/docs/ruby_api.md +43 -0
  24. data/docs/ruby_parser_translation.md +19 -0
  25. data/docs/serialization.md +209 -0
  26. data/docs/testing.md +55 -0
  27. data/ext/prism/api_node.c +5098 -0
  28. data/ext/prism/api_pack.c +267 -0
  29. data/ext/prism/extconf.rb +110 -0
  30. data/ext/prism/extension.c +1155 -0
  31. data/ext/prism/extension.h +18 -0
  32. data/include/prism/ast.h +5807 -0
  33. data/include/prism/defines.h +102 -0
  34. data/include/prism/diagnostic.h +339 -0
  35. data/include/prism/encoding.h +265 -0
  36. data/include/prism/node.h +57 -0
  37. data/include/prism/options.h +230 -0
  38. data/include/prism/pack.h +152 -0
  39. data/include/prism/parser.h +732 -0
  40. data/include/prism/prettyprint.h +26 -0
  41. data/include/prism/regexp.h +33 -0
  42. data/include/prism/util/pm_buffer.h +155 -0
  43. data/include/prism/util/pm_char.h +205 -0
  44. data/include/prism/util/pm_constant_pool.h +209 -0
  45. data/include/prism/util/pm_list.h +97 -0
  46. data/include/prism/util/pm_memchr.h +29 -0
  47. data/include/prism/util/pm_newline_list.h +93 -0
  48. data/include/prism/util/pm_state_stack.h +42 -0
  49. data/include/prism/util/pm_string.h +150 -0
  50. data/include/prism/util/pm_string_list.h +44 -0
  51. data/include/prism/util/pm_strncasecmp.h +32 -0
  52. data/include/prism/util/pm_strpbrk.h +46 -0
  53. data/include/prism/version.h +29 -0
  54. data/include/prism.h +289 -0
  55. data/jruby-prism.jar +0 -0
  56. data/lib/prism/compiler.rb +486 -0
  57. data/lib/prism/debug.rb +206 -0
  58. data/lib/prism/desugar_compiler.rb +207 -0
  59. data/lib/prism/dispatcher.rb +2150 -0
  60. data/lib/prism/dot_visitor.rb +4634 -0
  61. data/lib/prism/dsl.rb +785 -0
  62. data/lib/prism/ffi.rb +346 -0
  63. data/lib/prism/lex_compat.rb +908 -0
  64. data/lib/prism/mutation_compiler.rb +753 -0
  65. data/lib/prism/node.rb +17864 -0
  66. data/lib/prism/node_ext.rb +212 -0
  67. data/lib/prism/node_inspector.rb +68 -0
  68. data/lib/prism/pack.rb +224 -0
  69. data/lib/prism/parse_result/comments.rb +177 -0
  70. data/lib/prism/parse_result/newlines.rb +64 -0
  71. data/lib/prism/parse_result.rb +498 -0
  72. data/lib/prism/pattern.rb +250 -0
  73. data/lib/prism/serialize.rb +1354 -0
  74. data/lib/prism/translation/parser/compiler.rb +1838 -0
  75. data/lib/prism/translation/parser/lexer.rb +335 -0
  76. data/lib/prism/translation/parser/rubocop.rb +37 -0
  77. data/lib/prism/translation/parser.rb +178 -0
  78. data/lib/prism/translation/ripper.rb +577 -0
  79. data/lib/prism/translation/ruby_parser.rb +1521 -0
  80. data/lib/prism/translation.rb +11 -0
  81. data/lib/prism/version.rb +3 -0
  82. data/lib/prism/visitor.rb +495 -0
  83. data/lib/prism.rb +99 -0
  84. data/prism.gemspec +135 -0
  85. data/rbi/prism.rbi +7767 -0
  86. data/rbi/prism_static.rbi +207 -0
  87. data/sig/prism.rbs +4773 -0
  88. data/sig/prism_static.rbs +201 -0
  89. data/src/diagnostic.c +400 -0
  90. data/src/encoding.c +5132 -0
  91. data/src/node.c +2786 -0
  92. data/src/options.c +213 -0
  93. data/src/pack.c +493 -0
  94. data/src/prettyprint.c +8881 -0
  95. data/src/prism.c +18406 -0
  96. data/src/regexp.c +638 -0
  97. data/src/serialize.c +1554 -0
  98. data/src/token_type.c +700 -0
  99. data/src/util/pm_buffer.c +190 -0
  100. data/src/util/pm_char.c +318 -0
  101. data/src/util/pm_constant_pool.c +322 -0
  102. data/src/util/pm_list.c +49 -0
  103. data/src/util/pm_memchr.c +35 -0
  104. data/src/util/pm_newline_list.c +84 -0
  105. data/src/util/pm_state_stack.c +25 -0
  106. data/src/util/pm_string.c +203 -0
  107. data/src/util/pm_string_list.c +28 -0
  108. data/src/util/pm_strncasecmp.c +24 -0
  109. data/src/util/pm_strpbrk.c +180 -0
  110. metadata +156 -0
@@ -0,0 +1,250 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Prism
4
+ # A pattern is an object that wraps a Ruby pattern matching expression. The
5
+ # expression would normally be passed to an `in` clause within a `case`
6
+ # expression or a rightward assignment expression. For example, in the
7
+ # following snippet:
8
+ #
9
+ # case node
10
+ # in ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]]
11
+ # end
12
+ #
13
+ # the pattern is the <tt>ConstantPathNode[...]</tt> expression.
14
+ #
15
+ # The pattern gets compiled into an object that responds to #call by running
16
+ # the #compile method. This method itself will run back through Prism to
17
+ # parse the expression into a tree, then walk the tree to generate the
18
+ # necessary callable objects. For example, if you wanted to compile the
19
+ # expression above into a callable, you would:
20
+ #
21
+ # callable = Prism::Pattern.new("ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]]").compile
22
+ # callable.call(node)
23
+ #
24
+ # The callable object returned by #compile is guaranteed to respond to #call
25
+ # with a single argument, which is the node to match against. It also is
26
+ # guaranteed to respond to #===, which means it itself can be used in a `case`
27
+ # expression, as in:
28
+ #
29
+ # case node
30
+ # when callable
31
+ # end
32
+ #
33
+ # If the query given to the initializer cannot be compiled into a valid
34
+ # matcher (either because of a syntax error or because it is using syntax we
35
+ # do not yet support) then a Prism::Pattern::CompilationError will be
36
+ # raised.
37
+ class Pattern
38
+ # Raised when the query given to a pattern is either invalid Ruby syntax or
39
+ # is using syntax that we don't yet support.
40
+ class CompilationError < StandardError
41
+ # Create a new CompilationError with the given representation of the node
42
+ # that caused the error.
43
+ def initialize(repr)
44
+ super(<<~ERROR)
45
+ prism was unable to compile the pattern you provided into a usable
46
+ expression. It failed on to understand the node represented by:
47
+
48
+ #{repr}
49
+
50
+ Note that not all syntax supported by Ruby's pattern matching syntax
51
+ is also supported by prism's patterns. If you're using some syntax
52
+ that you believe should be supported, please open an issue on
53
+ GitHub at https://github.com/ruby/prism/issues/new.
54
+ ERROR
55
+ end
56
+ end
57
+
58
+ # The query that this pattern was initialized with.
59
+ attr_reader :query
60
+
61
+ # Create a new pattern with the given query. The query should be a string
62
+ # containing a Ruby pattern matching expression.
63
+ def initialize(query)
64
+ @query = query
65
+ @compiled = nil
66
+ end
67
+
68
+ # Compile the query into a callable object that can be used to match against
69
+ # nodes.
70
+ def compile
71
+ result = Prism.parse("case nil\nin #{query}\nend")
72
+ compile_node(result.value.statements.body.last.conditions.last.pattern)
73
+ end
74
+
75
+ # Scan the given node and all of its children for nodes that match the
76
+ # pattern. If a block is given, it will be called with each node that
77
+ # matches the pattern. If no block is given, an enumerator will be returned
78
+ # that will yield each node that matches the pattern.
79
+ def scan(root)
80
+ return to_enum(__method__, root) unless block_given?
81
+
82
+ @compiled ||= compile
83
+ queue = [root]
84
+
85
+ while (node = queue.shift)
86
+ yield node if @compiled.call(node)
87
+ queue.concat(node.compact_child_nodes)
88
+ end
89
+ end
90
+
91
+ private
92
+
93
+ # Shortcut for combining two procs into one that returns true if both return
94
+ # true.
95
+ def combine_and(left, right)
96
+ ->(other) { left.call(other) && right.call(other) }
97
+ end
98
+
99
+ # Shortcut for combining two procs into one that returns true if either
100
+ # returns true.
101
+ def combine_or(left, right)
102
+ ->(other) { left.call(other) || right.call(other) }
103
+ end
104
+
105
+ # Raise an error because the given node is not supported.
106
+ def compile_error(node)
107
+ raise CompilationError, node.inspect
108
+ end
109
+
110
+ # in [foo, bar, baz]
111
+ def compile_array_pattern_node(node)
112
+ compile_error(node) if !node.rest.nil? || node.posts.any?
113
+
114
+ constant = node.constant
115
+ compiled_constant = compile_node(constant) if constant
116
+
117
+ preprocessed = node.requireds.map { |required| compile_node(required) }
118
+
119
+ compiled_requireds = ->(other) do
120
+ deconstructed = other.deconstruct
121
+
122
+ deconstructed.length == preprocessed.length &&
123
+ preprocessed
124
+ .zip(deconstructed)
125
+ .all? { |(matcher, value)| matcher.call(value) }
126
+ end
127
+
128
+ if compiled_constant
129
+ combine_and(compiled_constant, compiled_requireds)
130
+ else
131
+ compiled_requireds
132
+ end
133
+ end
134
+
135
+ # in foo | bar
136
+ def compile_alternation_pattern_node(node)
137
+ combine_or(compile_node(node.left), compile_node(node.right))
138
+ end
139
+
140
+ # in Prism::ConstantReadNode
141
+ def compile_constant_path_node(node)
142
+ parent = node.parent
143
+
144
+ if parent.is_a?(ConstantReadNode) && parent.slice == "Prism"
145
+ compile_node(node.child)
146
+ else
147
+ compile_error(node)
148
+ end
149
+ end
150
+
151
+ # in ConstantReadNode
152
+ # in String
153
+ def compile_constant_read_node(node)
154
+ value = node.slice
155
+
156
+ if Prism.const_defined?(value, false)
157
+ clazz = Prism.const_get(value)
158
+
159
+ ->(other) { clazz === other }
160
+ elsif Object.const_defined?(value, false)
161
+ clazz = Object.const_get(value)
162
+
163
+ ->(other) { clazz === other }
164
+ else
165
+ compile_error(node)
166
+ end
167
+ end
168
+
169
+ # in InstanceVariableReadNode[name: Symbol]
170
+ # in { name: Symbol }
171
+ def compile_hash_pattern_node(node)
172
+ compile_error(node) if node.rest
173
+ compiled_constant = compile_node(node.constant) if node.constant
174
+
175
+ preprocessed =
176
+ node.elements.to_h do |element|
177
+ [element.key.unescaped.to_sym, compile_node(element.value)]
178
+ end
179
+
180
+ compiled_keywords = ->(other) do
181
+ deconstructed = other.deconstruct_keys(preprocessed.keys)
182
+
183
+ preprocessed.all? do |keyword, matcher|
184
+ deconstructed.key?(keyword) && matcher.call(deconstructed[keyword])
185
+ end
186
+ end
187
+
188
+ if compiled_constant
189
+ combine_and(compiled_constant, compiled_keywords)
190
+ else
191
+ compiled_keywords
192
+ end
193
+ end
194
+
195
+ # in nil
196
+ def compile_nil_node(node)
197
+ ->(attribute) { attribute.nil? }
198
+ end
199
+
200
+ # in /foo/
201
+ def compile_regular_expression_node(node)
202
+ regexp = Regexp.new(node.unescaped, node.closing[1..])
203
+
204
+ ->(attribute) { regexp === attribute }
205
+ end
206
+
207
+ # in ""
208
+ # in "foo"
209
+ def compile_string_node(node)
210
+ string = node.unescaped
211
+
212
+ ->(attribute) { string === attribute }
213
+ end
214
+
215
+ # in :+
216
+ # in :foo
217
+ def compile_symbol_node(node)
218
+ symbol = node.unescaped.to_sym
219
+
220
+ ->(attribute) { symbol === attribute }
221
+ end
222
+
223
+ # Compile any kind of node. Dispatch out to the individual compilation
224
+ # methods based on the type of node.
225
+ def compile_node(node)
226
+ case node
227
+ when AlternationPatternNode
228
+ compile_alternation_pattern_node(node)
229
+ when ArrayPatternNode
230
+ compile_array_pattern_node(node)
231
+ when ConstantPathNode
232
+ compile_constant_path_node(node)
233
+ when ConstantReadNode
234
+ compile_constant_read_node(node)
235
+ when HashPatternNode
236
+ compile_hash_pattern_node(node)
237
+ when NilNode
238
+ compile_nil_node(node)
239
+ when RegularExpressionNode
240
+ compile_regular_expression_node(node)
241
+ when StringNode
242
+ compile_string_node(node)
243
+ when SymbolNode
244
+ compile_symbol_node(node)
245
+ else
246
+ compile_error(node)
247
+ end
248
+ end
249
+ end
250
+ end