class Prism::Pattern
A pattern is an object that wraps a Ruby pattern matching expression. The expression would normally be passed to anin clause within acase expression or a rightward assignment expression. For example, in the following snippet:
casenodeinConstantPathNode[ConstantReadNode[name::Prism],ConstantReadNode[name::Pattern]]end
the pattern is theConstantPathNode[...] expression.
The pattern gets compiled into an object that responds to call by running thecompile method. This method itself will run back throughPrism to parse the expression into a tree, then walk the tree to generate the necessary callable objects. For example, if you wanted to compile the expression above into a callable, you would:
callable =Prism::Pattern.new("ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]]").compilecallable.call(node)
The callable object returned bycompile is guaranteed to respond to call with a single argument, which is the node to match against. It also is guaranteed to respond to===, which means it itself can be used in acase expression, as in:
casenodewhencallableend
If the query given to the initializer cannot be compiled into a valid matcher (either because of a syntax error or because it is using syntax we do not yet support) then aPrism::Pattern::CompilationError will be raised.
Attributes
The query that this pattern was initialized with.
Public Class Methods
Source
# File lib/prism/pattern.rb, line 64definitialize(query)@query =query@compiled =nilend
Create a new pattern with the given query. The query should be a string containing a Ruby pattern matching expression.
Public Instance Methods
Source
# File lib/prism/pattern.rb, line 71defcompileresult =Prism.parse("case nil\nin #{query}\nend")case_match_node =result.value.statements.body.lastraiseCompilationError,case_match_node.inspectunlesscase_match_node.is_a?(CaseMatchNode)in_node =case_match_node.conditions.lastraiseCompilationError,in_node.inspectunlessin_node.is_a?(InNode)compile_node(in_node.pattern)end
Compile the query into a callable object that can be used to match against nodes.
Source
# File lib/prism/pattern.rb, line 87defscan(root)returnto_enum(:scan,root)unlessblock_given?@compiled||=compilequeue = [root]while (node =queue.shift)yieldnodeif@compiled.call(node)# steep:ignorequeue.concat(node.compact_child_nodes)endend
Scan the given node and all of its children for nodes that match the pattern. If a block is given, it will be called with each node that matches the pattern. If no block is given, an enumerator will be returned that will yield each node that matches the pattern.
Private Instance Methods
Source
# File lib/prism/pattern.rb, line 103defcombine_and(left,right)->(other) {left.call(other)&&right.call(other) }end
Shortcut for combining two procs into one that returns true if both return true.
Source
# File lib/prism/pattern.rb, line 109defcombine_or(left,right)->(other) {left.call(other)||right.call(other) }end
Shortcut for combining two procs into one that returns true if either returns true.
Source
# File lib/prism/pattern.rb, line 144defcompile_alternation_pattern_node(node)combine_or(compile_node(node.left),compile_node(node.right))end
in foo | bar
Source
# File lib/prism/pattern.rb, line 119defcompile_array_pattern_node(node)compile_error(node)if!node.rest.nil?||node.posts.any?constant =node.constantcompiled_constant =compile_node(constant)ifconstantpreprocessed =node.requireds.map {|required|compile_node(required) }compiled_requireds =->(other)dodeconstructed =other.deconstructdeconstructed.length==preprocessed.length&&preprocessed .zip(deconstructed) .all? {|(matcher,value)|matcher.call(value) }endifcompiled_constantcombine_and(compiled_constant,compiled_requireds)elsecompiled_requiredsendend
in [foo, bar, baz]
Source
# File lib/prism/pattern.rb, line 169defcompile_constant_name(node,name)ifPrism.const_defined?(name,false)clazz =Prism.const_get(name)->(other) {clazz===other }elsifObject.const_defined?(name,false)clazz =Object.const_get(name)->(other) {clazz===other }elsecompile_error(node)endend
Compile a name associated with a constant.
Source
# File lib/prism/pattern.rb, line 149defcompile_constant_path_node(node)parent =node.parentifparent.is_a?(ConstantReadNode)&&parent.slice=="Prism"name =node.nameraiseCompilationError,node.inspectifname.nil?compile_constant_name(node,name)elsecompile_error(node)endend
Source
# File lib/prism/pattern.rb, line 164defcompile_constant_read_node(node)compile_constant_name(node,node.name)end
Source
# File lib/prism/pattern.rb, line 114defcompile_error(node)raiseCompilationError,node.inspectend
Raise an error because the given node is not supported.
Source
# File lib/prism/pattern.rb, line 185defcompile_hash_pattern_node(node)compile_error(node)ifnode.restcompiled_constant =compile_node(node.constant)ifnode.constantpreprocessed =node.elements.to_hdo|element|key =element.keyifkey.is_a?(SymbolNode) [key.unescaped.to_sym,compile_node(element.value)]elseraiseCompilationError,element.inspectendendcompiled_keywords =->(other)dodeconstructed =other.deconstruct_keys(preprocessed.keys)preprocessed.all?do|keyword,matcher|deconstructed.key?(keyword)&&matcher.call(deconstructed[keyword])endendifcompiled_constantcombine_and(compiled_constant,compiled_keywords)elsecompiled_keywordsendend
in InstanceVariableReadNode[name: Symbol] in { name:Symbol }
Source
# File lib/prism/pattern.rb, line 215defcompile_nil_node(node)->(attribute) {attribute.nil? }end
in nil
Source
# File lib/prism/pattern.rb, line 244defcompile_node(node)casenodewhenAlternationPatternNodecompile_alternation_pattern_node(node)whenArrayPatternNodecompile_array_pattern_node(node)whenConstantPathNodecompile_constant_path_node(node)whenConstantReadNodecompile_constant_read_node(node)whenHashPatternNodecompile_hash_pattern_node(node)whenNilNodecompile_nil_node(node)whenRegularExpressionNodecompile_regular_expression_node(node)whenStringNodecompile_string_node(node)whenSymbolNodecompile_symbol_node(node)elsecompile_error(node)endend
Compile any kind of node. Dispatch out to the individual compilation methods based on the type of node.
Source
# File lib/prism/pattern.rb, line 220defcompile_regular_expression_node(node)regexp =Regexp.new(node.unescaped,node.closing[1..])->(attribute) {regexp===attribute }end
in /foo/
Source
# File lib/prism/pattern.rb, line 228defcompile_string_node(node)string =node.unescaped->(attribute) {string===attribute }end
in “” in “foo”
Source
# File lib/prism/pattern.rb, line 236defcompile_symbol_node(node)symbol =node.unescaped.to_sym->(attribute) {symbol===attribute }end
in :+ in :foo