vorax 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,7 +12,7 @@ action end_identifier {
12
12
  @end = p - 1
13
13
  }
14
14
 
15
- terminator = (';' ws*) | (ws+ (K_AS | K_IS) ws+);
15
+ terminator = (';' ws*) | (ws+ (K_AS | K_IS | K_DECLARE) ws+);
16
16
  id = identifier >start_identifier %end_identifier;
17
17
  variable_name = id - (K_CURSOR | K_TYPE | K_FUNCTION | K_PROCEDURE | K_END | K_PRAGMA);
18
18
 
@@ -8,7 +8,7 @@ module Vorax
8
8
 
9
9
  class Region
10
10
 
11
- attr_accessor :start_pos, :end_pos
11
+ attr_accessor :start_pos, :end_pos, :body_start_pos
12
12
  attr_reader :name, :type
13
13
 
14
14
  def initialize(name, type, start_pos = 0, end_pos = 0)
@@ -16,6 +16,7 @@ module Vorax
16
16
  @type = type
17
17
  @start_pos = start_pos
18
18
  @end_pos = end_pos
19
+ @body_start_pos = 0
19
20
  end
20
21
 
21
22
  def to_s
@@ -53,6 +54,7 @@ module Vorax
53
54
  end
54
55
 
55
56
  def tree
57
+ @root.each { |t| t.content.end_pos = @text.length if t.content && t.content.end_pos == 0 }
56
58
  @root
57
59
  end
58
60
 
@@ -106,16 +108,14 @@ module Vorax
106
108
  subprog_type = 'PROCEDURE'
107
109
  end
108
110
  start_pos = scanner.pos - scanner.matched.length
109
- region = Region.new(subprog_name, subprog_type, scanner.pos)
111
+ region = Region.new(subprog_name, subprog_type, start_pos)
110
112
  node = Tree::TreeNode.new(region.to_s, region)
111
113
  @current_parent << node
112
- if @current_parent && @current_parent.content
113
- if @current_parent.content.type != 'SPEC'
114
- @level += 1
115
- assign_parent(node)
116
- else
117
- node.content.end_pos = node.content.start_pos
118
- end
114
+ if @current_parent && @current_parent.content && @current_parent.content.type == 'SPEC'
115
+ node.content.end_pos = node.content.start_pos
116
+ else
117
+ @level += 1
118
+ assign_parent(node)
119
119
  end
120
120
  end
121
121
  end
@@ -126,8 +126,13 @@ module Vorax
126
126
  if @begin_level > 1
127
127
  # start a new region
128
128
  region = Region.new('anonymous', 'BLOCK', scanner.pos)
129
+ region.body_start_pos = scanner.pos - scanner.matched.length
129
130
  @level += 1
130
131
  assign_parent(@current_parent << Tree::TreeNode.new(region.to_s, region))
132
+ else
133
+ if @current_parent && @current_parent.content
134
+ @current_parent.content.body_start_pos = scanner.pos - scanner.matched.length
135
+ end
131
136
  end
132
137
  end
133
138
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Vorax
4
4
 
5
- VERSION = '0.1.4' unless defined?(VERSION)
5
+ VERSION = '0.2.0' unless defined?(VERSION)
6
6
 
7
7
  end
@@ -4,41 +4,57 @@ include Vorax
4
4
 
5
5
  describe 'plsql structure' do
6
6
 
7
- it 'should work for complex plsql code' do
7
+ before(:each) do# {{{
8
+ @result = ""
9
+ end# }}}
10
+
11
+ def compute_tree(node, level = 0)# {{{
12
+ if node.is_root?
13
+ @result << "*"
14
+ else
15
+ @result << "|" unless node.parent.is_last_sibling?
16
+ @result << (' ' * (node.level - 1) * 4)
17
+ @result << (node.is_last_sibling? ? "+" : "|")
18
+ @result << "---"
19
+ @result << (node.has_children? ? "+" : ">")
20
+ end
21
+
22
+ @result << " #{node.name} - #{(node.content ? node.content.end_pos : '')} -> begin=#{(node.content ? node.content.body_start_pos : '')}\n"
23
+
24
+ node.children { |child| compute_tree(child, level + 1)}
25
+ end# }}}
26
+
27
+ it 'should work for complex plsql code' do# {{{
8
28
  text = File.open('spec/sql/test.pkg', 'rb') { |file| file.read }
9
- #text = File.open('spec/sql/admin_toolkit.bdy', 'rb') { |file| file.read }
10
29
  structure = Parser::PlsqlStructure.new(text)
