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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/bin/trace_visualization +21 -26
  4. data/lib/trace_visualization.rb +2 -2
  5. data/lib/trace_visualization/algorithm.rb +42 -0
  6. data/lib/trace_visualization/data/irepetition.rb +5 -1
  7. data/lib/trace_visualization/data/repetition.rb +14 -6
  8. data/lib/trace_visualization/data/sorted_array.rb +44 -0
  9. data/lib/trace_visualization/data/{lexeme.rb → token.rb} +7 -8
  10. data/lib/trace_visualization/lexeme_overlap_filter.rb +18 -18
  11. data/lib/trace_visualization/mapping.rb +72 -185
  12. data/lib/trace_visualization/repetitions/concatenation.rb +136 -0
  13. data/lib/trace_visualization/repetitions/context.rb +70 -0
  14. data/lib/trace_visualization/repetitions/filter.rb +153 -0
  15. data/lib/trace_visualization/repetitions/incrementation.rb +89 -0
  16. data/lib/trace_visualization/repetitions_psy.rb +12 -5
  17. data/lib/trace_visualization/utils.rb +5 -42
  18. data/lib/trace_visualization/version.rb +1 -1
  19. data/lib/trace_visualization/visualization/console_color_print.rb +20 -4
  20. data/spec/algorithm_spec.rb +69 -0
  21. data/spec/bwt_spec.rb +2 -5
  22. data/spec/data/sorted_array_spec.rb +27 -0
  23. data/spec/lexeme_overlap_filter_spec.rb +22 -22
  24. data/spec/longest_common_prefix_spec.rb +3 -8
  25. data/spec/mapping_spec.rb +72 -69
  26. data/spec/repetitions/concatenation_spec.rb +65 -0
  27. data/spec/repetitions/filter_spec.rb +180 -0
  28. data/spec/repetitions/incrementation_spec.rb +29 -0
  29. data/spec/repetitions_psy_spec.rb +7 -16
  30. data/spec/suffix_array_spec.rb +11 -31
  31. data/spec/utils_spec.rb +21 -9
  32. data/spec/visualization/console_color_print_spec.rb +26 -0
  33. data/trace_visualization.gemspec +2 -2
  34. metadata +27 -13
  35. data/lib/trace_visualization/repetitions_concatenation.rb +0 -134
  36. data/lib/trace_visualization/repetitions_context.rb +0 -18
  37. data/spec/repetitions_concatenation_spec.rb +0 -64
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 12c27504ea6bbbabd78f47e5bee3df251a5a7050
4
- data.tar.gz: 75a0bf55e52a108f449def1998de4fbf319d1f94
3
+ metadata.gz: 2fee2d1c5c6920d3966ae5190b05bcb40ce2b359
4
+ data.tar.gz: c8cb276ef0bfef1d293b996bd236c4d1cdc6f1b7
5
5
  SHA512:
6
- metadata.gz: f6fff098106b2ba908595a05345bebafc5686348454061983671c937c21a26ecb0cee59a8d6209203707949e7283daba5d620b7d386cd1ac230e021668f4a7f5
7
- data.tar.gz: 6e39264b5f0141746d7fda75d4c2c2be624a0829c12ed548160e6bd9f74afac162b06a6e9e670155ef042f7b7baf65eb0bff43a42236051f0aec81b15842495c
6
+ metadata.gz: 9dc0447760f9d5b95f27ec88e95bde2beb73037f36cb3af6d6aa4a324d17afa348e7462735e9a14e78aefdf9c779bb446beaaca5a249af32e467d4b14695f32f
7
+ data.tar.gz: d9b3c4ce306cd563ab394104fec2e85654e8bc55e8592a64ff7367a8269b7b33635f16412eba65af404c1eb2b790f9986c820a6fbb0aa483bbfbf155774e590b
data/Gemfile CHANGED
@@ -2,7 +2,7 @@ source 'https://rubygems.org'
2
2
 
3
3
  ruby '2.0.0'
4
4
 
5
- gem 'trace_preprocessor', "~> 0.0.2"
5
+ gem 'trace_preprocessor'
6
6
 
7
7
  # Specify your gem's dependencies in trace_visualization.gemspec
8
8
  gemspec
@@ -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 = TraceVisualization::Mapping.new
79
- mapping.process_without_reorder { from_preprocessed_file(tmp_file.path, options[:offset], options[:limit], !options[:test_preprocessor_performance]) }
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
- rs = nil
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
- #context = nil
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
- RepetitionsScore.fill_score(rs, :sort => true, :order => 'desc', :version => 'relative')
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
- rs[0 ... options[:out]].each do |r|
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
- rs
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)
@@ -5,7 +5,7 @@
5
5
  reorder
6
6
  repetitions
7
7
  repetitions_psy
8
- repetitions_context
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
- from_preprocessed_file options[:file_name]
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
- attr_reader :left_positions, :right_positions
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 Lexeme
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 LEXEME_REGEXP)
9
- attr_accessor :lexeme_length
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 LexemePos
51
- attr_accessor :lexeme
52
- attr_accessor :pos
50
+ class TokenPosition
51
+ attr_accessor :token, :pos
53
52
 
