tla-parser-s 0.1.0

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.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +75 -0
  3. data/VERSION +1 -0
  4. data/bin/tla-resolver.rb +7 -0
  5. data/lib/cli/cli.rb +90 -0
  6. data/lib/parser/exception.rb +6 -0
  7. data/lib/parser/lvalue.rb +63 -0
  8. data/lib/parser/parser.rb +129 -0
  9. data/lib/parser/parser_nodes.rb +1063 -0
  10. data/lib/parser/parser_sexp.treetop +442 -0
  11. data/lib/semantics/context.rb +355 -0
  12. data/lib/semantics/exception.rb +13 -0
  13. data/lib/semantics/resolver.rb +327 -0
  14. data/lib/semantics/symbol_table.rb +139 -0
  15. data/lib/tla-parser-s.rb +15 -0
  16. data/lib/utils/logger.rb +80 -0
  17. data/lib/utils/syntax_node.rb +73 -0
  18. data/lib/utils/version.rb +13 -0
  19. data/spec/fixtures/callables1.tla +64 -0
  20. data/spec/fixtures/directives.tla +7 -0
  21. data/spec/fixtures/resolver1/comments.tla +1 -0
  22. data/spec/fixtures/resolver1/directives.cfg +6 -0
  23. data/spec/fixtures/resolver1/directives.tla +12 -0
  24. data/spec/fixtures/resolver1/empty.tla +0 -0
  25. data/spec/fixtures/resolver1/macro1.tla +3 -0
  26. data/spec/fixtures/resolver1/macro2.tla +3 -0
  27. data/spec/fixtures/resolver1/op1.tla +3 -0
  28. data/spec/fixtures/resolver1/op2.tla +3 -0
  29. data/spec/fixtures/resolver1/proc1.tla +4 -0
  30. data/spec/fixtures/resolver1/proc2.tla +7 -0
  31. data/spec/fixtures/resolver1/proc3.tla +4 -0
  32. data/spec/fixtures/resolver1/proc4.tla +4 -0
  33. data/spec/fixtures/resolver1/proc4_hide.tla +4 -0
  34. data/spec/fixtures/resolver1/proc5.tla +4 -0
  35. data/spec/fixtures/resolver1/proc6.tla +4 -0
  36. data/spec/fixtures/resolver1/proc7.tla +4 -0
  37. data/spec/fixtures/resolver1/stmt_assert.tla +8 -0
  38. data/spec/fixtures/resolver1/stmt_assign.tla +6 -0
  39. data/spec/fixtures/resolver1/stmt_assign2.tla +6 -0
  40. data/spec/fixtures/resolver1/stmt_cond.tla +13 -0
  41. data/spec/fixtures/resolver1/stmt_either.tla +12 -0
  42. data/spec/fixtures/resolver1/stmt_print.tla +5 -0
  43. data/spec/fixtures/resolver1/var4.tla +1 -0
  44. data/spec/fixtures/resolver1/var5.tla +1 -0
  45. data/spec/fixtures/resolver1/var_choose_except.tla +2 -0
  46. data/spec/fixtures/resolver1/var_quantify.tla +4 -0
  47. data/spec/fixtures/resolver1/var_rec_except.tla +4 -0
  48. data/spec/fixtures/resolver1/var_rec_expr.tla +3 -0
  49. data/spec/fixtures/resolver1/var_record.tla +2 -0
  50. data/spec/fixtures/resolver1/var_seq.tla +1 -0
  51. data/spec/fixtures/resolver1/var_set.tla +1 -0
  52. data/spec/fixtures/resolver1/var_set_expr_map.tla +1 -0
  53. data/spec/fixtures/resolver1/var_x.tla +1 -0
  54. data/spec/fixtures/resolver1/variables.tla +4 -0
  55. data/spec/parser/parser_fixtures_spec.rb +117 -0
  56. data/spec/parser/parser_spec.rb +1649 -0
  57. data/spec/semantics/context_spec.rb +392 -0
  58. data/spec/semantics/resolver_spec.rb +364 -0
  59. data/spec/semantics/symbol_table_spec.rb +144 -0
  60. data/spec/spec_helper.rb +5 -0
  61. data/tla-parser-s.gemspec +41 -0
  62. metadata +153 -0
