lrama 0.5.3 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,20 +12,56 @@ module Lrama
12
12
  rule.id
13
13
  end
14
14
 
15
+ def empty_rule?
16
+ rule.empty_rule?
17
+ end
18
+
19
+ def number_of_rest_symbols
20
+ rule.rhs.count - position
21
+ end
22
+
23
+ def lhs
24
+ rule.lhs
25
+ end
26
+
15
27
  def next_sym
16
28
  rule.rhs[position]
17
29
  end
18
30
 
31
+ def next_next_sym
32
+ rule.rhs[position + 1]
33
+ end
34
+
35
+ def previous_sym
36
+ rule.rhs[position - 1]
37
+ end
38
+
19
39
  def end_of_rule?
20
40
  rule.rhs.count == position
21
41
  end
22
42
 
43
+ def beginning_of_rule?
44
+ position == 0
45
+ end
46
+
47
+ def start_item?
48
+ rule.id == 0 && position == 0
49
+ end
50
+
23
51
  def new_by_next_position
24
52
  Item.new(rule: rule, position: position + 1)
25
53
  end
26
54
 
27
- def previous_sym
28
- rule.rhs[position - 1]
55
+ def symbols_before_dot
56
+ rule.rhs[0...position]
57
+ end
58
+
59
+ def symbols_after_dot
60
+ rule.rhs[position..-1]
61
+ end
62
+
63
+ def to_s
64
+ "#{lhs.id.s_value}: #{display_name}"
29
65
  end
30
66
 
31
67
  def display_name
data/lib/lrama/states.rb CHANGED
@@ -102,43 +102,27 @@ module Lrama
102
102
  end
103
103
 
104
104
  def direct_read_sets
105
- h = {}
106
-
107
- @direct_read_sets.each do |k, v|
108
- h[k] = bitmap_to_terms(v)
105
+ @direct_read_sets.transform_values do |v|
106
+ bitmap_to_terms(v)
109
107
  end
110
-
111
- return h
112
108
  end
113
109
 
114
110
  def read_sets
115
- h = {}
116
-
117
- @read_sets.each do |k, v|
118
- h[k] = bitmap_to_terms(v)
111
+ @read_sets.transform_values do |v|
112
+ bitmap_to_terms(v)
119
113
  end
120
-
121
- return h
122
114
  end
123
115
 
124
116
  def follow_sets
125
- h = {}
126
-
127
- @follow_sets.each do |k, v|
128
- h[k] = bitmap_to_terms(v)
117
+ @follow_sets.transform_values do |v|
118
+ bitmap_to_terms(v)
129
119
  end
130
-
131
- return h
132
120
  end
133
121
 
134
122
  def la
135
- h = {}
136
-
137
- @la.each do |k, v|
138
- h[k] = bitmap_to_terms(v)
123
+ @la.transform_values do |v|
124
+ bitmap_to_terms(v)
139
125
  end
140
-
141
- return h
142
126
  end
143
127
 
144
128
  private
@@ -452,7 +436,7 @@ module Lrama
452
436
 
453
437
  # Can resolve only when both have prec
454
438
  unless shift_prec && reduce_prec
455
- state.conflicts << State::Conflict.new(symbols: [sym], reduce: reduce, type: :shift_reduce)
439
+ state.conflicts << State::ShiftReduceConflict.new(symbols: [sym], shift: shift, reduce: reduce)
456
440
  next
457
441
  end
458
442
 
@@ -471,6 +455,11 @@ module Lrama
471
455
 
472
456
  # shift_prec == reduce_prec, then check associativity
473
457
  case sym.precedence.type
458
+ when :precedence
459
+ # %precedence only specifies precedence and not specify associativity
460
+ # then a conflict is unresolved if precedence is same.
461
+ state.conflicts << State::ShiftReduceConflict.new(symbols: [sym], shift: shift, reduce: reduce)
462
+ next
474
463
  when :right
475
464
  # Shift is selected
476
465
  state.resolved_conflicts << State::ResolvedConflict.new(symbol: sym, reduce: reduce, which: :shift, same_prec: true)
@@ -501,16 +490,21 @@ module Lrama
501
490
 
502
491
  def compute_reduce_reduce_conflicts
503
492
  states.each do |state|
504
- a = []
493
+ count = state.reduces.count
505
494
 