54
- def initialize(lexeme, pos)
55
- @lexeme, @pos = lexeme, pos
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(lexeme_poss)
5
- lexeme_poss.sort! { |a, b| a.pos <=> b.pos }
6
- left_bound = lexeme_poss.inject(0) do |left_bound, lexeme_pos|
7
- [lexeme_pos.pos + lexeme_pos.lexeme.length, left_bound].max
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
- lexeme_pos = current[i]
16
+ token_pos = current[i]
17
17
 
18
- if lexeme_pos.pos + lexeme_pos.lexeme.length == pos
19
- fl_delete_lexeme = false
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 << lexeme_pos
23
- fl_delete_lexeme = true
22
+ result << token_pos
23
+ fl_delete_token = true
24
24
  else
25
- if is_longest_lexeme(current, lexeme_pos)
26
- result << lexeme_pos
25
+ if is_longest_token(current, token_pos)
26
+ result << token_pos
27
27
  current = []
28
28
  else
29
- fl_delete_lexeme = true
29
+ fl_delete_token = true
30
30
  end
31
31
  end
32
32
 
33
- if fl_delete_lexeme
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 < lexeme_poss.size && lexeme_poss[idx].pos == pos
43
- current << lexeme_poss[idx]
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.is_longest_lexeme(lexeme_poss, lexeme_pos)
51
+ def self.is_longest_token(token_positions, token_pos)
52
52
  result = true
53
53
 
54
- lexeme_poss.each do |other_lexeme_pos|
55
- if lexeme_pos != other_lexeme_pos && lexeme_pos.lexeme.length < other_lexeme_pos.lexeme.length
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/lexeme'
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
- # hash map: lexeme-object by lexeme-string
34
- @lexeme_table = {}
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
- # new
26
+ # Process input data with reorder
56
27
  def process(&block)
57
28
  instance_eval(&block)
58
- @max_value = TraceVisualization::Reorder.process(@mapped_str)
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
- process_preprocessed_line(line, use_lexeme_table) if (idx >= offset && idx < offset + limit)
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
- @str = str
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
- def from_preprocessed_string(str, use_lexeme_table = true)
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
- process_preprocessed_line(line)
63
+ process_line(line)
112
64
  end
65
+
66
+ @data.pop
113
67
  end
114
68
 
115
- def process_preprocessed_line(line, use_lexeme_table = true)
116
- lexeme_positions = []
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 = LEXEME_REGEXP.match(line, pos))
75
+ while (m = TOKEN_REGEXP.match(line, pos))
119
76
  pos = m.begin(0)
120
77
 
121
- lexeme = install_lexeme_m(m, use_lexeme_table)
122
- lexeme_positions << TraceVisualization::Data::LexemePos.new(lexeme, pos)
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
- pos, idx = 0, 0
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
- lexeme = nil
166
- if idx < lexeme_poss.size && lexeme_poss[idx].pos == pos
167
- lexeme = lexeme_poss[idx].lexeme
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
- lexeme = install_lexeme('CHAR', line[pos], line[pos].ord, 1)
92
+ token = install_token('CHAR', line[pos], line[pos].ord, 1, use_lexeme_table)
171
93
  end
172
- pos += lexeme.length
173
- @mapped_str << lexeme
94
+ pos += token.token_length
95
+ @data << token
174
96
  end
175
97
 
176
- @mapped_str << install_lexeme('CHAR', "\n", "\n".ord, 1)
98
+ @data << install_lf_token
177
99
  end
178
100
 
179
- def install_lexeme(name, lexeme_string, int_value, lexeme_length, use_lexeme_table = true)
180
- lexeme = use_lexeme_table ? @lexeme_table[lexeme_string] : nil
101
+ def install_token(name, token_string, int_value, token_length, use_token_table = true)
102
+ name = name.intern
181
103
 
182
- if lexeme.nil?
183
- lexeme = TraceVisualization::Data::Lexeme.new(name, lexeme_string, int_value)
184
- lexeme.lexeme_length = lexeme_length
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
- @lexeme_table[lexeme_string] = lexeme if use_lexeme_table
110
+ @tokens_map[token_string] = token if use_token_table
187
111
  end
188
112
 
189
- lexeme
113
+ token
190
114
  end
191
115
 
192
- def install_lexeme_m(m, use_lexeme_table = true)
193
- install_lexeme(m[:name], m[:source], m[:value].to_i, m.to_s.length, use_lexeme_table)
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
- @mapped_str[index]
126
+ @data[index]
198
127
  end
199
128
 
200
129
  def length
201
- @mapped_str.length
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 = install_lexeme('UNKNOWN', object, object.to_i, object.to_s.length)
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
- @mapped_str << lexeme
140
+ @data << lexeme
212
141
  end
213
142
 
214
143
  def pop
215
- @mapped_str.pop
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
- @mapped_str.find_all { |item| yield(item) }
152
+ @data.find_all { |item| yield(item) }
224
153
  end
225
154
 
226
- def restore(pos = 0, length = @mapped_str.length)
227
- @mapped_str[pos ... pos + length].inject("") { |res, c| res += c.value }
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
- @mapped_str.collect { |lexeme| lexeme.value }
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?