swift-ast-dump-parser 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: dc8754e58b54b5563e95e3f2abaa81782823aa1f
4
+ data.tar.gz: fb0ea24daf5b73f6b32be241bd33ea62e391d5be
5
+ SHA512:
6
+ metadata.gz: 3def18d0b3d524c6879bf0d29c6d3e58ce4811b3069abe1c0054b0ac3b5691d951e0e314c6afe70106458c6ceb4f98b862f8dad863536d31ed4796737f722cd8
7
+ data.tar.gz: 91b56fbe416abaf10ad8029b57c45ed7530975766cb6bc96c7b1e662843019cea4ddb3faa144fa450d5d127ab4e5070e477982db5c632ec0eadc7b32172c96cf
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require 'swift_ast_dump_parser'
5
+
6
+ ast_path = ARGV[0]
7
+ @tree = SwiftAST::Parser.new().parse_build_log_output(File.read(ast_path))
8
+ @tree.dump
@@ -0,0 +1,225 @@
1
+ module SwiftAST
2
+ autoload :StringScanner, 'strscan'
3
+ class Parser
4
+ def parse(string)
5
+ @scanner = StringScanner.new(string)
6
+ node = scan_children.first
7
+ node
8
+ end
9
+
10
+
11
+ def parse_build_log_output(string)
12
+ @scanner = StringScanner.new(string)
13
+ return unless @scanner.scan_until(/^\(source_file/)
14
+ unscan("(source_file")
15
+ children = scan_children
16
+
17
+ return if children.empty?
18
+ Node.new("ast", [], children)
19
+ end
20
+
21
+
22
+ def scan_parameters
23
+ parameters = []
24
+
25
+ while true
26
+ @scanner.skip(/\s*/)
27
+ parameter = scan_parameter?
28
+ break unless parameter
29
+ parameters << parameter
30
+ end
31
+
32
+ parameters
33
+ end
34
+
35
+ def scan_parameters_from_types
36
+ first_param = @scanner.scan(/\d+:/)
37
+ return [] unless first_param
38
+ return [first_param] + scan_parameters
39
+ end
40
+
41
+ def scan_children(level = 0)
42
+ children = []
43
+ while true
44
+ return children unless whitespaces = whitespaces_at(level)
45
+ node_name = scan_name?
46
+ return children if node_name == "source_file" && level != 0 && unscan(node_name + whitespaces)
47
+ node_parameters = scan_parameters
48
+
49
+ node_children = scan_children(level + 1)
50
+
51
+ while next_params = scan_parameters_from_types # these are stupid params alike
52
+ break if next_params.empty?
53
+ node_parameters += next_params
54
+ node_children += scan_children(level + 1)
55
+ end
56
+ node = Node.new(node_name, node_parameters, node_children)
57
+
58
+ children << node
59
+ @scanner.scan(/(\s|\\|\n|\r|\t)*\)[\w\s]*/)
60
+ end
61
+ children
62
+ end
63
+
64
+ def whitespaces_at(level = 0)
65
+ whitespaces = @scanner.scan(/(\s|\\|\n|\r|\t)*\(/)
66
+ if level == 0 && whitespaces.nil?
67
+ whitespaces = @scanner.scan(/.*?\(source_file/m)
68
+ return nil unless whitespaces
69
+ unscan("source_file")
70
+ end
71
+ whitespaces
72
+ end
73
+
74
+ def unscan(string)
75
+ @scanner.pos = @scanner.pos - string.length
76
+ end
77
+
78
+ def scan_name?
79
+ el_name = @scanner.scan(/#?[\w:]+/)
80
+ el_name
81
+ end
82
+
83
+ def scan_parameter?(is_parsing_rvalue = false)
84
+ #white spaces are skipped
85
+
86
+ # scan everything until space or opening sequence like ( < ' ".
87
+ # Since we can end up with closing bracket - we alos check for )
88
+
89
+ prefix = @scanner.scan(/[^\s()'"\[\\]+/) if is_parsing_rvalue
90
+ prefix = @scanner.scan(/[^\s()<'"\[\\=]+/) unless is_parsing_rvalue
91
+
92
+ next_char = @scanner.peek(1)
93
+ return nil unless next_char
94
+ should_unwrap_strings = !is_parsing_rvalue && !prefix
95
+
96
+ case next_char
97
+ when " " # next parameter
98
+ result = prefix
99
+ when "\\" # next parameter
100
+ @scanner.scan(/./)
101
+ result = prefix
102
+
103
+ when "\n" # next parameter
104
+ result = prefix
105
+ when ")" # closing bracket == end of element
106
+ result = prefix
107
+ when "\"" # doube quoted string
108
+ result = @scanner.scan(/./) + @scanner.scan_until(/"/)
109
+ result = result[1..-2] if should_unwrap_strings
110
+ result = (prefix || "") + result
111
+ when "'" # single quoted string
112
+ result = @scanner.scan(/./) + @scanner.scan_until(/'/)
113
+ result = result[1..-2] if should_unwrap_strings
114
+ result = (prefix || "") + result + (scan_parameter?(is_parsing_rvalue) || "")
115
+ when "<" # kinda generic
116
+ result = (prefix || "") + @scanner.scan(/./)
117
+ #in some cases this can be last char, just because we can end up with a=sdsd.function.<
118
+ result += @scanner.scan_until(/>/) + (scan_parameter?(is_parsing_rvalue) || "")
119
+ when "("
120
+ #rare case for enums in type (EnumType).enumValue
121
+ if !prefix && @scanner.check(/\([\w\s\(\)<>,:\]\[\.?]+\)\.\w+/)
122
+ return @scanner.scan(/\([\w\s\(\)<>,:\]\[\.?]+\)\.\w+/)
123
+ end
124
+
125
+ return nil if !prefix && !is_parsing_rvalue
126
+ result = (prefix || "") + @scanner.scan_until(/\)/) + (scan_parameter?(is_parsing_rvalue) || "")
127
+ when "["
128
+ result = (prefix || "") + scan_range + (scan_parameter?(is_parsing_rvalue) || "")
129
+ #rare case for tuple_shuffle_expr [with ([ProductDict], UserDict)]0: ([ProductDict], UserDict)
130
+ if result.start_with?("[with") && result.end_with?("]0:")
131
+ result = result + @scanner.scan_until(/\n/).chomp("\n")
132
+
133
+ end
134
+ when "="
135
+ result = prefix + @scanner.scan(/./) + (scan_parameter?(true) || "")
136
+
137
+ end
138
+
139
+ result
140
+
141
+ end
142
+
143
+ def scan_range
144
+ return unless @scanner.peek(1) == "["
145
+ result = @scanner.scan(/./)
146
+
147
+ while true
148
+ inside = @scanner.scan(/[^\]\[]+/) #everything but [ or ]
149
+ result += inside || ""
150
+ next_char = @scanner.peek(1)
151
+
152
+ return result + @scanner.scan(/./) if next_char == "]" # we found the end
153
+ result += scan_range if next_char == "["
154
+ raise "Unexpected character #{next_char} - [ or ] expected" if next_char != "[" && next_char != "]"
155
+ end
156
+
157
+ end
158
+
159
+ def scan_line_and_column
160
+ @scanner.scan(/:\d+:\d+/)
161
+ end
162
+
163
+ def isalpha(str)
164
+ !str.match(/[^A-Za-z@_]/)
165
+ end
166
+ def isAlphaDigit(str)
167
+ !str.match(/[^A-Za-z@_0-9]/)
168
+ end
169
+ def isalphaOrDot(str)
170
+ !str.match(/[^A-Za-z@_.,]/)
171
+ end
172
+
173
+
174
+ end
175
+
176
+ class Node
177
+
178
+ def initialize(name, parameters = [], children = [])
179
+ @name = name
180
+ @parameters = parameters
181
+ @children = children
182
+ end
183
+
184
+ def name
185
+ @name
186
+ end
187
+
188
+ def parameters
189
+ @parameters
190
+ end
191
+
192
+ def children
193
+ @children
194
+ end
195
+
196
+ def dump(level = 0)
197
+ @@line = 0 if level == 0
198
+ puts "\n" if level == 0
199
+ puts " " * level + "[#{@@line}][#{@name} #{@parameters}"
200
+ @@line = @@line + 1
201
+ @children.each { |child| child.dump(level + 1) }
202
+ end
203
+
204
+ def find_nodes(type)
205
+ found_nodes = []
206
+ @children.each { |child|
207
+ if child.name == type
208
+ found_nodes << child
209
+ else
210
+ found_nodes += child.find_nodes(type)
211
+ end
212
+ }
213
+ found_nodes
214
+ end
215
+
216
+ def on_node(type, &block)
217
+ @children.each { |child|
218
+ yield child if child.name == type
219
+ child.on_node(type, &block)
220
+ }
221
+ end
222
+
223
+ end
224
+
225
+ end
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: swift-ast-dump-parser
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Paul Taykalo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-11-12 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: |2
14
+ Tool that allows to build AST tree representation from the swift's AST dump
15
+ swift-ast-dump-parser <ast-file>
16
+ email: tt.kilew@gmail.com
17
+ executables:
18
+ - swift-ast-dump-parser
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - bin/swift-ast-dump-parser
23
+ - lib/swift_ast_dump_parser.rb
24
+ homepage: https://github.com/PaulTaykalo/swift-ast-dump-parser.git
25
+ licenses:
26
+ - MIT
27
+ metadata: {}
28
+ post_install_message:
29
+ rdoc_options: []
30
+ require_paths:
31
+ - lib
32
+ required_ruby_version: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ required_rubygems_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ requirements: []
43
+ rubyforge_project:
44
+ rubygems_version: 2.6.10
45
+ signing_key:
46
+ specification_version: 4
47
+ summary: Swift AST dump parser
48
+ test_files: []