tla-trace-filter 0.0.3

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.
@@ -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