Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit02b3c49

Browse files
committed
Documentation for search
1 parentbfa8c39 commit02b3c49

File tree

3 files changed

+56
-22
lines changed

3 files changed

+56
-22
lines changed

‎README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ It is built with only standard library dependencies. It additionally ships with
1515
-[CLI](#cli)
1616
-[ast](#ast)
1717
-[check](#check)
18+
-[expr](#expr)
1819
-[format](#format)
1920
-[json](#json)
2021
-[match](#match)
@@ -26,6 +27,7 @@ It is built with only standard library dependencies. It additionally ships with
2627
-[SyntaxTree.read(filepath)](#syntaxtreereadfilepath)
2728
-[SyntaxTree.parse(source)](#syntaxtreeparsesource)
2829
-[SyntaxTree.format(source)](#syntaxtreeformatsource)
30+
-[SyntaxTree.search(source, query, &block)](#syntaxtreesearchsource-query-block)
2931
-[Nodes](#nodes)
3032
-[child_nodes](#child_nodes)
3133
-[Pattern matching](#pattern-matching)
@@ -129,6 +131,24 @@ To change the print width that you are checking against, specify the `--print-wi
129131
stree check --print-width=100 path/to/file.rb
130132
```
131133

134+
###expr
135+
136+
This command will output a Ruby case-match expression that would match correctly against the first expression of the input.
137+
138+
```sh
139+
stree expr path/to/file.rb
140+
```
141+
142+
For a file that contains`1 + 1`, you will receive:
143+
144+
```ruby
145+
SyntaxTree::Binary[
146+
left:SyntaxTree::Int[value:"1"],
147+
operator::+,
148+
right:SyntaxTree::Int[value:"1"]
149+
]
150+
```
151+
132152
###format
133153

134154
This command will output the formatted version of each of the listed files. Importantly, it will not write that content back to the source files. It is meant to display the formatted version only.
@@ -312,6 +332,10 @@ This function takes an input string containing Ruby code and returns the syntax
312332

313333
This function takes an input string containing Ruby code, parses it into its underlying syntax tree, and formats it back out to a string. You can optionally pass a second argument to this method as well that is the maximum width to print. It defaults to`80`.
314334

335+
###SyntaxTree.search(source, query, &block)
336+
337+
This function takes an input string containing Ruby code, an input string containing a valid Ruby`in` clause expression that can be used to match against nodes in the tree (can be generated using`stree expr`,`stree match`, or`Node#construct_keys`), and a block. Each node that matches the given query will be yielded to the block. The block will receive the node as its only argument.
338+
315339
##Nodes
316340

317341
There are many different node types in the syntax tree. They are meant to be treated as immutable structs containing links to child nodes with minimal logic contained within their implementation. However, for the most part they all respond to a certain set of APIs, listed below.

‎lib/syntax_tree.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,10 @@ def self.read(filepath)
7575

7676
File.read(filepath,encoding:encoding)
7777
end
78+
79+
# Searches through the given source using the given pattern and yields each
80+
# node in the tree that matches the pattern to the given block.
81+
defself.search(source,query, &block)
82+
Search.new(Pattern.new(query).compile).scan(parse(source), &block)
83+
end
7884
end

‎lib/syntax_tree/pattern.rb

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ module SyntaxTree
3737
# do not yet support) then a SyntaxTree::Pattern::CompilationError will be
3838
# raised.
3939
classPattern
40+
# Raised when the query given to a pattern is either invalid Ruby syntax or
41+
# is using syntax that we don't yet support.
4042
classCompilationError <StandardError
4143
definitialize(repr)
4244
super(<<~ERROR)
@@ -76,27 +78,27 @@ def compile
7678
defcombine_and(left,right)
7779
->(node){left.call(node) &&right.call(node)}
7880
end
79-
81+
8082
defcombine_or(left,right)
8183
->(node){left.call(node) ||right.call(node)}
8284
end
8385

84-
defcompile_node(node)
85-
casenode
86+
defcompile_node(root)
87+
caseroot
8688
inAryPtn[constant:,requireds:,rest:nil,posts:[]]
8789
compiled_constant=compile_node(constant)ifconstant
88-
90+
8991
preprocessed=requireds.map{ |required|compile_node(required)}
90-
92+
9193
compiled_requireds=->(node)do
9294
deconstructed=node.deconstruct
93-
95+
9496
deconstructed.length ==preprocessed.length &&
95-
preprocessed.zip(deconstructed).all?do |(matcher,value)|
96-
matcher.call(value)
97-
end
97+
preprocessed
98+
.zip(deconstructed)
99+
.all?{ |(matcher,value)|matcher.call(value)}
98100
end
99-
101+
100102
ifcompiled_constant
101103
combine_and(compiled_constant,compiled_requireds)
102104
else
@@ -106,63 +108,65 @@ def compile_node(node)
106108
combine_or(compile_node(left),compile_node(right))
107109
inConst[value:]ifSyntaxTree.const_defined?(value)
108110
clazz=SyntaxTree.const_get(value)
109-
111+
110112
->(node){node.is_a?(clazz)}
111113
inConst[value:]ifObject.const_defined?(value)
112114
clazz=Object.const_get(value)
113-
115+
114116
->(node){node.is_a?(clazz)}
115-
inConstPathRef[parent:VarRef[value:Const[value:"SyntaxTree"]],constant:]
117+
inConstPathRef[
118+
parent:VarRef[value:Const[value:"SyntaxTree"]],constant:
119+
]
116120
compile_node(constant)
117121
inDynaSymbol[parts:[]]
118-
symbol="".to_sym
122+
symbol=:""
119123

120124
->(node){node ==symbol}
121125
inDynaSymbol[parts:[TStringContent[value:]]]
122126
symbol=value.to_sym
123-
127+
124128
->(attribute){attribute ==value}
125129
inHshPtn[constant:,keywords:,keyword_rest:nil]
126130
compiled_constant=compile_node(constant)
127-
131+
128132
preprocessed=
129133
keywords.to_hdo |keyword,value|
130134
raiseNoMatchingPatternErrorunlesskeyword.is_a?(Label)
131135
[keyword.value.chomp(":").to_sym,compile_node(value)]
132136
end
133-
137+
134138
compiled_keywords=->(node)do
135139
deconstructed=node.deconstruct_keys(preprocessed.keys)
136-
140+
137141
preprocessed.all?do |keyword,matcher|
138142
matcher.call(deconstructed[keyword])
139143
end
140144
end
141-
145+
142146
ifcompiled_constant
143147
combine_and(compiled_constant,compiled_keywords)
144148
else
145149
compiled_keywords
146150
end
147151
inRegexpLiteral[parts:[TStringContent[value:]]]
148152
regexp=/#{value}/
149-
153+
150154
->(attribute){regexp.match?(attribute)}
151155
inStringLiteral[parts:[]]
152156
->(attribute){attribute ==""}
153157
inStringLiteral[parts:[TStringContent[value:]]]
154158
->(attribute){attribute ==value}
155159
inSymbolLiteral[value:]
156160
symbol=value.value.to_sym
157-
161+
158162
->(attribute){attribute ==symbol}
159163
inVarRef[value:Const=>value]
160164
compile_node(value)
161165
inVarRef[value:Kw[value:"nil"]]
162166
->(attribute){attribute.nil?}
163167
end
164168
rescueNoMatchingPatternError
165-
raiseCompilationError,PP.pp(node, +"").chomp
169+
raiseCompilationError,PP.pp(root, +"").chomp
166170
end
167171
end
168172
end

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp