metric_fu-Saikuro 1.1.1.0 → 1.1.2
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.
- checksums.yaml +7 -0
- data/README +52 -54
- data/lib/saikuro.rb +21 -1082
- data/lib/saikuro/base_formatter.rb +30 -0
- data/lib/saikuro/endable_parse_state.rb +12 -0
- data/lib/saikuro/filter.rb +22 -0
- data/lib/saikuro/html_stylesheet.rb +82 -0
- data/lib/saikuro/html_token_counter_formatter.rb +45 -0
- data/lib/saikuro/parse_block.rb +33 -0
- data/lib/saikuro/parse_class.rb +27 -0
- data/lib/saikuro/parse_comment.rb +15 -0
- data/lib/saikuro/parse_cond.rb +6 -0
- data/lib/saikuro/parse_def.rb +59 -0
- data/lib/saikuro/parse_do_cond.rb +24 -0
- data/lib/saikuro/parse_module.rb +6 -0
- data/lib/saikuro/parse_state.rb +286 -0
- data/lib/saikuro/parse_state_formatter.rb +27 -0
- data/lib/saikuro/parse_symbol.rb +13 -0
- data/lib/saikuro/result_index_generator.rb +87 -0
- data/lib/saikuro/saikuro_cmd_line_runner.rb +166 -0
- data/lib/saikuro/state_html_complexity_formatter.rb +38 -0
- data/lib/saikuro/token_counter.rb +51 -0
- data/lib/saikuro/token_counter_formatter.rb +35 -0
- data/lib/saikuro/usage.rb +0 -37
- data/lib/saikuro/version.rb +1 -1
- metadata +35 -24
- data/tests/large_example.rb +0 -70
- data/tests/samples.rb +0 -315
@@ -0,0 +1,30 @@
|
|
1
|
+
class BaseFormater
|
2
|
+
attr_accessor :warnings, :errors, :current
|
3
|
+
|
4
|
+
def initialize(out, filter = nil)
|
5
|
+
@out = out
|
6
|
+
@filter = filter
|
7
|
+
reset_data
|
8
|
+
end
|
9
|
+
|
10
|
+
def warn_error?(num, marker)
|
11
|
+
klass = ""
|
12
|
+
|
13
|
+
if @filter.error?(num)
|
14
|
+
klass = ' class="error"'
|
15
|
+
@errors<< [@current, marker, num]
|
16
|
+
elsif @filter.warn?(num)
|
17
|
+
klass = ' class="warning"'
|
18
|
+
@warnings<< [@current, marker, num]
|
19
|
+
end
|
20
|
+
|
21
|
+
klass
|
22
|
+
end
|
23
|
+
|
24
|
+
def reset_data
|
25
|
+
@warnings = Array.new
|
26
|
+
@errors = Array.new
|
27
|
+
@current = ""
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Filter
|
2
|
+
attr_accessor :limit, :error, :warn
|
3
|
+
|
4
|
+
def initialize(limit = -1, error = 11, warn = 8)
|
5
|
+
@limit = limit
|
6
|
+
@error = error
|
7
|
+
@warn = warn
|
8
|
+
end
|
9
|
+
|
10
|
+
def ignore?(count)
|
11
|
+
count < @limit
|
12
|
+
end
|
13
|
+
|
14
|
+
def warn?(count)
|
15
|
+
count >= @warn
|
16
|
+
end
|
17
|
+
|
18
|
+
def error?(count)
|
19
|
+
count >= @error
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module HTMLStyleSheet
|
2
|
+
def HTMLStyleSheet.style_sheet
|
3
|
+
out = StringIO.new
|
4
|
+
|
5
|
+
out.puts "<style>"
|
6
|
+
out.puts 'body {'
|
7
|
+
out.puts ' margin: 20px;'
|
8
|
+
out.puts ' padding: 0;'
|
9
|
+
out.puts ' font-size: 12px;'
|
10
|
+
out.puts ' font-family: bitstream vera sans, verdana, arial, sans serif;'
|
11
|
+
out.puts ' background-color: #efefef;'
|
12
|
+
out.puts '}'
|
13
|
+
out.puts ''
|
14
|
+
out.puts 'table { '
|
15
|
+
out.puts ' border-collapse: collapse;'
|
16
|
+
out.puts ' /*border-spacing: 0;*/'
|
17
|
+
out.puts ' border: 1px solid #666;'
|
18
|
+
out.puts ' background-color: #fff;'
|
19
|
+
out.puts ' margin-bottom: 20px;'
|
20
|
+
out.puts '}'
|
21
|
+
out.puts ''
|
22
|
+
out.puts 'table, th, th+th, td, td+td {'
|
23
|
+
out.puts ' border: 1px solid #ccc;'
|
24
|
+
out.puts '}'
|
25
|
+
out.puts ''
|
26
|
+
out.puts 'table th {'
|
27
|
+
out.puts ' font-size: 12px;'
|
28
|
+
out.puts ' color: #fc0;'
|
29
|
+
out.puts ' padding: 4px 0;'
|
30
|
+
out.puts ' background-color: #336;'
|
31
|
+
out.puts '}'
|
32
|
+
out.puts ''
|
33
|
+
out.puts 'th, td {'
|
34
|
+
out.puts ' padding: 4px 10px;'
|
35
|
+
out.puts '}'
|
36
|
+
out.puts ''
|
37
|
+
out.puts 'td { '
|
38
|
+
out.puts ' font-size: 13px;'
|
39
|
+
out.puts '}'
|
40
|
+
out.puts ''
|
41
|
+
out.puts '.class_name {'
|
42
|
+
out.puts ' font-size: 17px;'
|
43
|
+
out.puts ' margin: 20px 0 0;'
|
44
|
+
out.puts '}'
|
45
|
+
out.puts ''
|
46
|
+
out.puts '.class_complexity {'
|
47
|
+
out.puts 'margin: 0 auto;'
|
48
|
+
out.puts '}'
|
49
|
+
out.puts ''
|
50
|
+
out.puts '.class_complexity>.class_complexity {'
|
51
|
+
out.puts ' margin: 0;'
|
52
|
+
out.puts '}'
|
53
|
+
out.puts ''
|
54
|
+
out.puts '.class_total_complexity, .class_total_lines, .start_token_count, .file_count {'
|
55
|
+
out.puts ' font-size: 13px;'
|
56
|
+
out.puts ' font-weight: bold;'
|
57
|
+
out.puts '}'
|
58
|
+
out.puts ''
|
59
|
+
out.puts '.class_total_complexity, .class_total_lines {'
|
60
|
+
out.puts ' color: #c00;'
|
61
|
+
out.puts '}'
|
62
|
+
out.puts ''
|
63
|
+
out.puts '.start_token_count, .file_count {'
|
64
|
+
out.puts ' color: #333;'
|
65
|
+
out.puts '}'
|
66
|
+
out.puts ''
|
67
|
+
out.puts '.warning {'
|
68
|
+
out.puts ' background-color: yellow;'
|
69
|
+
out.puts '}'
|
70
|
+
out.puts ''
|
71
|
+
out.puts '.error {'
|
72
|
+
out.puts ' background-color: #f00;'
|
73
|
+
out.puts '}'
|
74
|
+
out.puts "</style>"
|
75
|
+
|
76
|
+
out.string
|
77
|
+
end
|
78
|
+
|
79
|
+
def style_sheet
|
80
|
+
HTMLStyleSheet.style_sheet
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class HTMLTokenCounterFormater < TokenCounterFormater
|
2
|
+
include HTMLStyleSheet
|
3
|
+
|
4
|
+
def start(new_out=nil)
|
5
|
+
reset_data
|
6
|
+
@out = new_out if new_out
|
7
|
+
@out.puts "<html>"
|
8
|
+
@out.puts style_sheet
|
9
|
+
@out.puts "<body>"
|
10
|
+
end
|
11
|
+
|
12
|
+
def start_count(number_of_files)
|
13
|
+
@out.puts "<div class=\"start_token_count\">"
|
14
|
+
@out.puts "Number of files: #{number_of_files}"
|
15
|
+
@out.puts "</div>"
|
16
|
+
end
|
17
|
+
|
18
|
+
def start_file(file_name)
|
19
|
+
@current = file_name
|
20
|
+
@out.puts "<div class=\"file_count\">"
|
21
|
+
@out.puts "<p class=\"file_name\">"
|
22
|
+
@out.puts "File: #{file_name}"
|
23
|
+
@out.puts "</p>"
|
24
|
+
@out.puts "<table width=\"100%\" border=\"1\">"
|
25
|
+
@out.puts "<tr><th>Line</th><th>Tokens</th></tr>"
|
26
|
+
end
|
27
|
+
|
28
|
+
def line_token_count(line_number,number_of_tokens)
|
29
|
+
return if @filter.ignore?(number_of_tokens)
|
30
|
+
klass = warn_error?(number_of_tokens, line_number)
|
31
|
+
@out.puts "<tr><td>#{line_number}</td><td#{klass}>#{number_of_tokens}</td></tr>"
|
32
|
+
end
|
33
|
+
|
34
|
+
def end_file
|
35
|
+
@out.puts "</table>"
|
36
|
+
end
|
37
|
+
|
38
|
+
def end_count
|
39
|
+
end
|
40
|
+
|
41
|
+
def end
|
42
|
+
@out.puts "</body>"
|
43
|
+
@out.puts "</html>"
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class ParseBlock < EndableParseState
|
2
|
+
|
3
|
+
def initialize(lexer,parent=nil)
|
4
|
+
super(lexer,parent)
|
5
|
+
@complexity = 1
|
6
|
+
@lbraces = Array.new
|
7
|
+
end
|
8
|
+
|
9
|
+
# Because the token for a block and hash right brace is the same,
|
10
|
+
# we need to track the hash left braces to determine when an end is
|
11
|
+
# encountered.
|
12
|
+
def parse_token(token)
|
13
|
+
if token.is_a?(TkLBRACE)
|
14
|
+
@lbraces.push(true)
|
15
|
+
elsif token.is_a?(TkRBRACE)
|
16
|
+
if @lbraces.empty?
|
17
|
+
do_right_brace_token(token)
|
18
|
+
#do_end_token(token)
|
19
|
+
else
|
20
|
+
@lbraces.pop
|
21
|
+
end
|
22
|
+
else
|
23
|
+
super(token)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def do_right_brace_token(token)
|
28
|
+
# we are done ? what about a hash in a block :-/
|
29
|
+
@run = false
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class ParseClass < EndableParseState
|
2
|
+
def initialize(lexer,parent=nil)
|
3
|
+
super(lexer,parent)
|
4
|
+
@type_name = "Class"
|
5
|
+
end
|
6
|
+
|
7
|
+
def do_constant_token(token)
|
8
|
+
@name = token.name if @name.empty?
|
9
|
+
nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def compute_state(formater)
|
13
|
+
# Seperate the Module and Class Children out
|
14
|
+
cnm_children, @children = @children.partition do |child|
|
15
|
+
child.kind_of?(ParseClass)
|
16
|
+
end
|
17
|
+
|
18
|
+
formater.start_class_compute_state(@type_name,@name,self.calc_complexity,self.calc_lines)
|
19
|
+
super(formater)
|
20
|
+
formater.end_class_compute_state(@name)
|
21
|
+
|
22
|
+
cnm_children.each do |child|
|
23
|
+
child.name = @name + "::" + child.name
|
24
|
+
child.compute_state(formater)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Read and consume tokens in comments until a new line.
|
2
|
+
class ParseComment < ParseState
|
3
|
+
|
4
|
+
# While in a comment state do not count the tokens.
|
5
|
+
def count_tokens?
|
6
|
+
false
|
7
|
+
end
|
8
|
+
|
9
|
+
def parse_token(token)
|
10
|
+
if token.is_a?(TkNL)
|
11
|
+
@lines += 1
|
12
|
+
@run = false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class ParseDef < EndableParseState
|
2
|
+
|
3
|
+
def initialize(lexer,parent=nil)
|
4
|
+
super(lexer,parent)
|
5
|
+
@complexity = 1
|
6
|
+
@looking_for_name = true
|
7
|
+
@first_space = true
|
8
|
+
end
|
9
|
+
|
10
|
+
# This way I don't need to list all possible overload
|
11
|
+
# tokens.
|
12
|
+
def create_def_name(token)
|
13
|
+
case token
|
14
|
+
when TkSPACE
|
15
|
+
# mark first space so we can stop at next space
|
16
|
+
if @first_space
|
17
|
+
@first_space = false
|
18
|
+
else
|
19
|
+
@looking_for_name = false
|
20
|
+
end
|
21
|
+
when TkNL,TkLPAREN,TkfLPAREN,TkSEMICOLON
|
22
|
+
# we can also stop at a new line or left parenthesis
|
23
|
+
@looking_for_name = false
|
24
|
+
when TkDOT
|
25
|
+
@name<< "."
|
26
|
+
when TkCOLON2
|
27
|
+
@name<< "::"
|
28
|
+
when TkASSIGN
|
29
|
+
@name<< "="
|
30
|
+
when TkfLBRACK
|
31
|
+
@name<< "["
|
32
|
+
when TkRBRACK
|
33
|
+
@name<< "]"
|
34
|
+
else
|
35
|
+
begin
|
36
|
+
@name<< token.name.to_s
|
37
|
+
rescue Exception => err
|
38
|
+
#what is this?
|
39
|
+
STDOUT.puts @@token_counter.current_file
|
40
|
+
STDOUT.puts @name
|
41
|
+
STDOUT.puts token.inspect
|
42
|
+
STDOUT.puts err.message
|
43
|
+
exit 1
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def parse_token(token)
|
49
|
+
if @looking_for_name
|
50
|
+
create_def_name(token)
|
51
|
+
end
|
52
|
+
super(token)
|
53
|
+
end
|
54
|
+
|
55
|
+
def compute_state(formater)
|
56
|
+
formater.def_compute_state(@name, self.calc_complexity, self.calc_lines)
|
57
|
+
super(formater)
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class ParseDoCond < ParseCond
|
2
|
+
def initialize(lexer,parent=nil)
|
3
|
+
super(lexer,parent)
|
4
|
+
@looking_for_new_line = true
|
5
|
+
end
|
6
|
+
|
7
|
+
# Need to consume the do that can appear at the
|
8
|
+
# end of these control structures.
|
9
|
+
def parse_token(token)
|
10
|
+
if @looking_for_new_line
|
11
|
+
if token.is_a?(TkDO)
|
12
|
+
nil
|
13
|
+
else
|
14
|
+
if token.is_a?(TkNL)
|
15
|
+
@looking_for_new_line = false
|
16
|
+
end
|
17
|
+
super(token)
|
18
|
+
end
|
19
|
+
else
|
20
|
+
super(token)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,286 @@
|
|
1
|
+
# Main class and structure used to compute the
|
2
|
+
# cyclomatic complexity of Ruby programs.
|
3
|
+
class ParseState
|
4
|
+
include RubyToken
|
5
|
+
attr_accessor :name, :children, :complexity, :parent, :lines
|
6
|
+
|
7
|
+
@@top_state = nil
|
8
|
+
def ParseState.make_top_state()
|
9
|
+
@@top_state = ParseState.new(nil)
|
10
|
+
@@top_state.name = "__top__"
|
11
|
+
@@top_state
|
12
|
+
end
|
13
|
+
|
14
|
+
@@token_counter = TokenCounter.new
|
15
|
+
def ParseState.set_token_counter(counter)
|
16
|
+
@@token_counter = counter
|
17
|
+
end
|
18
|
+
def ParseState.get_token_counter
|
19
|
+
@@token_counter
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(lexer,parent=nil)
|
23
|
+
@name = ""
|
24
|
+
@children = Array.new
|
25
|
+
@complexity = 0
|
26
|
+
@parent = parent
|
27
|
+
@lexer = lexer
|
28
|
+
@run = true
|
29
|
+
# To catch one line def statements, We always have one line.
|
30
|
+
@lines = 0
|
31
|
+
@last_token_line_and_char = Array.new
|
32
|
+
end
|
33
|
+
|
34
|
+
def top_state?
|
35
|
+
self == @@top_state
|
36
|
+
end
|
37
|
+
|
38
|
+
def lexer=(lexer)
|
39
|
+
@run = true
|
40
|
+
@lexer = lexer
|
41
|
+
end
|
42
|
+
|
43
|
+
def make_state(type,parent = nil)
|
44
|
+
cstate = type.new(@lexer,self)
|
45
|
+
parent.children<< cstate
|
46
|
+
cstate
|
47
|
+
end
|
48
|
+
|
49
|
+
def calc_complexity
|
50
|
+
complexity = @complexity
|
51
|
+
children.each do |child|
|
52
|
+
complexity += child.calc_complexity
|
53
|
+
end
|
54
|
+
complexity
|
55
|
+
end
|
56
|
+
|
57
|
+
def calc_lines
|
58
|
+
lines = @lines
|
59
|
+
children.each do |child|
|
60
|
+
lines += child.calc_lines
|
61
|
+
end
|
62
|
+
lines
|
63
|
+
end
|
64
|
+
|
65
|
+
def compute_state(formater)
|
66
|
+
if top_state?
|
67
|
+
compute_state_for_global(formater)
|
68
|
+
end
|
69
|
+
|
70
|
+
@children.each do |s|
|
71
|
+
s.compute_state(formater)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def compute_state_for_global(formater)
|
76
|
+
global_def, @children = @children.partition do |s|
|
77
|
+
!s.kind_of?(ParseClass)
|
78
|
+
end
|
79
|
+
return if global_def.empty?
|
80
|
+
gx = global_def.inject(0) { |c,s| s.calc_complexity }
|
81
|
+
gl = global_def.inject(0) { |c,s| s.calc_lines }
|
82
|
+
formater.start_class_compute_state("Global", "", gx, gl)
|
83
|
+
global_def.each do |s|
|
84
|
+
s.compute_state(formater)
|
85
|
+
end
|
86
|
+
formater.end_class_compute_state("")
|
87
|
+
end
|
88
|
+
|
89
|
+
# Count the tokens parsed if true else ignore them.
|
90
|
+
def count_tokens?
|
91
|
+
true
|
92
|
+
end
|
93
|
+
|
94
|
+
def parse
|
95
|
+
while @run do
|
96
|
+
tok = @lexer.token
|
97
|
+
@run = false if tok.nil?
|
98
|
+
if lexer_loop?(tok)
|
99
|
+
STDERR.puts "Lexer loop at line : #{@lexer.line_no} char #{@lexer.char_no}."
|
100
|
+
@run = false
|
101
|
+
end
|
102
|
+
@last_token_line_and_char<< [@lexer.line_no.to_i, @lexer.char_no.to_i, tok]
|
103
|
+
if $VERBOSE
|
104
|
+
puts "DEBUG: #{@lexer.line_no} #{tok.class}:#{tok.name if tok.respond_to?(:name)}"
|
105
|
+
end
|
106
|
+
@@token_counter.count_token(@lexer.line_no, tok) if count_tokens?
|
107
|
+
parse_token(tok)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Ruby-Lexer can go into a loop if the file does not end with a newline.
|
112
|
+
def lexer_loop?(token)
|
113
|
+
return false if @last_token_line_and_char.empty?
|
114
|
+
loop_flag = false
|
115
|
+
last = @last_token_line_and_char.last
|
116
|
+
line = last[0]
|
117
|
+
char = last[1]
|
118
|
+
ltok = last[2]
|
119
|
+
|
120
|
+
if ( (line == @lexer.line_no.to_i) &&
|
121
|
+
(char == @lexer.char_no.to_i) &&
|
122
|
+
(ltok.class == token.class) )
|
123
|
+
# We are potentially in a loop
|
124
|
+
if @last_token_line_and_char.size >= 3
|
125
|
+
loop_flag = true
|
126
|
+
end
|
127
|
+
else
|
128
|
+
# Not in a loop so clear stack
|
129
|
+
@last_token_line_and_char = Array.new
|
130
|
+
end
|
131
|
+
|
132
|
+
loop_flag
|
133
|
+
end
|
134
|
+
|
135
|
+
def do_begin_token(token)
|
136
|
+
make_state(EndableParseState, self)
|
137
|
+
end
|
138
|
+
|
139
|
+
def do_class_token(token)
|
140
|
+
make_state(ParseClass,self)
|
141
|
+
end
|
142
|
+
|
143
|
+
def do_module_token(token)
|
144
|
+
make_state(ParseModule,self)
|
145
|
+
end
|
146
|
+
|
147
|
+
def do_def_token(token)
|
148
|
+
make_state(ParseDef,self)
|
149
|
+
end
|
150
|
+
|
151
|
+
def do_constant_token(token)
|
152
|
+
nil
|
153
|
+
end
|
154
|
+
|
155
|
+
def do_identifier_token(token)
|
156
|
+
if (token.name == "__END__" && token.char_no.to_i == 0)
|
157
|
+
# The Ruby code has stopped and the rest is data so cease parsing.
|
158
|
+
@run = false
|
159
|
+
end
|
160
|
+
nil
|
161
|
+
end
|
162
|
+
|
163
|
+
def do_right_brace_token(token)
|
164
|
+
nil
|
165
|
+
end
|
166
|
+
|
167
|
+
def do_end_token(token)
|
168
|
+
end_debug
|
169
|
+
nil
|
170
|
+
end
|
171
|
+
|
172
|
+
def do_block_token(token)
|
173
|
+
make_state(ParseBlock,self)
|
174
|
+
end
|
175
|
+
|
176
|
+
def do_conditional_token(token)
|
177
|
+
make_state(ParseCond,self)
|
178
|
+
end
|
179
|
+
|
180
|
+
def do_conditional_do_control_token(token)
|
181
|
+
make_state(ParseDoCond,self)
|
182
|
+
end
|
183
|
+
|
184
|
+
def do_case_token(token)
|
185
|
+
make_state(EndableParseState, self)
|
186
|
+
end
|
187
|
+
|
188
|
+
def do_one_line_conditional_token(token)
|
189
|
+
# This is an if with no end
|
190
|
+
@complexity += 1
|
191
|
+
#STDOUT.puts "got IF_MOD: #{self.to_yaml}" if $VERBOSE
|
192
|
+
#if state.type != "class" && state.type != "def" && state.type != "cond"
|
193
|
+
#STDOUT.puts "Changing IF_MOD Parent" if $VERBOSE
|
194
|
+
#state = state.parent
|
195
|
+
#@run = false
|
196
|
+
nil
|
197
|
+
end
|
198
|
+
|
199
|
+
def do_else_token(token)
|
200
|
+
STDOUT.puts "Ignored/Unknown Token:#{token.class}" if $VERBOSE
|
201
|
+
nil
|
202
|
+
end
|
203
|
+
|
204
|
+
def do_comment_token(token)
|
205
|
+
make_state(ParseComment, self)
|
206
|
+
end
|
207
|
+
|
208
|
+
def do_symbol_token(token)
|
209
|
+
make_state(ParseSymbol, self)
|
210
|
+
end
|
211
|
+
|
212
|
+
def parse_token(token)
|
213
|
+
state = nil
|
214
|
+
case token
|
215
|
+
when TkCLASS
|
216
|
+
state = do_class_token(token)
|
217
|
+
when TkMODULE
|
218
|
+
state = do_module_token(token)
|
219
|
+
when TkDEF
|
220
|
+
state = do_def_token(token)
|
221
|
+
when TkCONSTANT
|
222
|
+
# Nothing to do with a constant at top level?
|
223
|
+
state = do_constant_token(token)
|
224
|
+
when TkIDENTIFIER,TkFID
|
225
|
+
# Nothing to do at top level?
|
226
|
+
state = do_identifier_token(token)
|
227
|
+
when TkRBRACE
|
228
|
+
# Nothing to do at top level
|
229
|
+
state = do_right_brace_token(token)
|
230
|
+
when TkEND
|
231
|
+
state = do_end_token(token)
|
232
|
+
# At top level this might be an error...
|
233
|
+
when TkDO,TkfLBRACE
|
234
|
+
state = do_block_token(token)
|
235
|
+
when TkIF,TkUNLESS
|
236
|
+
state = do_conditional_token(token)
|
237
|
+
when TkWHILE,TkUNTIL,TkFOR
|
238
|
+
state = do_conditional_do_control_token(token)
|
239
|
+
when TkELSIF #,TkELSE
|
240
|
+
@complexity += 1
|
241
|
+
when TkELSE
|
242
|
+
# Else does not increase complexity
|
243
|
+
when TkCASE
|
244
|
+
state = do_case_token(token)
|
245
|
+
when TkWHEN
|
246
|
+
@complexity += 1
|
247
|
+
when TkBEGIN
|
248
|
+
state = do_begin_token(token)
|
249
|
+
when TkRESCUE
|
250
|
+
# Maybe this should add complexity and not begin
|
251
|
+
@complexity += 1
|
252
|
+
when TkIF_MOD, TkUNLESS_MOD, TkUNTIL_MOD, TkWHILE_MOD, TkQUESTION
|
253
|
+
state = do_one_line_conditional_token(token)
|
254
|
+
when TkNL
|
255
|
+
#
|
256
|
+
@lines += 1
|
257
|
+
when TkRETURN
|
258
|
+
# Early returns do not increase complexity as the condition that
|
259
|
+
# calls the return is the one that increases it.
|
260
|
+
when TkCOMMENT
|
261
|
+
state = do_comment_token(token)
|
262
|
+
when TkSYMBEG
|
263
|
+
state = do_symbol_token(token)
|
264
|
+
when TkError
|
265
|
+
STDOUT.puts "Lexer received an error for line #{@lexer.line_no} char #{@lexer.char_no}"
|
266
|
+
else
|
267
|
+
state = do_else_token(token)
|
268
|
+
end
|
269
|
+
state.parse if state
|
270
|
+
end
|
271
|
+
|
272
|
+
def end_debug
|
273
|
+
STDOUT.puts "got an end: #{@name} in #{self.class.name}" if $VERBOSE
|
274
|
+
if @parent.nil?
|
275
|
+
STDOUT.puts "DEBUG: Line #{@lexer.line_no}"
|
276
|
+
STDOUT.puts "DEBUG: #{@name}; #{self.class}"
|
277
|
+
# to_yaml can cause an infinite loop?
|
278
|
+
#STDOUT.puts "TOP: #{@@top_state.to_yaml}"
|
279
|
+
#STDOUT.puts "TOP: #{@@top_state.inspect}"
|
280
|
+
|
281
|
+
# This may not be an error?
|
282
|
+
#exit 1
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
end
|