506
- state.reduces.each do |reduce|
507
- next if reduce.look_ahead.nil?
495
+ for i in 0...count do
496
+ reduce1 = state.reduces[i]
497
+ next if reduce1.look_ahead.nil?
508
498
 
509
- intersection = a & reduce.look_ahead
510
- a += reduce.look_ahead
499
+ for j in (i+1)...count do
500
+ reduce2 = state.reduces[j]
501
+ next if reduce2.look_ahead.nil?
511
502
 
512
- if !intersection.empty?
513
- state.conflicts << State::Conflict.new(symbols: intersection.dup, reduce: reduce, type: :reduce_reduce)
503
+ intersection = reduce1.look_ahead & reduce2.look_ahead
504
+
505
+ if !intersection.empty?
506
+ state.conflicts << State::ReduceReduceConflict.new(symbols: intersection, reduce1: reduce1, reduce2: reduce2)
507
+ end
514
508
  end
515
509
  end
516
510
  end
@@ -526,9 +520,9 @@ module Lrama
526
520
 
527
521
  state.default_reduction_rule = state.reduces.map do |r|
528
522
  [r.rule, r.rule.id, (r.look_ahead || []).count]
529
- end.sort_by do |rule, rule_id, count|
523
+ end.min_by do |rule, rule_id, count|
530
524
  [-count, rule_id]
531
- end.first.first
525
+ end.first
532
526
  end
533
527
  end
534
528
 
@@ -14,13 +14,13 @@ module Lrama
14
14
 
15
15
  private
16
16
 
17
- def _report(io, grammar: false, states: false, itemsets: false, lookaheads: false, solved: false, verbose: false)
17
+ def _report(io, grammar: false, states: false, itemsets: false, lookaheads: false, solved: false, counterexamples: false, verbose: false)
18
18
  # TODO: Unused terms
19
19
  # TODO: Unused rules
20
20
 
21
21
  report_conflicts(io)
22
22
  report_grammar(io) if grammar
23
- report_states(io, itemsets, lookaheads, solved, verbose)
23
+ report_states(io, itemsets, lookaheads, solved, counterexamples, verbose)
24
24
  end
25
25
 
26
26
  def report_conflicts(io)
@@ -71,7 +71,11 @@ module Lrama
71
71
  io << "\n\n"
72
72
  end
73
73
 
74
- def report_states(io, itemsets, lookaheads, solved, verbose)
74
+ def report_states(io, itemsets, lookaheads, solved, counterexamples, verbose)
75
+ if counterexamples
76
+ cex = Counterexamples.new(@states)
77
+ end
78
+
75
79
  @states.states.each do |state|
76
80
  # Report State
77
81
  io << "State #{state.id}\n\n"
@@ -106,7 +110,6 @@ module Lrama
106
110
  end
107
111
  io << "\n"
108
112
 
109
-
110
113
  # Report shifts
111
114
  tmp = state.term_transitions.select do |shift, _|
112
115
  !shift.not_selected
@@ -119,7 +122,6 @@ module Lrama
119
122
  end
120
123
  io << "\n" if !tmp.empty?
121
124
 
122
-
123
125
  # Report error caused by %nonassoc
124
126
  nl = false
125
127
  tmp = state.resolved_conflicts.select do |resolved|
@@ -134,7 +136,6 @@ module Lrama
134
136
  end
135
137
  io << "\n" if !tmp.empty?
136
138
 
137
-
138
139
  # Report reduces
139
140
  nl = false
140
141
  max_len = state.non_default_reduces.flat_map(&:look_ahead).compact.map(&:display_name).map(&:length).max || 0
@@ -167,7 +168,6 @@ module Lrama
167
168
  end
168
169
  io << "\n" if nl
169
170
 
170
-
171
171
  # Report nonterminal transitions
172
172
  tmp = []
173
173
  max_len = 0
@@ -185,7 +185,6 @@ module Lrama
185
185
  end
186
186
  io << "\n" if !tmp.empty?
187
187
 
188
-
189
188
  if solved
190
189
  # Report conflict resolutions
191
190
  state.resolved_conflicts.each do |resolved|
@@ -194,6 +193,27 @@ module Lrama
194
193
  io << "\n" if !state.resolved_conflicts.empty?
