trace_visualization 0.0.3 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/bin/trace_visualization +21 -26
- data/lib/trace_visualization.rb +2 -2
- data/lib/trace_visualization/algorithm.rb +42 -0
- data/lib/trace_visualization/data/irepetition.rb +5 -1
- data/lib/trace_visualization/data/repetition.rb +14 -6
- data/lib/trace_visualization/data/sorted_array.rb +44 -0
- data/lib/trace_visualization/data/{lexeme.rb → token.rb} +7 -8
- data/lib/trace_visualization/lexeme_overlap_filter.rb +18 -18
- data/lib/trace_visualization/mapping.rb +72 -185
- data/lib/trace_visualization/repetitions/concatenation.rb +136 -0
- data/lib/trace_visualization/repetitions/context.rb +70 -0
- data/lib/trace_visualization/repetitions/filter.rb +153 -0
- data/lib/trace_visualization/repetitions/incrementation.rb +89 -0
- data/lib/trace_visualization/repetitions_psy.rb +12 -5
- data/lib/trace_visualization/utils.rb +5 -42
- data/lib/trace_visualization/version.rb +1 -1
- data/lib/trace_visualization/visualization/console_color_print.rb +20 -4
- data/spec/algorithm_spec.rb +69 -0
- data/spec/bwt_spec.rb +2 -5
- data/spec/data/sorted_array_spec.rb +27 -0
- data/spec/lexeme_overlap_filter_spec.rb +22 -22
- data/spec/longest_common_prefix_spec.rb +3 -8
- data/spec/mapping_spec.rb +72 -69
- data/spec/repetitions/concatenation_spec.rb +65 -0
- data/spec/repetitions/filter_spec.rb +180 -0
- data/spec/repetitions/incrementation_spec.rb +29 -0
- data/spec/repetitions_psy_spec.rb +7 -16
- data/spec/suffix_array_spec.rb +11 -31
- data/spec/utils_spec.rb +21 -9
- data/spec/visualization/console_color_print_spec.rb +26 -0
- data/trace_visualization.gemspec +2 -2
- metadata +27 -13
- data/lib/trace_visualization/repetitions_concatenation.rb +0 -134
- data/lib/trace_visualization/repetitions_context.rb +0 -18
- data/spec/repetitions_concatenation_spec.rb +0 -64
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2fee2d1c5c6920d3966ae5190b05bcb40ce2b359
|
4
|
+
data.tar.gz: c8cb276ef0bfef1d293b996bd236c4d1cdc6f1b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9dc0447760f9d5b95f27ec88e95bde2beb73037f36cb3af6d6aa4a324d17afa348e7462735e9a14e78aefdf9c779bb446beaaca5a249af32e467d4b14695f32f
|
7
|
+
data.tar.gz: d9b3c4ce306cd563ab394104fec2e85654e8bc55e8592a64ff7367a8269b7b33635f16412eba65af404c1eb2b790f9986c820a6fbb0aa483bbfbf155774e590b
|
data/Gemfile
CHANGED
data/bin/trace_visualization
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'trace_visualization'
|
4
|
+
require 'trace_preprocessor'
|
4
5
|
require 'tempfile'
|
5
6
|
require 'benchmark'
|
6
7
|
require 'optparse'
|
@@ -39,6 +40,11 @@ def parse_options
|
|
39
40
|
opts.on('-t', '--test_preprocessor_performance', 'Test preprocessor performance') do
|
40
41
|
options[:test_preprocessor_performance] = true
|
41
42
|
end
|
43
|
+
|
44
|
+
opts.on('-v', '--version', 'Display version') do
|
45
|
+
puts "Version #{VERSION}"
|
46
|
+
exit
|
47
|
+
end
|
42
48
|
|
43
49
|
opts.on('-h', '--help', 'Display this screen') do
|
44
50
|
puts opts
|
@@ -75,8 +81,10 @@ def foo(options)
|
|
75
81
|
|
76
82
|
mapping = nil
|
77
83
|
bm('Mapping') do
|
78
|
-
mapping =
|
79
|
-
mapping.
|
84
|
+
mapping = Mapping.new
|
85
|
+
mapping.process do
|
86
|
+
from_preprocessed_file(tmp_file.path, options[:offset], options[:limit], !options[:test_preprocessor_performance])
|
87
|
+
end
|
80
88
|
end
|
81
89
|
|
82
90
|
source_file_length = `wc -c #{options[:source_file_name]}`.to_i
|
@@ -94,40 +102,27 @@ def foo(options)
|
|
94
102
|
exit 0
|
95
103
|
end
|
96
104
|
|
97
|
-
|
98
|
-
bm('PSY1') do
|
99
|
-
rs = Repetitions.psy1(mapping, options[:positions_min_size], true)
|
100
|
-
end
|
101
|
-
|
102
|
-
puts "rs.size = #{rs.size}"
|
105
|
+
repetitions = Algorithm.process(mapping, {})
|
103
106
|
|
104
|
-
|
105
|
-
#bm('Context') do
|
106
|
-
# context = TraceVisualization::Repetitions::Context.new(mapping, rs)
|
107
|
-
#end
|
107
|
+
RepetitionsScore.fill_score(repetitions, :sort => true, :order => 'desc', :version => 'relative')
|
108
108
|
|
109
|
-
|
109
|
+
#
|
110
|
+
# rs[0 ... options[:out]].each do |r|
|
111
|
+
# puts '---------------------'
|
112
|
+
# puts r
|
113
|
+
# puts Visualization::ConsoleColorPrint.hl(mapping, r)
|
114
|
+
# end
|
110
115
|
|
111
|
-
|
112
|
-
puts '---------------------'
|
113
|
-
puts r
|
114
|
-
puts Visualization::ConsoleColorPrint.hl(mapping, r)
|
115
|
-
end
|
116
|
+
Visualization::ConsoleColorPrint.hl_stdout(mapping, repetitions[0])
|
116
117
|
|
117
|
-
|
118
|
+
repetitions
|
118
119
|
end
|
119
120
|
|
120
|
-
|
121
121
|
def bm(name, &block)
|
122
122
|
Benchmark.bm(17) do |x|
|
123
123
|
x.report(name, &block)
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
127
|
-
|
128
127
|
options = parse_options
|
129
|
-
rs = foo(options)
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
128
|
+
rs = foo(options)
|
data/lib/trace_visualization.rb
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
reorder
|
6
6
|
repetitions
|
7
7
|
repetitions_psy
|
8
|
-
|
8
|
+
repetitions/context
|
9
9
|
repetitions_score
|
10
10
|
visualization/console_color_print
|
11
11
|
).each { |file| require File.join(File.dirname(__FILE__), 'trace_visualization', file) }
|
@@ -34,7 +34,7 @@ module TraceVisualization
|
|
34
34
|
# Read & mapping file
|
35
35
|
mapping = TraceVisualization::Mapping.new
|
36
36
|
mapping.process do
|
37
|
-
|
37
|
+
from_file options[:file_name]
|
38
38
|
end
|
39
39
|
|
40
40
|
=begin
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'trace_visualization/utils'
|
2
|
+
require 'trace_visualization/assert'
|
3
|
+
require 'trace_visualization/repetitions/filter'
|
4
|
+
require 'trace_visualization/repetitions/concatenation'
|
5
|
+
|
6
|
+
module TraceVisualization
|
7
|
+
|
8
|
+
# Main algorithm
|
9
|
+
module Algorithm
|
10
|
+
include TraceVisualization
|
11
|
+
include TraceVisualization::Repetitions
|
12
|
+
|
13
|
+
# Run main algorithm of approximate repeats processing
|
14
|
+
# @param mapping [TraceVisualization::Mapping]
|
15
|
+
# @param options [Hash]
|
16
|
+
def self.process(mapping, options = {})
|
17
|
+
TraceVisualization.assert_instance_of(mapping, Mapping)
|
18
|
+
|
19
|
+
Utils.set_default_options(options, { :positions_min_size => 3, :k => 3 })
|
20
|
+
|
21
|
+
context = Context.new(mapping)
|
22
|
+
|
23
|
+
# First step - calculate strict repetitions
|
24
|
+
context.repetitions = Repetitions.psy1(mapping, options[:positions_min_size])
|
25
|
+
|
26
|
+
# Second step - iterative process concatenation & incrementation algorithms for approximate repeats processing
|
27
|
+
Filter.strict_repetitions_filter(mapping, context, options)
|
28
|
+
|
29
|
+
for kk in 1 .. options[:k]
|
30
|
+
Concatenation.process(context, {
|
31
|
+
:k => kk,
|
32
|
+
:positions_min_size => options[:positions_min_size]
|
33
|
+
})
|
34
|
+
|
35
|
+
Filter.repetitions_filter(mapping, context, options)
|
36
|
+
end
|
37
|
+
|
38
|
+
context.repetitions
|
39
|
+
end
|
40
|
+
|
41
|
+
end # Algorithm
|
42
|
+
end # TraceVisualization
|
@@ -1,3 +1,7 @@
|
|
1
|
+
require 'trace_visualization/data/sorted_array'
|
2
|
+
|
3
|
+
include TraceVisualization::Data
|
4
|
+
|
1
5
|
# Interface for Repetition
|
2
6
|
module IRepetition
|
3
7
|
def positions_size; end
|
@@ -31,7 +35,7 @@ class RepetitionBase
|
|
31
35
|
attr_accessor :lines
|
32
36
|
|
33
37
|
def initialize
|
34
|
-
@lines =
|
38
|
+
@lines = SortedArray.new
|
35
39
|
end
|
36
40
|
|
37
41
|
def left_length
|
@@ -5,11 +5,13 @@ module TraceVisualization
|
|
5
5
|
module Data
|
6
6
|
class Repetition < RepetitionBase
|
7
7
|
@@sequence = 0
|
8
|
-
|
8
|
+
|
9
|
+
attr_reader :id
|
10
|
+
attr_reader :left_positions, :right_positions
|
11
|
+
|
9
12
|
attr_accessor :score
|
10
13
|
attr_accessor :pcount
|
11
|
-
|
12
|
-
attr_reader :id
|
14
|
+
|
13
15
|
attr_accessor :strict_ids
|
14
16
|
|
15
17
|
def to_s
|
@@ -23,7 +25,7 @@ module TraceVisualization
|
|
23
25
|
"left = #{@left != nil ? @left.id : 'nil'}, " +
|
24
26
|
"right = #{@right != nil ? @right.id : 'nil'}"
|
25
27
|
end
|
26
|
-
|
28
|
+
|
27
29
|
def initialize(length, left_positions, right_positions = nil)
|
28
30
|
super()
|
29
31
|
|
@@ -35,10 +37,16 @@ module TraceVisualization
|
|
35
37
|
@right_positions = right_positions
|
36
38
|
|
37
39
|
@id = (@@sequence += 1)
|
38
|
-
@strict_ids = [@id]
|
39
|
-
@lines = []
|
40
|
+
@strict_ids = [ @id ]
|
40
41
|
end
|
41
42
|
|
43
|
+
def ==(other_repetition)
|
44
|
+
other_repetition != nil &&
|
45
|
+
@length == other_repetition.length &&
|
46
|
+
@left_positions == other_repetition.left_positions &&
|
47
|
+
@right_positions == other_repetition.right_positions
|
48
|
+
end
|
49
|
+
|
42
50
|
def positions_size
|
43
51
|
@left_positions.size
|
44
52
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module TraceVisualization
|
2
|
+
module Data
|
3
|
+
class SortedArray < Array
|
4
|
+
def self.[] *array
|
5
|
+
SortedArray.new(array)
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(array = nil)
|
9
|
+
super( array.sort ) if array
|
10
|
+
end
|
11
|
+
|
12
|
+
def << value
|
13
|
+
insert index_of_last_LE(value), value
|
14
|
+
end
|
15
|
+
|
16
|
+
alias push <<
|
17
|
+
alias shift <<
|
18
|
+
|
19
|
+
def index_of_last_LE value
|
20
|
+
l, r = 0, length - 1
|
21
|
+
while l <= r
|
22
|
+
m = (r + l) / 2
|
23
|
+
|
24
|
+
if value < self[m]
|
25
|
+
r = m - 1
|
26
|
+
else
|
27
|
+
l = m + 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
l
|
32
|
+
end
|
33
|
+
|
34
|
+
def index value
|
35
|
+
idx = index_of_last_LE(value)
|
36
|
+
|
37
|
+
if idx != 0 && self[idx - 1] == value
|
38
|
+
idx -= 1 while idx != 0 && self[idx - 1] == value
|
39
|
+
idx
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module TraceVisualization
|
2
2
|
module Data
|
3
|
-
class
|
3
|
+
class Token
|
4
4
|
attr_accessor :name
|
5
5
|
attr_accessor :value
|
6
6
|
attr_accessor :int_value
|
7
7
|
|
8
|
-
# Length of preprocessed string (see
|
9
|
-
attr_accessor :
|
8
|
+
# Length of preprocessed string (see TOKEN_REGEXP)
|
9
|
+
attr_accessor :token_length
|
10
10
|
|
11
11
|
attr_accessor :ord
|
12
12
|
|
@@ -47,12 +47,11 @@ module TraceVisualization
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
class
|
51
|
-
attr_accessor :
|
52
|
-
attr_accessor :pos
|
50
|
+
class TokenPosition
|
51
|
+
attr_accessor :token, :pos
|
53
52
|
|
54
|
-
def initialize(
|
55
|
-
@
|
53
|
+
def initialize(token, pos)
|
54
|
+
@token, @pos = token, pos
|
56
55
|
end
|
57
56
|
end
|
58
57
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module TraceVisualization
|
2
2
|
module LexemeOverlapFilter
|
3
3
|
|
4
|
-
def self.process(
|
5
|
-
|
6
|
-
left_bound =
|
7
|
-
[
|
4
|
+
def self.process(token_positions)
|
5
|
+
token_positions.sort! { |a, b| a.pos <=> b.pos }
|
6
|
+
left_bound = token_positions.inject(0) do |left_bound, token_pos|
|
7
|
+
[token_pos.pos + token_pos.token.length, left_bound].max
|
8
8
|
end
|
9
9
|
|
10
10
|
idx, current, result = 0, [], []
|
@@ -13,24 +13,24 @@ module TraceVisualization
|
|
13
13
|
|
14
14
|
i = 0
|
15
15
|
while i < current.size
|
16
|
-
|
16
|
+
token_pos = current[i]
|
17
17
|
|
18
|
-
if
|
19
|
-
|
18
|
+
if token_pos.pos + token_pos.token.length == pos
|
19
|
+
fl_delete_token = false
|
20
20
|
|
21
21
|
if current.size == 1
|
22
|
-
result <<
|
23
|
-
|
22
|
+
result << token_pos
|
23
|
+
fl_delete_token = true
|
24
24
|
else
|
25
|
-
if
|
26
|
-
result <<
|
25
|
+
if is_longest_token(current, token_pos)
|
26
|
+
result << token_pos
|
27
27
|
current = []
|
28
28
|
else
|
29
|
-
|
29
|
+
fl_delete_token = true
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
if
|
33
|
+
if fl_delete_token
|
34
34
|
current.delete_at(i)
|
35
35
|
i -= 1
|
36
36
|
end
|
@@ -39,8 +39,8 @@ module TraceVisualization
|
|
39
39
|
i += 1
|
40
40
|
end
|
41
41
|
|
42
|
-
while idx <
|
43
|
-
current <<
|
42
|
+
while idx < token_positions.size && token_positions[idx].pos == pos
|
43
|
+
current << token_positions[idx]
|
44
44
|
idx += 1
|
45
45
|
end
|
46
46
|
end
|
@@ -48,11 +48,11 @@ module TraceVisualization
|
|
48
48
|
result
|
49
49
|
end
|
50
50
|
|
51
|
-
def self.
|
51
|
+
def self.is_longest_token(token_positions, token_pos)
|
52
52
|
result = true
|
53
53
|
|
54
|
-
|
55
|
-
if
|
54
|
+
token_positions.each do |other_token_pos|
|
55
|
+
if token_pos != other_token_pos && token_pos.token.length < other_token_pos.token.length
|
56
56
|
result = false
|
57
57
|
break
|
58
58
|
end
|
@@ -3,38 +3,18 @@ require 'ipaddr'
|
|
3
3
|
|
4
4
|
require 'trace_visualization/reorder'
|
5
5
|
require 'trace_visualization/lexeme_overlap_filter'
|
6
|
-
require 'trace_visualization/data/
|
6
|
+
require 'trace_visualization/data/token'
|
7
|
+
|
8
|
+
include TraceVisualization
|
7
9
|
|
8
10
|
module TraceVisualization
|
9
11
|
class Mapping
|
10
|
-
|
11
|
-
attr_accessor :tokens
|
12
|
-
|
13
|
-
LEXEME_REGEXP = /\{LEXEME;(?<name>[a-zA-Z0-9]+);(?<source>[^;]+);(?<value>[0-9]+)\}/
|
14
|
-
|
15
|
-
DEFAULT_TOKENS = {
|
16
|
-
:ID => [
|
17
|
-
/(?<lexeme>\[\d{3,}\])/,
|
18
|
-
lambda { |source| source[1 ... -1].to_i }
|
19
|
-
],
|
20
|
-
|
21
|
-
:IP => [
|
22
|
-
/(?<lexeme>(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))/,
|
23
|
-
lambda { |source| IPAddr.new(source).to_i }
|
24
|
-
],
|
25
|
-
|
26
|
-
:TIME => [
|
27
|
-
/(?<lexeme>\[\d{2} [a-zA-Z]{3} \d{4} \d{2}\:\d{2}\:\d{2}\])/,
|
28
|
-
lambda { |source| Time.parse(source[1 ... -1]).to_i }
|
29
|
-
]
|
30
|
-
}
|
12
|
+
TOKEN_REGEXP = /\{TOKEN;(?<name>[a-zA-Z0-9]+);(?<source>[^;]+);(?<value>[0-9]+);(?<kind>[0-9]+)\}/
|
31
13
|
|
32
14
|
def initialize
|
33
|
-
|
34
|
-
@
|
35
|
-
|
36
|
-
@tokens = {}
|
37
|
-
@mapped_str = []
|
15
|
+
@tokens_map = {}
|
16
|
+
@data = []
|
17
|
+
@lines = []
|
38
18
|
end
|
39
19
|
|
40
20
|
def self.init(&block)
|
@@ -42,163 +22,112 @@ module TraceVisualization
|
|
42
22
|
mapping.instance_eval(&block)
|
43
23
|
mapping
|
44
24
|
end
|
45
|
-
|
46
|
-
# new
|
47
|
-
def token(name, pattern, converter_func)
|
48
|
-
@tokens[name] = [pattern, converter_func]
|
49
|
-
end
|
50
|
-
|
51
|
-
def default_tokens
|
52
|
-
@tokens.merge!(DEFAULT_TOKENS)
|
53
|
-
end
|
54
25
|
|
55
|
-
#
|
26
|
+
# Process input data with reorder
|
56
27
|
def process(&block)
|
57
28
|
instance_eval(&block)
|
58
|
-
@max_value =
|
29
|
+
@max_value = Reorder.process(@data)
|
59
30
|
end
|
60
31
|
|
32
|
+
# Process input data without reorder
|
61
33
|
def process_without_reorder(&block)
|
62
34
|
instance_eval(&block)
|
63
35
|
end
|
64
36
|
|
65
|
-
##
|
66
|
-
# Load data from source file. File is read line by line
|
67
|
-
|
68
|
-
def from_file(path)
|
69
|
-
validate_file_name_argument(path)
|
70
|
-
|
71
|
-
open(path) do |fd|
|
72
|
-
while (line = fd.gets)
|
73
|
-
process_line(line)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
##
|
79
37
|
# Load data from preprocessed file. File is read line by line
|
80
|
-
|
81
|
-
def from_preprocessed_file(path, offset, limit, use_lexeme_table = true)
|
38
|
+
def from_file(path, offset = 0, limit = 2**32, use_lexeme_table = true)
|
82
39
|
validate_file_name_argument(path)
|
83
40
|
|
84
41
|
idx = 0
|
85
42
|
open(path) do |fd|
|
86
43
|
while (line = fd.gets)
|
87
|
-
|
44
|
+
line.chomp!
|
45
|
+
if idx >= offset && idx < offset + limit
|
46
|
+
process_line(line, use_lexeme_table)
|
47
|
+
elsif idx >= offset + limit
|
48
|
+
break
|
49
|
+
end
|
88
50
|
|
89
51
|
idx += 1
|
90
52
|
end
|
91
53
|
end
|
92
|
-
end
|
93
|
-
|
94
|
-
# new
|
95
|
-
def from_string(str)
|
96
|
-
validate_string_argument(str)
|
97
54
|
|
98
|
-
@
|
99
|
-
|
100
|
-
str.split("\n").each do |line|
|
101
|
-
process_line(line)
|
102
|
-
end
|
103
|
-
|
104
|
-
@mapped_str.pop if @mapped_str[-1].value == "\n" && str[-1] != "\n"
|
55
|
+
@data.pop
|
105
56
|
end
|
106
57
|
|
107
|
-
|
58
|
+
# Load data from string
|
59
|
+
def from_string(str, use_lexeme_table = true)
|
108
60
|
validate_string_argument(str)
|
109
61
|
|
110
62
|
str.split("\n").each do |line|
|
111
|
-
|
63
|
+
process_line(line)
|
112
64
|
end
|
65
|
+
|
66
|
+
@data.pop
|
113
67
|
end
|
114
68
|
|
115
|
-
|
116
|
-
|
69
|
+
# Process line
|
70
|
+
def process_line(line, use_lexeme_table = true)
|
71
|
+
@lines << @data.length
|
72
|
+
|
73
|
+
token_positions = []
|
117
74
|
pos = 0
|
118
|
-
while (m =
|
75
|
+
while (m = TOKEN_REGEXP.match(line, pos))
|
119
76
|
pos = m.begin(0)
|
120
77
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
pos += lexeme.lexeme_length
|
125
|
-
end
|
126
|
-
|
78
|
+
token = install_token_m(m, use_lexeme_table)
|
79
|
+
token_positions << Data::TokenPosition.new(token, pos)
|
127
80
|
|
128
|
-
|
129
|
-
while pos < line.length
|
130
|
-
lexeme = nil
|
131
|
-
if idx < lexeme_positions.size && lexeme_positions[idx].pos == pos
|
132
|
-
lexeme = lexeme_positions[idx].lexeme
|
133
|
-
idx += 1
|
134
|
-
else
|
135
|
-
lexeme = install_lexeme('CHAR', line[pos], line[pos].ord, 1, use_lexeme_table)
|
136
|
-
end
|
137
|
-
pos += lexeme.lexeme_length
|
138
|
-
@mapped_str << lexeme
|
81
|
+
pos += token.token_length
|
139
82
|
end
|
140
83
|
|
141
|
-
@mapped_str << install_lexeme('CHAR', "\n", "\n".ord, 1, use_lexeme_table)
|
142
|
-
end
|
143
|
-
|
144
|
-
# new
|
145
|
-
def process_line(line)
|
146
|
-
lexeme_poss = []
|
147
84
|
|
148
|
-
@tokens.each do |name, value|
|
149
|
-
pattern, converter_func = value
|
150
|
-
pos = 0
|
151
|
-
while (m = pattern.match(line, pos))
|
152
|
-
lexeme_string, pos = m[:lexeme], m.begin(0)
|
153
|
-
|
154
|
-
lexeme = install_lexeme(name, lexeme_string, converter_func.call(lexeme_string), lexeme_string.length)
|
155
|
-
lexeme_poss << TraceVisualization::Data::LexemePos.new(lexeme, pos)
|
156
|
-
|
157
|
-
pos += lexeme_string.length
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
lexeme_poss = TraceVisualization::LexemeOverlapFilter.process(lexeme_poss)
|
162
|
-
|
163
85
|
pos, idx = 0, 0
|
164
86
|
while pos < line.length
|
165
|
-
|
166
|
-
if idx <
|
167
|
-
|
87
|
+
token = nil
|
88
|
+
if idx < token_positions.size && token_positions[idx].pos == pos
|
89
|
+
token = token_positions[idx].token
|
168
90
|
idx += 1
|
169
91
|
else
|
170
|
-
|
92
|
+
token = install_token('CHAR', line[pos], line[pos].ord, 1, use_lexeme_table)
|
171
93
|
end
|
172
|
-
pos +=
|
173
|
-
@
|
94
|
+
pos += token.token_length
|
95
|
+
@data << token
|
174
96
|
end
|
175
97
|
|
176
|
-
@
|
98
|
+
@data << install_lf_token
|
177
99
|
end
|
178
100
|
|
179
|
-
def
|
180
|
-
|
101
|
+
def install_token(name, token_string, int_value, token_length, use_token_table = true)
|
102
|
+
name = name.intern
|
181
103
|
|
182
|
-
|
183
|
-
|
184
|
-
|
104
|
+
token = use_token_table ? @tokens_map[token_string] : nil
|
105
|
+
|
106
|
+
if token.nil?
|
107
|
+
token = Data::Token.new(name, token_string, int_value)
|
108
|
+
token.token_length = token_length
|
185
109
|
|
186
|
-
@
|
110
|
+
@tokens_map[token_string] = token if use_token_table
|
187
111
|
end
|
188
112
|
|
189
|
-
|
113
|
+
token
|
190
114
|
end
|
191
115
|
|
192
|
-
def
|
193
|
-
|
116
|
+
def install_token_m(m, use_lexeme_table = true)
|
117
|
+
install_token(m[:name], m[:source], m[:value].to_i, m.to_s.length, use_lexeme_table)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Install token with LF (line feed or end of line)
|
121
|
+
def install_lf_token
|
122
|
+
install_token('CHAR', "\n", 0x0A, 1)
|
194
123
|
end
|
195
124
|
|
196
125
|
def [](index)
|
197
|
-
@
|
126
|
+
@data[index]
|
198
127
|
end
|
199
128
|
|
200
129
|
def length
|
201
|
-
@
|
130
|
+
@data.length
|
202
131
|
end
|
203
132
|
|
204
133
|
def size
|
@@ -206,13 +135,13 @@ module TraceVisualization
|
|
206
135
|
end
|
207
136
|
|
208
137
|
def <<(object)
|
209
|
-
lexeme =
|
138
|
+
lexeme = install_token('UNKNOWN', object, object.to_i, object.to_s.length)
|
210
139
|
lexeme.ord = 0 # fake ord because Reorder already processed
|
211
|
-
@
|
140
|
+
@data << lexeme
|
212
141
|
end
|
213
142
|
|
214
143
|
def pop
|
215
|
-
@
|
144
|
+
@data.pop
|
216
145
|
end
|
217
146
|
|
218
147
|
def max
|
@@ -220,15 +149,23 @@ module TraceVisualization
|
|
220
149
|
end
|
221
150
|
|
222
151
|
def find_all
|
223
|
-
@
|
152
|
+
@data.find_all { |item| yield(item) }
|
224
153
|
end
|
225
154
|
|
226
|
-
|
227
|
-
|
155
|
+
# Restore source data
|
156
|
+
# @param pos [Integer] begin position
|
157
|
+
# @param length [Integer] the length of restore part
|
158
|
+
def restore(pos = 0, length = @data.length)
|
159
|
+
@data[pos ... pos + length].inject("") { |res, c| res += c.value }
|
228
160
|
end
|
229
161
|
|
230
162
|
def to_ary
|
231
|
-
@
|
163
|
+
@data.collect { |lexeme| lexeme.value }
|
164
|
+
end
|
165
|
+
|
166
|
+
# @return array of lines positions
|
167
|
+
def lines
|
168
|
+
@lines
|
232
169
|
end
|
233
170
|
|
234
171
|
def method_missing(name, *args, &blk)
|
@@ -236,57 +173,7 @@ module TraceVisualization
|
|
236
173
|
end
|
237
174
|
|
238
175
|
private
|
239
|
-
|
240
|
-
def parse(str)
|
241
|
-
map = {}
|
242
|
-
ppos = []
|
243
|
-
itemByPos = {}
|
244
|
-
|
245
|
-
DEFAULT_TOKENS.each do |type, patterns|
|
246
|
-
patterns.each do |pattern|
|
247
|
-
match(str, type, pattern, map, ppos, itemByPos)
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
i, j = 0, 0
|
252
|
-
result = []
|
253
|
-
|
254
|
-
ppos.sort!
|
255
|
-
|
256
|
-
while i < str.size
|
257
|
-
if i == ppos[j]
|
258
|
-
item = itemByPos[ppos[j]]
|
259
|
-
result << item
|
260
|
-
i, j = i + item.length, j + 1
|
261
|
-
else
|
262
|
-
result << Item.new(str[i], "char")
|
263
|
-
i += 1
|
264
|
-
end
|
265
|
-
end
|
266
|
-
|
267
|
-
@max_value = TraceVisualization::Reorder.process(result)
|
268
|
-
|
269
|
-
result
|
270
|
-
end
|
271
176
|
|
272
|
-
def match(str, type, pattern, map, ppos, itemByPos)
|
273
|
-
pos = 0
|
274
|
-
|
275
|
-
limit = 1000
|
276
|
-
|
277
|
-
while (m = pattern.match(str, pos))
|
278
|
-
value = m[:value]
|
279
|
-
pos = m.begin(0)
|
280
|
-
ppos << pos
|
281
|
-
|
282
|
-
map[value] = Item.new(value, type) unless map[value]
|
283
|
-
itemByPos[pos] = map[value]
|
284
|
-
|
285
|
-
pos += value.size
|
286
|
-
end
|
287
|
-
|
288
|
-
end
|
289
|
-
|
290
177
|
def validate_file_name_argument(path)
|
291
178
|
raise ArgumentError, 'Argument must be a string' if not path.instance_of? String
|
292
179
|
raise ArgumentError, 'File path is not defined' if path.empty?
|