11
- @result = ''
12
- def compute_tree(node, level = 0)
13
- if node.is_root?
14
- @result << "*"
15
- else
16
- @result << "|" unless node.parent.is_last_sibling?
17
- @result << (' ' * (node.level - 1) * 4)
18
- @result << (node.is_last_sibling? ? "+" : "|")
19
- @result << "---"
20
- @result << (node.has_children? ? "+" : ">")
21
- end
22
-
23
- @result << " #{node.name} - #{(node.content ? node.content.end_pos : '')}\n"
24
-
25
- node.children { |child| compute_tree(child, level + 1)}
26
- end
30
+ compute_tree(structure.tree)
31
+ @result.should eq(<<STR
32
+ * root - -> begin=
33
+ |---+ test[SPEC]: 25 - 154 -> begin=0
34
+ | |---> test[PROCEDURE]: 61 - 61 -> begin=0
35
+ | +---> muci[FUNCTION]: 91 - 91 -> begin=0
36
+ +---+ test[BODY]: 180 - 1173 -> begin=1136
37
+ |---+ private_proc[PROCEDURE]: 232 - 874 -> begin=454
38
+ | |---> abc[FUNCTION]: 325 - 392 -> begin=360
39
+ | +---> xyz[PROCEDURE]: 403 - 449 -> begin=424
40
+ |---+ test[PROCEDURE]: 879 - 1045 -> begin=911
41
+ | +---> anonymous[BLOCK]: 967 - 1038 -> begin=962
42
+ +---> muci[FUNCTION]: 1050 - 1133 -> begin=1104
43
+ STR
44
+ )
45
+ end# }}}
27
46
 
47
+ it 'should work for a function' do# {{{
48
+ text = File.open('spec/sql/test.fnc', 'rb') { |file| file.read }
49
+ structure = Parser::PlsqlStructure.new(text)
28
50
  compute_tree(structure.tree)
29
51
  @result.should eq(<<STR
30
- * root -
31
- |---+ test[SPEC]: 25 - 154
32
- | |---> test[PROCEDURE]: 70 - 70
33
- | +---> muci[FUNCTION]: 99 - 99
34
- |---+ test[BODY]: 180 - 876
35
- | |---> private_proc[PROCEDURE]: 241 - 394
36
- | +---> xyz[PROCEDURE]: 414 - 451
37
- |---> test[PROCEDURE]: 890 - 0
38
- +---> anonymous[BLOCK]: 969 - 1040
52
+ * root - -> begin=
53
+ +---+ test[FUNCTION]: 18 - 134 -> begin=118
54
+ +---> muci[PROCEDURE]: 78 - 115 -> begin=97
39
55
  STR
40
56
  )
41
- end
57
+ end# }}}
42
58
 
43
59
  end
44
60
 
@@ -0,0 +1,12 @@
1
+ create or replace function test return boolean as
2
+
3
+ l_local varchar2(100);
4
+
5
+ procedure muci as
6
+ begin
7
+ null;
8
+ end;
9
+
10
+ begin
11
+ null;
12
+ end;
@@ -17,7 +17,7 @@ create or replace package body test as
17
17
  l_var varchar2(100);
18
18
 
19
19
  /* local function */
20
- funzcction abc return boolean as
20
+ function abc return boolean as
21
21
  begin
22
22
  return true;
23
23
  end;
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vorax
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-17 00:00:00.000000000 Z
12
+ date: 2013-02-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
@@ -98,7 +98,6 @@ files:
98
98
  - lib/vorax/output/vertical_convertor.rb
99
99
  - lib/vorax/output/zip_convertor.rb
100
100
  - lib/vorax/parser/argument.rb~
101
- - lib/vorax/parser/body_split.rb
102
101
  - lib/vorax/parser/conn_string.rb
103
102
  - lib/vorax/parser/grammars/alias.rb
104
103
  - lib/vorax/parser/grammars/alias.rl
@@ -134,6 +133,7 @@ files:
134
133
  - spec/sql/drop_user.sql
135
134
  - spec/sql/muci.spc
136
135
  - spec/sql/setup_user.sql
136
+ - spec/sql/test.fnc
137
137
  - spec/sql/test.pkg
138
138
  - spec/sqlplus_spec.rb
139
139
  - spec/stmt_inspector_spec.rb
@@ -179,6 +179,7 @@ test_files:
179
179
  - spec/sql/drop_user.sql
180
180
  - spec/sql/muci.spc
181
181
  - spec/sql/setup_user.sql
182
+ - spec/sql/test.fnc
182
183
  - spec/sql/test.pkg
183
184
  - spec/sqlplus_spec.rb
184
185
  - spec/stmt_inspector_spec.rb