195
194
  end
196
195
 
196
+ if counterexamples && state.has_conflicts?
197
+ # Report counterexamples
198
+ examples = cex.compute(state)
199
+ examples.each do |example|
200
+ label0 = example.type == :shift_reduce ? "shift/reduce" : "reduce/reduce"
201
+ label1 = example.type == :shift_reduce ? "Shift derivation" : "First Reduce derivation"
202
+ label2 = example.type == :shift_reduce ? "Reduce derivation" : "Second Reduce derivation"
203
+
204
+ io << " #{label0} conflict on token #{example.conflict_symbol.id.s_value}:\n"
205
+ io << " #{example.path1_item}\n"
206
+ io << " #{example.path2_item}\n"
207
+ io << " #{label1}\n"
208
+ example.derivations1.render_strings_for_report.each do |str|
209
+ io << " #{str}\n"
210
+ end
211
+ io << " #{label2}\n"
212
+ example.derivations2.render_strings_for_report.each do |str|
213
+ io << " #{str}\n"
214
+ end
215
+ end
216
+ end
197
217
 
198
218
  if verbose
199
219
  # Report direct_read_sets
@@ -209,7 +229,6 @@ module Lrama
209
229
  end
210
230
  io << "\n"
211
231
 
212
-
213
232
  # Report reads_relation
214
233
  io << " [Reads Relation]\n"
215
234
  @states.nterms.each do |nterm|
@@ -223,7 +242,6 @@ module Lrama
223
242
  end
224
243
  io << "\n"
225
244
 
226
-
227
245
  # Report read_sets
228
246
  io << " [Read sets]\n"
229
247
  read_sets = @states.read_sets
@@ -238,7 +256,6 @@ module Lrama
238
256
  end
239
257
  io << "\n"
240
258
 
241
-
242
259
  # Report includes_relation
243
260
  io << " [Includes Relation]\n"
244
261
  @states.nterms.each do |nterm|
@@ -252,7 +269,6 @@ module Lrama
252
269
  end
253
270
  io << "\n"
254
271
 
255
-
256
272
  # Report lookback_relation
257
273
  io << " [Lookback Relation]\n"
258
274
  @states.rules.each do |rule|
@@ -261,12 +277,11 @@ module Lrama
261
277
 
262
278
  a.each do |state_id2, nterm_id2|
263
279
  n = @states.nterms.find {|n| n.token_id == nterm_id2 }
264
- io << " (Rule: #{rule.to_s}) -> (State #{state_id2}, #{n.id.s_value})\n"
280
+ io << " (Rule: #{rule}) -> (State #{state_id2}, #{n.id.s_value})\n"
265
281
  end
266
282
  end
267
283
  io << "\n"
268
284
 
269
-
270
285
  # Report follow_sets
271
286
  io << " [Follow sets]\n"
272
287
  follow_sets = @states.follow_sets
@@ -281,7 +296,6 @@ module Lrama
281
296
  end
282
297
  io << "\n"
283
298
 
284
-
285
299
  # Report LA
286
300
  io << " [Look-Ahead Sets]\n"
287
301
  tmp = []
@@ -301,7 +315,6 @@ module Lrama
301
315
  io << "\n" if !tmp.empty?
302
316
  end
303
317
 
304
-
305
318
  # End of Report State
306
319
  io << "\n"
307
320
  end
data/lib/lrama/type.rb ADDED
@@ -0,0 +1,4 @@
1
+ module Lrama
2
+ class Type < Struct.new(:id, :tag, keyword_init: true)
3
+ end
4
+ end
data/lib/lrama/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Lrama
2
- VERSION = "0.5.3".freeze
2
+ VERSION = "0.5.5".freeze
3
3
  end
data/lib/lrama.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require "lrama/bitmap"
2
2
  require "lrama/command"
3
3
  require "lrama/context"
4
+ require "lrama/counterexamples"
4
5
  require "lrama/digraph"
5
6
  require "lrama/grammar"
6
7
  require "lrama/lexer"
@@ -10,5 +11,6 @@ require "lrama/report"
10
11
  require "lrama/state"
11
12
  require "lrama/states"
12
13
  require "lrama/states_reporter"
14
+ require "lrama/type"
13
15
  require "lrama/version"
14
16
  require "lrama/warning"