vorax 0.1.4 → 0.2.0

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.
@@ -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
-