@@ -1,168 +0,0 @@
1
- # encoding: utf-8
2
- require 'strscan'
3
-
4
- module Vorax
5
-
6
- module Parser
7
-
8
- class SubProgram
9
-
10
- attr_accessor :start_pos, :declare_pos, :end_pos, :text, :level
11
- attr_reader :name, :type
12
-
13
- def initialize(name, type, start_pos)
14
- @name = name
15
- @type = type
16
- @start_pos = start_pos
17
- @declare_pos = nil
18
- @end_pos = nil
19
- @text = ''
20
- @level = 0
21
- end
22
-
23
- end
24
-
25
- class BodySplit
26
-
27
- PLSQL_SPEC = '(?:\bpackage\b|\btype\b)'
28
- SUBPROG = '(?:\bfunction\b|\bprocedure\b)'
29
- BEGIN_MODULE = '(?:\bbegin\b)'
30
- END_MODULE = '(?:\bend\b)'
31
-
32
- def initialize
33
- spots = [BEGIN_ML_COMMENT, BEGIN_SL_COMMENT,
34
- BEGIN_PLSQL_SPECIAL_QUOTING, BEGIN_QUOTING,
35
- PLSQL_SPEC, SUBPROG, BEGIN_MODULE, END_MODULE]
36
- @marks = Regexp.new(spots.join('|'), Regexp::IGNORECASE)
37
- @level = 0
38
- end
39
-
40
- def split(text)
41
- @blocks = []
42
- @ss = StringScanner.new(text)
43
- @level = 0
44
- @crr_block = nil
45
- while !@ss.eos?
46
- Parser::consume(@ss, :scan_until, @marks)
47
- process_ml_comment
48
- process_sl_comment
49
- process_double_quotes
50
- process_plsql_quoting
51
- process_single_quotes
52
- process_plsql_spec
53
- process_subprog
54
- process_begin
55
- process_end
56
- end
57
- return @blocks
58
- end
59
-
60
- private
61
-
62
- def process_ml_comment
63
- scan_until(/\*\/\s*/) if @ss.matched =~ /#{BEGIN_ML_COMMENT}/
64
- end
65
-
66
- def process_sl_comment
67
- scan_until(/\n/) if @ss.matched =~ /#{BEGIN_SL_COMMENT}/
68
- end
69
-
70
- def process_double_quotes
71
- scan_until(/"/) if @ss.matched == '"'
72
- end
73
-
74
- def process_plsql_quoting
75
- if @ss.matched =~ /q'\[/
76
- scan_until(/\]'/)
77
- elsif @ss.matched =~ /q'[{]/
78
- scan_until(/[}]'/)
79
- elsif @ss.matched =~ /q'[(]/
80
- scan_until(/[)]'/)
81
- elsif @ss.matched =~ /q'[<]/
82
- scan_until(/[>]'/)
83
- end
84
- end
85
-
86
- def process_single_quotes
87
- if @ss.matched == "'"
88
- begin
89
- scan_until(/\'+/)
90
- end while (@ss.matched != "'" && !@ss.eos?)
91
- end
92
- end
93
-
94
- def process_plsql_spec
95
- if @ss.matched =~ /#{PLSQL_SPEC}/i
96
- meta_data = Parser.plsql_spec("#{@ss.matched}#{@ss.rest}")
97
- if meta_data[:end_def] > 0
98
- spec = SubProgram.new(meta_data[:name], 'spec', @ss.pos)
99
- spec.declare_pos = @ss.pos + meta_data[:end_def]
100
- scan_until(/#{SLASH_TERMINATOR}/)
101
- spec.end_pos = @ss.pos
102
- spec.text = @ss.string[(spec.start_pos..spec.end_pos)]
103
- @blocks << spec
104
- end
105
- end
106
- end
107
-
108
- def process_subprog
109
- if @ss.matched =~ /#{SUBPROG}/i
110
- subprog_name = @ss.peek(32)[/(?:"[^"]+")|(?:[A-Z0-9$_#]+)/i]
111
- if @ss.matched =~ /function/i
112
- subprog_type = 'function'
113
- elsif @ss.matched =~ /procedure/i
114
- subprog_type = 'procedure'
115
- end
116
- start_pos = @ss.pos - @ss.matched.length
117
- @crr_block = SubProgram.new(subprog_name, subprog_type, start_pos)
118
- end
119
- end
120
-
121
- def process_begin
122
- if @ss.matched =~ /#{BEGIN_MODULE}/i && @crr_block
123
- @level += 1
124
- @crr_block.declare_pos = @ss.pos
125
- @crr_block.level = @level
126
- end
127
- end
128
-
129
- def process_end
130
- if @ss.matched =~ /#{END_MODULE}/i
131
- # we have an "end" match. first of all check if it's not part
132
- # of an conditional compiling "$end" definition
133
- char_behind = @ss.string[@ss.pos - @ss.matched.length - 1, 1]
134
- if char_behind != '$'
135
- finish = Parser.end_subprog("#{@ss.matched}#{@ss.rest}")
136
- if finish > 0
137
- if @level == 1
138
- if @crr_block
139
- @crr_block.end_pos = (@ss.pos - 1) + (finish - 1)
140
- @crr_block.text = @ss.string[(@crr_block.start_pos..@crr_block.end_pos)]
141
- @blocks << @crr_block.clone
142
- @crr_block = nil
143
- end
144
- end
145
- @level -= 1
146
- end
147
- end
148
- end
149
- end
150
-
151
- def scan_until(regexp, skip = false)
152
- if skip
153
- @ss.skip_until(regexp)
154
- else
155
- segment = @ss.scan_until(regexp)
156
- if !segment
157
- @ss.terminate
158
- end
159
- end
160
- end
161
-
162
- end
163
-
164
- end
165
-
166
- end
167
-
168
-