tla-trace-filter 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.org +66 -0
- data/VERSION +1 -0
- data/bin/tla-trace-filter.rb +5 -0
- data/lib/cli/cli.rb +563 -0
- data/lib/filter/filter.rb +134 -0
- data/lib/parser/grammar.treetop +132 -0
- data/lib/parser/node_extensions.rb +267 -0
- data/lib/parser/parser.rb +85 -0
- data/lib/render/render.rb +510 -0
- data/lib/tla-trace-filter.rb +6 -0
- data/lib/util/logger.rb +82 -0
- data/mustache/add-links-interface.mustache +33 -0
- data/mustache/add-links-state-dump.mustache +28 -0
- data/mustache/add-links-transition.mustache +14 -0
- data/mustache/add-links.mustache +43 -0
- data/mustache/api-call-default.mustache +14 -0
- data/mustache/api-call-init.mustache +70 -0
- data/mustache/api-call-input.mustache +20 -0
- data/mustache/api-call-link.mustache +2 -0
- data/mustache/api-call-main.mustache +86 -0
- data/mustache/api-call-output.mustache +18 -0
- data/mustache/api-call-return.mustache +13 -0
- data/mustache/api-call.mustache +34 -0
- data/spec/cli/cli_spec.rb +73 -0
- data/spec/filter/filter_spec.rb +53 -0
- data/spec/fixtures/interfaces.yaml +22 -0
- data/spec/fixtures/model.tla +1195 -0
- data/spec/fixtures/trace.txt +102 -0
- data/spec/parser/node_extensions_spec.rb +9 -0
- data/spec/parser/parser_spec.rb +392 -0
- data/spec/render/render_spec.rb +177 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/test_spec.rb +8 -0
- data/tla-trace-filter.gemspec +45 -0
- metadata +171 -0
@@ -0,0 +1,134 @@
|
|
1
|
+
module TlaTraceFilter
|
2
|
+
|
3
|
+
# Class service {#filter} acepptss lines from tla+tools trace
|
4
|
+
# output, and manages state {#state}, {#lines},
|
5
|
+
# {#stateLine}.Collaborates with {#parser} to parse state variable
|
6
|
+
# assignents in trace output {#lines}
|
7
|
+
#
|
8
|
+
class Filter
|
9
|
+
|
10
|
+
include TlaTraceFilter::Util::MyLogger
|
11
|
+
|
12
|
+
|
13
|
+
# @# @!attribute [String] stateLine line opending state space dump
|
14
|
+
attr_accessor :stateLine
|
15
|
+
|
16
|
+
# @# @!attribute [Array<String>] lines collected
|
17
|
+
attr_accessor :lines
|
18
|
+
|
19
|
+
# @# @!attribute [enum] state where filtering is in
|
20
|
+
attr_accessor :state
|
21
|
+
|
22
|
+
|
23
|
+
# @# @!attribute [Parser] parser
|
24
|
+
attr_accessor :parser
|
25
|
+
|
26
|
+
# ------------------------------------------------------------------
|
27
|
+
# @!group Constructor
|
28
|
+
|
29
|
+
def initialize(options={})
|
30
|
+
|
31
|
+
@logger = getLogger( nil, options )
|
32
|
+
@logger.info "#{__method__}: init filter"
|
33
|
+
|
34
|
+
|
35
|
+
initState( options )
|
36
|
+
end
|
37
|
+
|
38
|
+
def initState( options = {} )
|
39
|
+
self.state = :default
|
40
|
+
self.parser = TlaTraceFilter::Parser::Parser.new( options )
|
41
|
+
end
|
42
|
+
|
43
|
+
# @!endgroup
|
44
|
+
|
45
|
+
|
46
|
+
# ------------------------------------------------------------------
|
47
|
+
# @!group Class services
|
48
|
+
|
49
|
+
# Accept 'line' input and act according to {#state} :default=
|
50
|
+
# return 'line' possibly modified in place, :inStateSpace=collect
|
51
|
+
# {#lines}.
|
52
|
+
#
|
53
|
+
# @param line [String] line to filter
|
54
|
+
#
|
55
|
+
# @return [String, nil] result from filtering line, nil do not
|
56
|
+
# output
|
57
|
+
def filter(line)
|
58
|
+
case state
|
59
|
+
when :default
|
60
|
+
inDefault(line)
|
61
|
+
when :inStateSpace
|
62
|
+
inStateSpace(line)
|
63
|
+
else
|
64
|
+
raise "Unknown filter state #{state}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
# @!endgroup
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
# ------------------------------------------------------------------
|
74
|
+
# @!group Filter state machine. Valid states see {#filter}
|
75
|
+
|
76
|
+
def inDefault( line )
|
77
|
+
if line =~ /^State [0-9]+:/
|
78
|
+
enterStateSpace( line )
|
79
|
+
else
|
80
|
+
line
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def inStateSpace( line )
|
85
|
+
if line =~ /^[\s]*\n$/
|
86
|
+
return exitStateSapce
|
87
|
+
else
|
88
|
+
self.lines << line
|
89
|
+
return nil
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# @!endgroup
|
94
|
+
|
95
|
+
# ------------------------------------------------------------------
|
96
|
+
# @!group State changes
|
97
|
+
|
98
|
+
# @return [nil] nil output postponed in exit state apce
|
99
|
+
def enterStateSpace(line)
|
100
|
+
@logger.info "#{__method__}: line=#{line}"
|
101
|
+
self.stateLine = line
|
102
|
+
self.lines = []
|
103
|
+
# self.lines = [ line ]
|
104
|
+
|
105
|
+
self.state = :inStateSpace
|
106
|
+
return nil
|
107
|
+
end
|
108
|
+
|
109
|
+
# @return [Hash] hash with properties :line (String), :actionLine
|
110
|
+
# (Integer parsed), :state_space
|
111
|
+
def exitStateSapce
|
112
|
+
@logger.info "#{__method__} entering"
|
113
|
+
|
114
|
+
ret = {
|
115
|
+
:line => stateLine || "empty line",
|
116
|
+
:actionLine => stateLine[/Action line ([0-9]*)/,1].to_i,
|
117
|
+
:state_space => parser.parse( lines.join( "\n") ).value,
|
118
|
+
}
|
119
|
+
@logger.info "#{__method__} return=#{ret.to_yaml}"
|
120
|
+
self.state = :default
|
121
|
+
ret
|
122
|
+
end
|
123
|
+
|
124
|
+
# @!endgroup
|
125
|
+
|
126
|
+
# ------------------------------------------------------------------
|
127
|
+
# @!group Helpers
|
128
|
+
|
129
|
+
|
130
|
+
# @!endgroup
|
131
|
+
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module TlaTraceFilter
|
2
|
+
module Parser
|
3
|
+
grammar Grammar
|
4
|
+
|
5
|
+
# ------------------------------------------------------------------
|
6
|
+
# state_space
|
7
|
+
|
8
|
+
rule state_space
|
9
|
+
( '/\\' space variables:state_variable space* <NonTerminal> )* <StateSpace> / newline
|
10
|
+
end
|
11
|
+
|
12
|
+
rule state_variable
|
13
|
+
state_variable:name space+ "=" space+ variable_value:composite_value <StateVariable>
|
14
|
+
end
|
15
|
+
|
16
|
+
# ------------------------------------------------------------------
|
17
|
+
# Composite values
|
18
|
+
|
19
|
+
rule composite_value
|
20
|
+
set_value /
|
21
|
+
function_value / sequence_value / record_value / reserved_word / integer / string
|
22
|
+
end
|
23
|
+
|
24
|
+
rule set_value
|
25
|
+
'{' space* (value_list)? '}' <SetValue>
|
26
|
+
end
|
27
|
+
|
28
|
+
rule function_value
|
29
|
+
'(' space* (function_value_list)? ')' <FunctionValue>
|
30
|
+
end
|
31
|
+
|
32
|
+
rule sequence_value
|
33
|
+
'<<' space* (value_list)? '>>' <SequenceValue>
|
34
|
+
end
|
35
|
+
|
36
|
+
rule record_value
|
37
|
+
'[' space* (record_element_list)? ']' <RecordValue>
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
# ------------------------------------------------------------------
|
42
|
+
# Composite buiding blocks
|
43
|
+
|
44
|
+
rule record_element_list
|
45
|
+
record_element space* (record_element_list_tail)*
|
46
|
+
end
|
47
|
+
|
48
|
+
rule record_element_list_tail
|
49
|
+
',' space* record_element
|
50
|
+
end
|
51
|
+
|
52
|
+
rule record_element
|
53
|
+
element_name:name space* '|->' space* element_value:value space* <RecordElement>
|
54
|
+
end
|
55
|
+
|
56
|
+
rule function_value_list
|
57
|
+
function_value_element space* (function_value_list_tail)*
|
58
|
+
end
|
59
|
+
|
60
|
+
rule function_value_list_tail
|
61
|
+
'@@' space* function_value_element
|
62
|
+
end
|
63
|
+
|
64
|
+
rule function_value_element
|
65
|
+
domain:function_domain space* ':>' space* range:value space* <FunctionElement>
|
66
|
+
end
|
67
|
+
|
68
|
+
rule function_domain
|
69
|
+
string / integer / reserved_word
|
70
|
+
end
|
71
|
+
|
72
|
+
rule value_list
|
73
|
+
value space* (value_list_tail)*
|
74
|
+
end
|
75
|
+
|
76
|
+
rule value_list_tail
|
77
|
+
',' space* value_list
|
78
|
+
end
|
79
|
+
|
80
|
+
rule value
|
81
|
+
reserved_word / integer / string / composite_value
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
# ------------------------------------------------------------------
|
86
|
+
# atomic values
|
87
|
+
|
88
|
+
rule string
|
89
|
+
'"' string_value:[^"]* '"' <StringValue>
|
90
|
+
end
|
91
|
+
|
92
|
+
rule name
|
93
|
+
[_A-Za-z] [_A-Za-z0-9]* <Name>
|
94
|
+
end
|
95
|
+
|
96
|
+
rule integer
|
97
|
+
('+'/'-')? [0-9]+ <IntegerValue>
|
98
|
+
end
|
99
|
+
|
100
|
+
rule reserved_word
|
101
|
+
(tla_reserved_word/ sbuilder_reserved_word )
|
102
|
+
end
|
103
|
+
|
104
|
+
rule tla_reserved_word
|
105
|
+
"FALSE" <FalseValue> / "TRUE" <TrueValue>
|
106
|
+
end
|
107
|
+
|
108
|
+
rule sbuilder_reserved_word
|
109
|
+
"Nil" <NilValue> / "WildCard" <WildCardValue>
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
|
114
|
+
# ------------------------------------------------------------------
|
115
|
+
# white spaces etc
|
116
|
+
|
117
|
+
rule space
|
118
|
+
whitespace / newline
|
119
|
+
end
|
120
|
+
|
121
|
+
rule whitespace
|
122
|
+
[\s]+
|
123
|
+
end
|
124
|
+
|
125
|
+
rule newline
|
126
|
+
[\n]
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,267 @@
|
|
1
|
+
require 'set'
|
2
|
+
# Open up Treetop::Runtime::SyntaxNode to add tree traversal methods
|
3
|
+
module Treetop
|
4
|
+
module Runtime
|
5
|
+
class SyntaxNode
|
6
|
+
|
7
|
+
# ------------------------------------------------------------------
|
8
|
+
# @!group Tree traversing methods added to an opend class
|
9
|
+
|
10
|
+
|
11
|
+
# @return [s(AstSexp) nodes matching 'sym' or 'blk' returning
|
12
|
+
# true anywhere in sexp-tree
|
13
|
+
def nodes_with_match( cl=nil, &blk )
|
14
|
+
blk = ->(chldSexp) { chldSexp.class == cl } unless cl.nil?
|
15
|
+
nodes = [] # []
|
16
|
+
deep_each do |n|
|
17
|
+
found = blk[n]
|
18
|
+
nodes << n if found
|
19
|
+
found
|
20
|
+
end
|
21
|
+
nodes
|
22
|
+
end
|
23
|
+
|
24
|
+
def deep_each(prune=true, &block)
|
25
|
+
return enum_for(:deep_each) unless block_given?
|
26
|
+
|
27
|
+
each_sexp do |sexp|
|
28
|
+
found = block[sexp]
|
29
|
+
if !( prune && found )
|
30
|
+
sexp.deep_each(&block)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def each_sexp
|
36
|
+
return enum_for(:each_sexp) unless block_given?
|
37
|
+
elements && elements.each do |sexp|
|
38
|
+
# next unless Sexp === sexp
|
39
|
+
yield sexp
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# @!endgroup
|
44
|
+
|
45
|
+
|
46
|
+
end # class SyntaxNode
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
module TlaTraceFilter
|
52
|
+
module Parser
|
53
|
+
module Grammar
|
54
|
+
|
55
|
+
class Root <Treetop::Runtime::SyntaxNode
|
56
|
+
end # root
|
57
|
+
|
58
|
+
|
59
|
+
class NonTerminal <Root
|
60
|
+
end
|
61
|
+
class Terminal <Root
|
62
|
+
end
|
63
|
+
|
64
|
+
class StateSpace < NonTerminal
|
65
|
+
|
66
|
+
def value
|
67
|
+
h = state_space
|
68
|
+
h.keys.each do |variable|
|
69
|
+
h[variable] = h[variable].variable_value.value
|
70
|
+
end
|
71
|
+
h
|
72
|
+
end
|
73
|
+
|
74
|
+
def state_space
|
75
|
+
# nodes_with_match(StateVariable).each_with_index do |e, indx|
|
76
|
+
# puts ( "#{indx} e.class=#{e.class} #{e.respond_to?(:name) ? e.name : 'xx'}")
|
77
|
+
# end
|
78
|
+
nodes_with_match(StateVariable).inject( {} ) do |memo,stateVariable|
|
79
|
+
memo[stateVariable.name.to_sym] = stateVariable
|
80
|
+
memo
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
class StateVariable < NonTerminal
|
87
|
+
def name
|
88
|
+
state_variable.text_value
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# ------------------------------------------------------------------
|
93
|
+
# @!group Composites
|
94
|
+
|
95
|
+
class CompositeValue < NonTerminal
|
96
|
+
|
97
|
+
def value_childs
|
98
|
+
nodes_with_match do |n|
|
99
|
+
n.is_a?( Terminal ) ||
|
100
|
+
n.is_a?( CompositeValue) ||
|
101
|
+
n.is_a?(RecordElement) ||
|
102
|
+
n.is_a?(FunctionElement)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
class FunctionValue < CompositeValue
|
109
|
+
|
110
|
+
def value
|
111
|
+
function_value
|
112
|
+
end
|
113
|
+
|
114
|
+
def function_value
|
115
|
+
value_childs.inject({}) do |memo, functionElement|
|
116
|
+
memo = memo.merge( functionElement.value )
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
class RecordValue < CompositeValue
|
123
|
+
def value
|
124
|
+
record_value
|
125
|
+
end
|
126
|
+
|
127
|
+
def record_value
|
128
|
+
value_childs.inject({}) do |memo, recordElement|
|
129
|
+
memo = memo.merge( recordElement.value )
|
130
|
+
end
|
131
|
+
# {}
|
132
|
+
end
|
133
|
+
|
134
|
+
def record_elements
|
135
|
+
value_childs
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
class SetValue < CompositeValue
|
141
|
+
def value
|
142
|
+
set_value
|
143
|
+
end
|
144
|
+
|
145
|
+
def set_value
|
146
|
+
Set.new(set_array)
|
147
|
+
end
|
148
|
+
|
149
|
+
def set_array
|
150
|
+
value_childs.inject( [] ) do |memo, setElement|
|
151
|
+
memo << setElement.value
|
152
|
+
memo
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
class FunctionElement < NonTerminal
|
161
|
+
def value
|
162
|
+
function_element_value
|
163
|
+
end
|
164
|
+
|
165
|
+
def function_element_value
|
166
|
+
{ domain.value => range.value }
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
class RecordElement < NonTerminal
|
171
|
+
|
172
|
+
def value
|
173
|
+
record_element_value
|
174
|
+
end
|
175
|
+
|
176
|
+
def record_element_value
|
177
|
+
{ element_name.value => element_value.value }
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
class SequenceValue < CompositeValue
|
183
|
+
def value
|
184
|
+
sequence_value
|
185
|
+
end
|
186
|
+
|
187
|
+
def sequence_value
|
188
|
+
value_childs.map { |n| n.value }
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
|
193
|
+
|
194
|
+
# @!endgroup
|
195
|
+
|
196
|
+
|
197
|
+
# ------------------------------------------------------------------
|
198
|
+
# @!group Atomic values
|
199
|
+
|
200
|
+
class Name < Terminal
|
201
|
+
def value
|
202
|
+
name_value
|
203
|
+
end
|
204
|
+
def name_value
|
205
|
+
text_value
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
class LiteralValue < Terminal
|
210
|
+
def value
|
211
|
+
literal_value
|
212
|
+
end
|
213
|
+
def literal_value
|
214
|
+
text_value
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
class TrueValue < LiteralValue
|
219
|
+
def value
|
220
|
+
true
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
class FalseValue < LiteralValue
|
225
|
+
def value
|
226
|
+
false
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
class NilValue < LiteralValue
|
231
|
+
def value
|
232
|
+
nil
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
class WildCardValue < LiteralValue
|
237
|
+
def value
|
238
|
+
"*"
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
class StringValue < Terminal
|
243
|
+
def value
|
244
|
+
str_value
|
245
|
+
end
|
246
|
+
def str_value
|
247
|
+
string_value.text_value
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
class IntegerValue < Terminal
|
252
|
+
def value
|
253
|
+
int_value
|
254
|
+
end
|
255
|
+
def int_value
|
256
|
+
text_value.to_i
|
257
|
+
end
|
258
|
+
|
259
|
+
end
|
260
|
+
|
261
|
+
|
262
|
+
# @!endgroup
|
263
|
+
|
264
|
+
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|