trace_visualization 0.0.3 → 0.0.5
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 +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?
|