-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauto_bash.rb
More file actions
153 lines (126 loc) · 3.14 KB
/
auto_bash.rb
File metadata and controls
153 lines (126 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/usr/bin/env ruby
# frozen_string_literal: true
# Example: Auto Backend Selection with Bash
#
# Demonstrates parsing Bash shell scripts with tree-sitter-bash.
require "bundler/inline"
gemfile do
source "https://gem.coop"
gem "tree_haver", path: File.expand_path("..", __dir__)
gem "ffi" # FFI backend - most portable
end
require "tree_haver"
puts "=" * 70
puts "TreeHaver Auto Backend - Bash Parsing"
puts "=" * 70
puts
# Bash script example
bash_source = <<~BASH
#!/bin/bash
# Function to greet user
greet() {
local name="$1"
echo "Hello, $name!"
}
# Main script
if [ -n "$USER" ]; then
greet "$USER"
else
echo "User not found"
exit 1
fi
# Loop example
for i in {1..3}; do
echo "Iteration $i"
done
BASH
puts "Bash Source:"
puts "-" * 70
puts bash_source
puts
# Register Bash grammar
puts "Registering Bash grammar..."
finder = TreeHaver::GrammarFinder.new(:bash)
if finder.available?
finder.register!
puts "✓ Registered from: #{finder.find_library_path}"
else
puts "✗ tree-sitter-bash not found"
puts finder.not_found_message
exit 1
end
puts
backend = TreeHaver.backend_module
puts "Backend: #{backend}"
puts
# Parse Bash
parser = TreeHaver::Parser.new
parser.language = TreeHaver::Language.bash
tree = parser.parse(bash_source)
puts "✓ Parsed successfully"
puts
# Explore AST
root = tree.root_node
puts "Root: #{root.type} with #{root.child_count} children"
puts
# Row number validation
puts "=== Row Number Validation ==="
row_errors = []
i = 0
root.each do |child|
start_row = child.start_point.row
end_row = child.end_point.row
puts "Node #{i}: #{child.type} (rows #{start_row}-#{end_row})"
# For multiline script, nodes should NOT all be on row 0
if i > 2 && start_row == 0 && child.type.to_s != "comment"
row_errors << "Node #{i} (#{child.type}) has start_row=0, expected different row"
end
i += 1
end
puts
if row_errors.empty?
puts "✓ Row numbers look correct!"
else
puts "✗ Row number issues detected:"
row_errors.each { |err| puts " - #{err}" }
exit 1
end
puts
# Find functions
def find_functions(node, results = [])
results << node if node.type == "function_definition"
node.children.each { |child| find_functions(child, results) }
results
end
functions = find_functions(root)
puts "Functions Found: #{functions.count}"
functions.each do |func|
puts " • #{func.text.lines.first.strip}"
end
puts
# Find if statements
def find_if_statements(node, results = [])
results << node if node.type == "if_statement"
node.children.each { |child| find_if_statements(child, results) }
results
end
ifs = find_if_statements(root)
puts "If Statements: #{ifs.count}"
puts
# Find loops
def find_loops(node, results = [])
results << node if ["for_statement", "while_statement"].include?(node.type)
node.children.each { |child| find_loops(child, results) }
results
end
loops = find_loops(root)
puts "Loops Found: #{loops.count}"
puts
puts "=" * 70
puts "Bash Parsing Use Cases:"
puts " • Shell script analysis"
puts " • CI/CD script validation"
puts " • Documentation generation"
puts " • Security auditing"
puts " • Code refactoring tools"
puts "=" * 70