@@ -0,0 +1,442 @@
1
+ # coding: utf-8
2
+ grammar Sexp
3
+
4
+ # ------------------------------------------------------------------
5
+ # Default starting point we will parse TLA+ snippets
6
+
7
+ rule snippets
8
+ ( space / directive space? <Snippet>/ callable space? <Snippet> / variable space? <Snippet>)* <Snippets>
9
+ end
10
+
11
+ # ------------------------------------------------------------------
12
+ # directive
13
+
14
+ rule directive
15
+ invariants / assumptions
16
+ end
17
+
18
+ rule assumptions
19
+ 'ASSUME' space? identifier (assumption* <Assumption> ) <Assumption>
20
+ end
21
+
22
+ rule assumption
23
+ space? identifier <NonTerminal>
24
+ end
25
+
26
+ rule invariants
27
+ 'INVARIANT' space? identifier (invariant* <Invariant> ) <Invariant>
28
+ end
29
+
30
+ rule invariant
31
+ space? identifier <NonTerminal>
32
+ end
33
+
34
+
35
+ # ------------------------------------------------------------------
36
+ # callable
37
+
38
+ rule callable
39
+ procedure / macro / operator
40
+ end
41
+
42
+ rule procedure
43
+
44
+ 'procedure' space? identifier ( '(' space? identifier_list? ')' <Parameters> ) space? &'{' statement space* ';'? <Procedure>
45
+
46
+ end
47
+
48
+ rule macro
49
+
50
+ 'macro' space? identifier space?
51
+ ( '(' space? identifier_list? space? ')' space? <Parameters> )
52
+ &'{' statement ';'? <Macro>
53
+
54
+ end
55
+
56
+ rule operator
57
+ identifier space?
58
+ ( '(' space? identifier_list? ')' space? <Parameters> )?
59
+ '==' space? expression <OperatorDef>
60
+ end
61
+
62
+ # ------------------------------------------------------------------
63
+ # Formal parameters (for macro & procedure definitions)
64
+
65
+
66
+ rule identifier_list
67
+ identifier space? identifier_list_tail? <IdentifierList>
68
+ end
69
+
70
+ # Right recursive rule
71
+ rule identifier_list_tail
72
+ ',' space? identifier_list <NonTerminal>
73
+ end
74
+
75
+ # ------------------------------------------------------------------
76
+ # actual parameters
77
+
78
+ rule expression_list
79
+ expression expression_list_tail? <ExpressionList>
80
+ end
81
+
82
+ rule expression_list_tail
83
+ ',' space? expression_list <NonTerminal>
84
+ end
85
+
86
+ # ------------------------------------------------------------------
87
+ # Expression
88
+
89
+ rule expression
90
+
91
+ additive_expression space? <Expression>
92
+
93
+ end
94
+
95
+ rule additive_expression
96
+
97
+ multitive_expression space? additive_expression_tail? <AdditiveExpression>
98
+
99
+ end
100
+
101
+ rule additive_expression_tail
102
+ additive_operator space? additive_expression <AdditiveExpression>
103
+ end
104
+
105
+ rule multitive_expression
106
+
107
+ # primary_expression space? multitive_expression_tail? <MultitiveExpression>
108
+ unary_expression space? multitive_expression_tail? <MultitiveExpression>
109
+
110
+ end
111
+
112
+ rule multitive_expression_tail
113
+ multitive_operator space? multitive_expression <MultitiveExpression>
114
+ end
115
+
116
+ rule unary_expression
117
+ unary_operator space? primary_expression <UnaryExpression> / primary_expression
118
+ end
119
+
120
+
121
+ rule primary_expression
122
+ unit_expression space* ( unit_expression_tail* <UnitExpression> ) <PrimaryExpression>
123
+ end
124
+
125
+ rule unit_expression
126
+ sequence_expression / set_expression / set_expression_map / record_expression / operator_expression / quantify_expression / choose_expression
127
+ / identifier
128
+ / record_self
129
+ / original_value
130
+ / string / integer / ( '(' space? expression space? ')' <ParenthesisExpression>) <UnitExpression>
131
+
132
+ end
133
+
134
+ rule unit_expression_tail
135
+
136
+ '.' space* identifier space* <FieldByName> / '[' space* unit_expression space* ']' space* <FieldByValue>
137
+
138
+ end
139
+
140
+
141
+ rule operator_expression
142
+ identifier space? '(' space? expression_list? space? ')' <OperatorExpression>
143
+ end
144
+
145
+
146
+ rule record_expression
147
+ &( '[' space* identifier space* 'EXCEPT' ) '[' space* record_except ']' <RecordExcept>
148
+ / '[' space? record_expression_element? ']' <RecordDefinition>
149
+ end
150
+
151
+ rule record_expression_element
152
+
153
+ ( identifier space? '|->' space? expression <RecordElement>) space? record_expression_element_tail? <NonTerminal>
154
+
155
+ end
156
+
157
+ rule record_expression_element_tail
158
+ ',' space? record_expression_element <NonTerminal>
159
+ end
160
+
161
+ rule record_except
162
+ ( identifier space* 'EXCEPT' <RecordExceptIdentifier>) space* (lvalue space* '=' space* expression space* <RecordExceptField>) ( record_except_tail* <RecordExceptField>) <NonTerminal>
163
+ end
164
+
165
+ rule record_except_tail
166
+ ',' space* lvalue space* '=' space* expression <Root>
167
+ end
168
+
169
+ rule choose_expression
170
+
171
+ 'CHOOSE' space* bound_expression space* ':' space* expression <ChooseExpression>
172
+
173
+ end
174
+
175
+ rule quantify_expression
176
+ quantify_operator space? ( quantify_expression_bound+ <BindsInExpression>) ':' space? space? expression <QuantifyExpression>
177
+ end
178
+
179
+ rule quantify_expression_bound
180
+ bound_expression space? quantify_expression_bound_tail? <BindsInExpression>
181
+ end
182
+
183
+ rule quantify_expression_bound_tail
184
+ ',' space? quantify_expression_bound <BindsInExpression>
185
+ end
186
+
187
+ rule sequence_expression
188
+ '<<' space* expression_list? space* '>>' <SequenceExpression>
189
+ end
190
+
191
+ rule set_expression_map
192
+ '{' ( space* expression space* <SetExpressionDef>) ':' ( space* bound_expression <BoundInExpression> ) '}' <SetExpressionMap>
193
+
194
+ end
195
+
196
+ rule set_expression
197
+ '{' space* ( bound_expression ':' space* <BoundInExpression> )? (space* expression? <SetExpressionDef>) '}' <SetExpression>
198
+ end
199
+
200
+ rule bound_expression
201
+ identifier space* '\in' space+ 'DOMAIN'? space? expression space* <BoundInExpression>
202
+ end
203
+
204
+
205
+
206
+ # ------------------------------------------------------------------
207
+ # statement
208
+
209
+ rule statement
210
+ space* (identifier ':' space* <Label>)? unlabeled_statement space* <Statement>
211
+ end
212
+
213
+
214
+ # ------------------------------------------------------------------
215
+ # unlabeled statements
216
+
217
+ rule unlabeled_statement
218
+ goto / print / return_statement / skip / call / assignment_statement / compound_statement / assert /either / conditional / macro_call
219
+ end
220
+
221
+ rule conditional
222
+ 'if' space* '(' space* expression space* ')' space* statement conditional_else? <Conditional>
223
+ end
224
+
225
+ rule conditional_else
226
+ 'else' statement <Statement>
227
+ end
228
+
229
+ rule assignment_statement
230
+
231
+ lvalue ':=' space* expression <Assignment>
232
+
233
+ end
234
+
235
+
236
+ rule lvalue
237
+ primary_expression space* <LValue>
238
+ end
239
+
240
+
241
+ rule compound_statement
242
+ '{' space* ( compound_statement_list* <StatementList>) space* '}' <CompoundStatement>
243
+ end
244
+
245
+ rule compound_statement_list
246
+ statement ';' <StatementList>
247
+ end
248
+
249
+ rule goto
250
+ 'goto' space* identifier <Goto>
251
+ end
252
+
253
+ rule print
254
+ 'print' space* expression <Print>
255
+ end
256
+
257
+ rule either
258
+ 'either' space* statement space* (either_list+ <StatementList>) <Either>
259
+ end
260
+
261
+ rule either_list
262
+ 'or' space* statement <StatementList>
263
+ end
264
+
265
+ rule assert
266
+ 'assert' space* expression <Assert>
267
+ end
268
+
269
+ rule return_statement
270
+ 'return' <Return>
271
+ end
272
+
273
+
274
+ rule macro_call
275
+ identifier space? "(" space* expression_list? space* ")" <MacroCall>
276
+ end
277
+
278
+
279
+ rule call
280
+ 'call' space? identifier space? "(" space? expression_list? space? ")" <Call>
281
+ end
282
+
283
+ rule skip
284
+ 'skip' <Skip>
285
+ end
286
+
287
+ # ------------------------------------------------------------------
288
+ # variable
289
+
290
+ rule variable
291
+ identifier space? '=' space? expression space* ';'? <VariableDef>
292
+ end
293
+
294
+
295
+ # ------------------------------------------------------------------
296
+ # elementary
297
+
298
+ rule identifier
299
+ !reserved_word name <Identifier>
300
+ end
301
+
302
+ rule record_self
303
+ '!' <Self>
304
+ end
305
+
306
+ rule original_value
307
+ '@' <OriginalValue>
308
+ end
309
+
310
+
311
+ rule name
312
+ [_A-Za-z] [_A-Za-z0-9]*
313
+ end
314
+
315
+ rule string
316
+ '"' [^"]* '"' <StringValue>
317
+ end
318
+
319
+ rule integer
320
+ ('+'/'-')? [0-9]+ <IntegerValue>
321
+ end
322
+
323
+ # ------------------------------------------------------------------
324
+ # atoms
325
+
326
+ rule multitive_operator
327
+ '/\\' <Operator> / '/' <Operator> / '*' <Operator> / '\cap' <Operator> / '\intersect' <Operator> / '\in' <Operator>
328
+ end
329
+
330
+ rule additive_operator
331
+ "=>" <Operator> / '#' <Operator> /
332
+ '<=>' <Operator> /
333
+ '>=' <Operator> / '>' <Operator> / '=' <Operator> /
334
+ '<=' <Operator> / '<' <Operator> /
335
+ '-' <Operator> / '+' <Operator>
336
+ / '\/' <Operator> / '\cup' <Operator> / '\union' <Operator>
337
+ / '\\' <Operator>
338
+ end
339
+
340
+ rule unary_operator
341
+ '-' <Operator> / '+' <Operator> / "\\lnot" <Operator> / "~" <Operator>
342
+ end
343
+
344
+ rule quantify_operator
345
+ '\\A' <Operator> / '\\E' <Operator>
346
+ end
347
+
348
+ rule reserved_word
349
+ "ASSUME" <ReservedWord> /
350
+ "ELSE" <ReservedWord> /
351
+ "LOCAL" <ReservedWord> /
352
+ "UNION" <ReservedWord> /
353
+ "ASSUMPTION" <ReservedWord> /
354
+ "ENABLED" <ReservedWord> /
355
+ "MODULE" <ReservedWord> /
356
+ "AXIOM" <ReservedWord> /
357
+ "EXCEPT" <ReservedWord> /
358
+ "OTHER" <ReservedWord> /
359
+ "VARIABLES" <ReservedWord> /
360
+ "VARIABLE" <ReservedWord> /
361
+ "CASE" <ReservedWord> /
362
+ "EXTENDS" <ReservedWord> /
363
+ "SF_" <ReservedWord> /
364
+ "WF_" <ReservedWord> /
365
+ "CHOOSE" <ReservedWord> /
366
+ "IF" <ReservedWord> /
367
+ "SUBSET" <ReservedWord> /
368
+ "WITH" <ReservedWord> /
369
+ "INSTANCE" <ReservedWord> /
370
+ "IN" <ReservedWord> /
371
+ "THEN" <ReservedWord> /
372
+ "CONSTANTS" <ReservedWord> /
373
+ "CONSTANT" <ReservedWord> /
374
+ "THEOREM" <ReservedWord> /
375
+ "COROLLARY" <ReservedWord> /
376
+ "DOMAIN" <ReservedWord> /
377
+ "LET" <ReservedWord> /
378
+ "UNCHANGED" <ReservedWord> /
379
+ "BY" <ReservedWord> /
380
+ "HAVE" <ReservedWord> /
381
+ "QED" <ReservedWord> /
382
+ "TAKE" <ReservedWord> /
383
+ "HIDE" <ReservedWord> /
384
+ "RECURSIVE" <ReservedWord> /
385
+ "USE" <ReservedWord> /
386
+ "DEFINE" <ReservedWord> /
387
+ "PROOF" <ReservedWord> /
388
+ "WITNESS" <ReservedWord> /
389
+ "PICK" <ReservedWord> /
390
+ "DEFS" <ReservedWord> /
391
+ "DEF" <ReservedWord> /
392
+ "PROVE" <ReservedWord> /
393
+ "SUFFICES" <ReservedWord> /
394
+ "NEW" <ReservedWord> /
395
+ "LAMBDA" <ReservedWord> /
396
+ "STATE" <ReservedWord> /
397
+ "ACTION" <ReservedWord> /
398
+ "TEMPORAL" <ReservedWord> /
399
+ "OBVIOUS" <ReservedWord> /
400
+ "OMITTED" <ReservedWord> /
401
+ "LEMMA" <ReservedWord> /
402
+ "PROPOSITION" <ReservedWord> /
403
+ "ONLY" <ReservedWord>
404
+
405
+ end
406
+
407
+
408
+ # ------------------------------------------------------------------
409
+ # spaces && comments
410
+
411
+ rule space
412
+ whitespace / newline / comment
413
+ end
414
+
415
+ rule whitespace
416
+ [\s]+
417
+ end
418
+
419
+ rule newline
420
+ [\n]+
421
+ end
422
+
423
+ rule comment
424
+ line_comment / block_comment
425
+ end
426
+
427
+ # New may be missing on last line on a file
428
+ rule line_comment
429
+ '\\*' [^\n]* [\n]?
430
+ end
431
+
432
+ rule block_comment
433
+ '(*'
434
+
435
+ (
436
+ !'*)'
437
+ (. / "\n")
438
+ )*
439
+ '*)' space?
440
+ end
441
+
442
+ end
@@ -0,0 +1,355 @@
1
+ # coding: utf-8
2
+
3
+ require 'forwardable'
4
+
5
+ module TlaParserS
6
+
7
+ # ******************************************************************
8
+ #
9
+ # Manage context to parse TLA+ snippets
10
+ #
11
+ #
12
+ # Builds context in three phases:
13
+ #
14
+ # 1) Initial context includes TLA+ standard definitions e.g. TRUE, FALSE
15
+ # when context is created
16
+ # 2) Global context includes snippets defining macros, procedures,
17
+ # operators, and variables. Using pushContext/addContext
18
+ # 3) During resolve phase push to context formal parameters, quantification
19
+ # bind variables, variables in set constructor generator. Uses
20
+ # pushContext/addContext methods internally from 'resolveDefine',
21
+ #
22
+ #
23
+ # ******************************************************************
24
+
25
+ class Context
26
+
27
+ extend Forwardable # for easy delegation
28
+
29
+ attr_accessor :symbol_table
30
+
31
+ def_delegators :symbol_table, :currentContext, :dumpContext,
32
+ :popContext, :entries, :resolveModule
33
+
34
+ # ------------------------------------------------------------------
35
+ # Logger
36
+
37
+ PROGNAME = "context" # progname for logger
38
+ include TlaParserS::Utils::MyLogger # mix logger
39
+
40
+ # # TLA+ standar library symbols
41
+
42
+ # GLOABLS = %w( TRUE FALSE )
43
+
44
+
45
+ # ------------------------------------------------------------------
46
+ # constructore
47
+ def initialize( options={} )
48
+
49
+ @logger = getLogger( PROGNAME, options )
50
+ @logger.info( "#{__method__} initialized" )
51
+
52
+ initContext
53
+ end
54
+
55
+ # ------------------------------------------------------------------
56
+ # manage context
57
+
58
+ def initContext
59
+ @symbol_table = SymbolTable.new
60
+
61
+ # # create context for standar library && add entries
62
+ # @symbol_table.pushContext( nil )
63
+ # GLOABLS.each do |global|
64
+ # entry = {
65
+ # :context_type => "Init",
66
+ # :context => "Global",
67
+ # :symbol_type => "StandardLib",
68
+ # :symbol_name => global,
69
+ # }
70
+
71
+ # @symbol_table.addEntry( entry )
72
+ # end
73
+ return self
74
+ end
75
+
76
+ # Create new context in symbol table && add etnries
77
+ def initEntries( entries )
78
+
79
+ return unless entries && entries.any?
80
+
81
+ # create new context
82
+ pushContext
83
+
84
+ # add entries
85
+ entries.each do |entry|
86
+ @symbol_table.addEntry( entry )
87
+ end
88
+
89
+ end
90
+
91
+
92
+ # Add more symbols to current context levell
93
+ #
94
+ def addContext( snippets, moduleName=nil )
95
+ symbol_table.addContext( snippets, moduleName )
96
+ return self
97
+ end
98
+
99
+
100
+ # Add one level to context & and add snipets there
101
+ #
102
+ # @param snippets [SyntaxNode] implementing 'symbol_definitions` method
103
+ #
104
+ def pushContext( snippets=nil, moduleName=nil )
105
+ warn "Method symbol_definitions not implemented on #{snippets}" if snippets && !snippets.respond_to?(:symbol_definitions)
106
+ symbol_table.pushContext( snippets, moduleName )
107
+ return self
108
+ end
109
+
110
+
111
+ # @param symbol [String] to resolve
112
+ # @return [Hash] with :symbol, :resolved properties
113
+ def resolveSymbol( symbol )
114
+ resolved = symbol_table.resolveContext( symbol )
115
+ return {
116
+ :symbol => symbol,
117
+ :resolved => resolved,
118
+ }
119
+ end
120
+
121
+ # ------------------------------------------------------------------
122
+ # Resolver
123
+
124
+ # @param stmt [Statement] parse tree node for statement to resolve
125
+ # @return see 'resolveExpression'
126
+ private def resolveStatement( stmt, ret=[] )
127
+
128
+ stmt.traverse(ret) do |ret,node_type, node|
129
+ @logger.debug( "#{__method__}: enter node_type=#{node_type}, #{node.text_value}ret=#{ret}." )
130
+ case node_type
131
+ when "Statement"
132
+ when "Skip"
133
+ when "Return"
134
+ when "Goto"
135
+ when "Identifier"
136
+ @logger.debug( "#{__method__}: Identifier node=#{node.inspect}" )
137
+ ret.concat( resolveExpression( node ))
138
+ when "Conditional"
139
+ ret.concat( resolveExpression( node.condition ))
140
+ @logger.debug( "#{__method__}: Conditional if_true=#{node.if_true.inspect}" )
141
+ ret.concat( resolveStatement( node.if_true, ret ))
142
+ ret.concat( resolveStatement( node.if_not_true, ret )) if node.if_not_true
143
+ when "Either"
144
+ ret = node.choices.each { |s| resolveStatement( s, ret ) }
145
+ when "Assert"
146
+ ret.concat( resolveExpression( node.assertion ))
147
+ when "Assignment"
148
+ lvalue = node.lvalue
149
+ @logger.debug( "#{__method__}: Assignment lvalue=#{lvalue.inspect}" )
150
+ ret.concat( resolveExpression( node.lvalue.expression ) )
151
+ ret.concat( resolveExpression( node.rvalue ))
152
+ # lvalue = node.lvalue.node_value
153
+ # @logger.debug( "#{__method__}: Assign lvalue=#{lvalue}" )
154
+ # # take just first variable
155
+ # lvalue = lvalue.split( /[.\[]/ ).first
156
+ # ret << resolvedIdentifier( lvalue, symbol_table.resolveContext( lvalue ))
157
+ # # resovel expression
158
+ # ret.concat( resolveExpression( node.rvalue ))
159
+ when "Print"
160
+ @logger.debug( "#{__method__}: Print node=#{node.inspect}" )
161
+ sret = resolveExpression( node.print_expression )
162
+ @logger.debug( "#{__method__}: Print sret=#{sret}" )
163
+ ret = ret.concat( sret )
164
+ when "CompoundStatement"
165
+ ret = node.statements.each { |s| resolveStatement( s, ret ) }
166
+ # sret = []
167
+ # node.statements.each { |s| sret = resolveStatement( s, sret ) }
168
+ # ret.concat( sret )
169
+ when "MacroCall"
170
+ # resolve macro definition
171
+ ret << resolvedIdentifier( node.called, symbol_table.resolveContext( node.called ) )
172
+ # resolve actual parameters
173
+ node.actual_parameters.each do |expr_node|
174
+ eret = resolveExpression(expr_node )
175
+ @logger.debug "actual param eret=#{eret}"
176
+ ret.concat( eret )
177
+ end # actual paramtere
178
+ when "Call"
179
+ # resolve procedure definition
180
+ ret << resolvedIdentifier( node.called, symbol_table.resolveContext( node.called ) )
181
+ # resolve actual parameters
182
+ ret = node.actual_parameters.each do |expr_node|
183
+ ret.concat( resolveExpression( expr_node ))
184
+ end # actual paramtere
185
+ else
186
+ msg = "#{__method__}: Unknwon statement node type #{node_type} for node #{node.inspect}"
187
+ @logger.warn( msg )
188
+ warn msg
189
+ end
190
+ @logger.debug( "#{__method__}: leave node_type=#{node_type} ret=#{ret}." )
191
+ ret
192
+ end
193
+ ret
194
+ end # def resolveStatement( stmt )
195
+
196
+
197
+ # @return see 'resolveStatement'
198
+ def resolveDefine( defineNode )
199
+ # @logger.debug "resolveDefine starting callable=#{defineNode.inspect}"
200
+
201
+ pushContext( defineNode )
202
+ # dumpContext
203
+ if defineNode.respond_to?( :body_node ) then
204
+ @logger.info( "#{__method__} start with resolveStatement for #{defineNode.body_node}" )
205
+ if defineNode.body_node.is_a?(Sexp::Expression)
206
+ ret = resolveExpression( defineNode.body_node )
207
+ else
208
+ ret = resolveStatement( defineNode.body_node )
209
+ end
210
+ elsif defineNode.respond_to?( :init ) then
211
+ @logger.info( "#{__method__} start with resolveExpression #{defineNode.init}" )
212
+ ret = resolveExpression( defineNode.init )
213
+ @logger.debug( "#{__method__} resolveExpression-->#{ret}" )
214
+ else
215
+ msg = <<-EOS
216
+ Unknown tree node object #{defineNode}.
217
+
218
+ Should be 'Callabe' or 'VariableDef'
219
+ EOS
220
+ @logger.error( "#{__method__} #{msg}" )
221
+ raise ContextException.new msg
222
+
223
+ end
224
+
225
+ popContext()
226
+ ret
227
+ end
228
+
229
+
230
+ # @param expression [Expression] parse tree node for exprresion to resolve
231
+ # @return [Hash:Array] {:symbol,:resolved} hashes, where :resolved is the result
232
+ # of symbol table lookup
233
+ def resolveExpression( expr )
234
+
235
+ ret = []
236
+ expr && expr.traverse do |m, node_type, enode, node_val |
237
+ @logger.debug( "#{__method__} node_type=#{node_type}, node_val=#{node_val}" )
238
+ case node_type
239
+ when "Identifier"
240
+ ret << resolvedIdentifier( node_val, symbol_table.resolveContext( node_val ) )
241
+ when "AdditiveExpression", "MultitiveExpression", "UnaryExpression", "ParenthesisExpression"
242
+ when "PrimaryExpression"
243
+ sret = []
244
+ enode.attribute_accessors && enode.attribute_accessors.each do |identifier|
245
+ sret = sret.concat( resolveExpression( identifier ))
246
+ end
247
+ ret = ret.concat( sret )
248
+ when "FieldByValue"
249
+ ret << resolvedIdentifier( node_val, symbol_table.resolveContext( node_val ) )
250
+ when "FieldByName"
251
+ when "SequenceExpression"
252
+ @logger.debug( "#{__method__} SequenceExpression: enode=#{enode.inspect}" )
253
+ sret = []
254
+ enode.tuples && enode.tuples.each do |tuple_expr|
255
+ sret = sret.concat( resolveExpression( tuple_expr ))
256
+ end
257
+ ret = ret.concat( sret )
258
+ when "ChooseExpression"
259
+ @logger.debug( "#{__method__} ChooseExpression: enode=#{enode.inspect}" )
260
+ @logger.debug( "#{__method__} ChooseExpression: enode.binds_node=#{enode.binds_node}" )
261
+ # bind node defines symbol table
262
+ pushContext( enode )
263
+ choose_expression=enode.choose_expression
264
+ @logger.debug( "#{__method__} ChooseExpression: choose_expression=#{choose_expression.inspect}" )
265
+ sret = resolveExpression( choose_expression )
266
+ @logger.info( "#{__method__} ChooseExpression: resolved sret=#{sret.map {|e| { e[:symbol] => e[:resolved] ? e[:resolved][:symbol_type]+':'+e[:resolved][:context] : nil} }}" )
267
+ ret = ret.concat( sret )
268
+ popContext()
269
+ when "RecordDefinition"
270
+ @logger.debug( "#{__method__} RecordDefinition: enode=#{enode.inspect}" )
271
+ sret = []
272
+ enode.record_fields.each do |record_field|
273
+ sret = sret.concat( resolveExpression( record_field.element_expression ))
274
+ end
275
+ @logger.info( "#{__method__} RecordDefinition: resolved sret=#{sret.map {|e| { e[:symbol] => e[:resolved] ? e[:resolved][:symbol_type]+':'+e[:resolved][:context] : nil} }}" )
276
+ ret = ret.concat( sret )
277
+ when "RecordExcept"
278
+ # resolve where identier poinst
279
+ id = enode.record_identifier
280
+ ret << resolvedIdentifier( id, symbol_table.resolveContext( id ) )
281
+ @logger.debug( "#{__method__} RecordExcept: id=#{id}, ret=#{ret}" )
282
+ sret = []
283
+ # resolve EXCEPT constructor field rvalue expression
284
+ enode.record_field_definitions && enode.record_field_definitions.each do |field_definition|
285
+ sret = sret.concat( resolveExpression( field_definition.rvalue_expression ))
286
+ end
287
+ ret = ret.concat( sret )
288
+ when "SetExpressionMap"
289
+ @logger.debug( "#{__method__} SetExpressionMap: enode=#{enode.inspect}" )
290
+ # resolve set mapped
291
+ sret = resolveExpression( enode.binds_node.bind_set )
292
+ ret = ret.concat( sret )
293
+
294
+ # resolve expression in set map
295
+ pushContext( enode )
296
+ sret = resolveExpression( enode.set_expression )
297
+ @logger.debug( "#{__method__} SetExpressionMap: resolved sret=#{sret}" )
298
+ ret = ret.concat( sret )
299
+ when "SetExpression"
300
+ @logger.debug( "#{__method__} SetExpression: enode=#{enode.inspect}" )
301
+ pushContext( enode )
302
+ sret = resolveExpression( enode.set_expression )
303
+ @logger.debug( "#{__method__} SetExpression: resolved sret=#{sret}" )
304
+ ret = ret.concat( sret )
305
+ popContext( )
306
+ when "OperatorExpression"
307
+ @logger.debug( "#{__method__} OperatorExpression: enode=#{enode.inspect}" )
308
+ operator_name = enode.operator_name
309
+ ret << resolvedIdentifier( operator_name, symbol_table.resolveContext( operator_name ) )
310
+ sret = []
311
+ enode.arguments && enode.arguments.each do |argument_node|
312
+ sret = sret.concat( resolveExpression( argument_node ))
313
+ end
314
+ @logger.info( "#{__method__} OperatorExpression: resolved sret=#{sret.map {|e| { e[:symbol] => e[:resolved] ? e[:resolved][:symbol_type]+':'+e[:resolved][:context] : nil} }}" )
315
+ ret = ret.concat( sret )
316
+
317
+ when "QuantifyExpression"
318
+
319
+ @logger.debug( "#{__method__} SetExpression: node.symbol_definitions=#{enode.symbol_definitions}" )
320
+ pushContext( enode )
321
+ sret = resolveExpression( enode.binds_nodes.first.bind_set )
322
+ ret = ret.concat( sret )
323
+ @logger.debug( "#{__method__} resolved sret=#{sret}" )
324
+ @logger.debug( "#{__method__} SetExpression: #{enode.quantified_expression.inspect}" )
325
+ qret = resolveExpression( enode.quantified_expression )
326
+ @logger.debug( "#{__method__} resolved qret=#{qret}" )
327
+ ret = ret.concat( qret )
328
+ @logger.debug( "#{__method__} resolved ret=#{ret}" )
329
+ popContext( )
330
+ when "IntegerValue", "StringValue", "OriginalValue"
331
+ else
332
+
333
+ msg = "Unknwon expression node type #{node_type} with value #{node_val}"
334
+ @logger.error( "#{__method__} #{msg}" )
335
+ raise ContextException.new msg
336
+
337
+ end
338
+ end
339
+ ret
340
+ end # def resolveExpression( expr )
341
+
342
+ private
343
+ # @return {Hash} with {:sybol,:resolved} -properties
344
+ def resolvedIdentifier( identifier, resolved )
345
+ { :symbol => identifier, :resolved => resolved }
346
+ end
347
+
348
+
349
+
350
+
351
+ end # class
352
+
353
+
354
+
355
+ end