class Prism::Pattern
Ein Muster ist ein Objekt, das einen Ruby-Mustervergleichsausdruck umschließt. Der Ausdruck würde normalerweise an eine in-Klausel innerhalb eines case-Ausdrucks oder eines nachgestellten Zuweisungsausdrucks übergeben. Zum Beispiel im folgenden Ausschnitt
case node in ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]] end
ist das Muster der Ausdruck ConstantPathNode[...].
Das Muster wird in ein Objekt kompiliert, das durch Ausführen der Methode compile auf Aufrufe reagiert. Diese Methode selbst läuft zurück durch Prism, um den Ausdruck in einen Baum zu parsen, und durchläuft dann den Baum, um die notwendigen aufrufbaren Objekte zu generieren. Wenn Sie beispielsweise den obigen Ausdruck in ein aufrufbares Objekt kompilieren möchten, würden Sie
callable = Prism::Pattern.new("ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]]").compile callable.call(node)
Das von compile zurückgegebene aufrufbare Objekt reagiert garantiert auf Aufrufe mit einem einzigen Argument, das der zu vergleichende Knoten ist. Es reagiert auch garantiert auf ===, was bedeutet, dass es selbst in einem case-Ausdruck verwendet werden kann, wie in
case node when callable end
Wenn die an den Initialisierer übergebene Abfrage nicht in einen gültigen Übereinstimmungsprozess kompiliert werden kann (entweder aufgrund eines Syntaxfehlers oder weil sie eine Syntax verwendet, die wir noch nicht unterstützen), wird eine Prism::Pattern::CompilationError ausgelöst.
Attribute
Die Abfrage, mit der dieses Muster initialisiert wurde.
Öffentliche Klassenmethoden
Source
# File lib/prism/pattern.rb, line 64 def initialize(query) @query = query @compiled = nil end
Erzeugt ein neues Muster mit der angegebenen Abfrage. Die Abfrage sollte ein String sein, der einen Ruby-Mustervergleichsausdruck enthält.
Öffentliche Instanzmethoden
Source
# File lib/prism/pattern.rb, line 71 def compile result = Prism.parse("case nil\nin #{query}\nend") case_match_node = result.value.statements.body.last raise CompilationError, case_match_node.inspect unless case_match_node.is_a?(CaseMatchNode) in_node = case_match_node.conditions.last raise CompilationError, in_node.inspect unless in_node.is_a?(InNode) compile_node(in_node.pattern) end
Kompiliert die Abfrage in ein aufrufbares Objekt, das zum Abgleichen von Knoten verwendet werden kann.
Source
# File lib/prism/pattern.rb, line 87 def scan(root) return to_enum(:scan, root) unless block_given? @compiled ||= compile queue = [root] while (node = queue.shift) yield node if @compiled.call(node) # steep:ignore queue.concat(node.compact_child_nodes) end end
Durchsucht den angegebenen Knoten und alle seine Kinder nach Knoten, die dem Muster entsprechen. Wenn ein Block übergeben wird, wird er mit jedem Knoten aufgerufen, der dem Muster entspricht. Wenn kein Block übergeben wird, wird ein Enumerator zurückgegeben, der jeden Knoten liefert, der dem Muster entspricht.
Private Instanzmethoden
Source
# File lib/prism/pattern.rb, line 103 def combine_and(left, right) ->(other) { left.call(other) && right.call(other) } end
Abkürzung zum Kombinieren zweier Procs zu einem, der wahr zurückgibt, wenn beide wahr zurückgeben.
Source
# File lib/prism/pattern.rb, line 109 def combine_or(left, right) ->(other) { left.call(other) || right.call(other) } end
Abkürzung zum Kombinieren zweier Procs zu einem, der wahr zurückgibt, wenn einer von beiden wahr zurückgibt.
Source
# File lib/prism/pattern.rb, line 144 def compile_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 119 def compile_array_pattern_node(node) compile_error(node) if !node.rest.nil? || node.posts.any? constant = node.constant compiled_constant = compile_node(constant) if constant preprocessed = node.requireds.map { |required| compile_node(required) } compiled_requireds = ->(other) do deconstructed = other.deconstruct deconstructed.length == preprocessed.length && preprocessed .zip(deconstructed) .all? { |(matcher, value)| matcher.call(value) } end if compiled_constant combine_and(compiled_constant, compiled_requireds) else compiled_requireds end end
in [foo, bar, baz]
Source
# File lib/prism/pattern.rb, line 169 def compile_constant_name(node, name) if Prism.const_defined?(name, false) clazz = Prism.const_get(name) ->(other) { clazz === other } elsif Object.const_defined?(name, false) clazz = Object.const_get(name) ->(other) { clazz === other } else compile_error(node) end end
Kompiliert einen Namen, der mit einer Konstante verbunden ist.
Source
# File lib/prism/pattern.rb, line 149 def compile_constant_path_node(node) parent = node.parent if parent.is_a?(ConstantReadNode) && parent.slice == "Prism" name = node.name raise CompilationError, node.inspect if name.nil? compile_constant_name(node, name) else compile_error(node) end end
Source
# File lib/prism/pattern.rb, line 164 def compile_constant_read_node(node) compile_constant_name(node, node.name) end
in ConstantReadNode in String
Source
# File lib/prism/pattern.rb, line 114 def compile_error(node) raise CompilationError, node.inspect end
Löst einen Fehler aus, da der angegebene Knoten nicht unterstützt wird.
Source
# File lib/prism/pattern.rb, line 185 def compile_hash_pattern_node(node) compile_error(node) if node.rest compiled_constant = compile_node(node.constant) if node.constant preprocessed = node.elements.to_h do |element| key = element.key if key.is_a?(SymbolNode) [key.unescaped.to_sym, compile_node(element.value)] else raise CompilationError, element.inspect end end compiled_keywords = ->(other) do deconstructed = other.deconstruct_keys(preprocessed.keys) preprocessed.all? do |keyword, matcher| deconstructed.key?(keyword) && matcher.call(deconstructed[keyword]) end end if compiled_constant combine_and(compiled_constant, compiled_keywords) else compiled_keywords end end
in InstanceVariableReadNode[name: Symbol] in { name: Symbol }
Source
# File lib/prism/pattern.rb, line 215 def compile_nil_node(node) ->(attribute) { attribute.nil? } end
in nil
Source
# File lib/prism/pattern.rb, line 244 def compile_node(node) case node when AlternationPatternNode compile_alternation_pattern_node(node) when ArrayPatternNode compile_array_pattern_node(node) when ConstantPathNode compile_constant_path_node(node) when ConstantReadNode compile_constant_read_node(node) when HashPatternNode compile_hash_pattern_node(node) when NilNode compile_nil_node(node) when RegularExpressionNode compile_regular_expression_node(node) when StringNode compile_string_node(node) when SymbolNode compile_symbol_node(node) else compile_error(node) end end
Kompiliert jeden Arten von Knoten. Leitet basierend auf dem Knotentyp zu den einzelnen Kompilierungsmethoden weiter.
Source
# File lib/prism/pattern.rb, line 220 def compile_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 228 def compile_string_node(node) string = node.unescaped ->(attribute) { string === attribute } end
in “” in “foo”
Source
# File lib/prism/pattern.rb, line 236 def compile_symbol_node(node) symbol = node.unescaped.to_sym ->(attribute) { symbol === attribute } end
in :+ in :foo