Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 0c5ebad

Browse files
committed
Support even more syntax
1 parent 78eea51 commit 0c5ebad

File tree

2 files changed

+49
-9
lines changed

2 files changed

+49
-9
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
/vendor/
1010

1111
test.rb
12+
query.txt

lib/syntax_tree/search.rb

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,37 @@ def scan(root)
2929

3030
private
3131

32+
def combine_and(left, right)
33+
->(node) { left.call(node) && right.call(node) }
34+
end
35+
36+
def combine_or(left, right)
37+
->(node) { left.call(node) || right.call(node) }
38+
end
39+
3240
def compile(pattern)
3341
case pattern
34-
in Binary[left:, operator: :|, right:]
35-
compiled_left = compile(left)
36-
compiled_right = compile(right)
42+
in AryPtn[constant:, requireds:, rest: nil, posts: []]
43+
compiled_constant = compile(constant) if constant
44+
45+
preprocessed = requireds.map { |required| compile(required) }
3746

38-
->(node) { compiled_left.call(node) || compiled_right.call(node) }
47+
compiled_requireds = ->(node) do
48+
deconstructed = node.deconstruct
49+
50+
deconstructed.length == preprocessed.length &&
51+
preprocessed.zip(deconstructed).all? do |(matcher, value)|
52+
matcher.call(value)
53+
end
54+
end
55+
56+
if compiled_constant
57+
combine_and(compiled_constant, compiled_requireds)
58+
else
59+
compiled_requireds
60+
end
61+
in Binary[left:, operator: :|, right:]
62+
combine_or(compile(left), compile_right)
3963
in Const[value:] if SyntaxTree.const_defined?(value)
4064
clazz = SyntaxTree.const_get(value)
4165

@@ -46,33 +70,48 @@ def compile(pattern)
4670
->(node) { node.is_a?(clazz) }
4771
in ConstPathRef[parent: VarRef[value: Const[value: "SyntaxTree"]]]
4872
compile(pattern.constant)
73+
in DynaSymbol[parts: [TStringContent[value:]]]
74+
symbol = value.to_sym
75+
76+
->(attribute) { attribute == value }
4977
in HshPtn[constant:, keywords:, keyword_rest: nil]
5078
compiled_constant = compile(constant)
5179

52-
preprocessed_keywords =
80+
preprocessed =
5381
keywords.to_h do |keyword, value|
5482
raise NoMatchingPatternError unless keyword.is_a?(Label)
5583
[keyword.value.chomp(":").to_sym, compile(value)]
5684
end
5785

5886
compiled_keywords = ->(node) do
59-
deconstructed = node.deconstruct_keys(preprocessed_keywords.keys)
60-
preprocessed_keywords.all? do |keyword, matcher|
87+
deconstructed = node.deconstruct_keys(preprocessed.keys)
88+
89+
preprocessed.all? do |keyword, matcher|
6190
matcher.call(deconstructed[keyword])
6291
end
6392
end
6493

65-
->(node) do
66-
compiled_constant.call(node) && compiled_keywords.call(node)
94+
if compiled_constant
95+
combine_and(compiled_constant, compiled_keywords)
96+
else
97+
compiled_keywords
6798
end
6899
in RegexpLiteral[parts: [TStringContent[value:]]]
69100
regexp = /#{value}/
70101

71102
->(attribute) { regexp.match?(attribute) }
103+
in StringLiteral[parts: []]
104+
->(attribute) { attribute == "" }
72105
in StringLiteral[parts: [TStringContent[value:]]]
73106
->(attribute) { attribute == value }
107+
in SymbolLiteral[value:]
108+
symbol = value.value.to_sym
109+
110+
->(attribute) { attribute == symbol }
74111
in VarRef[value: Const => value]
75112
compile(value)
113+
in VarRef[value: Kw[value: "nil"]]
114+
->(attribute) { attribute.nil? }
76115
end
77116
rescue NoMatchingPatternError
78117
raise UncompilableError, <<~ERROR

0 commit comments

Comments
 (0)