lrama 0.5.3 → 0.5.5
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.
- checksums.yaml +4 -4
- data/.github/workflows/test.yaml +24 -1
- data/Gemfile +3 -2
- data/README.md +11 -1
- data/doc/TODO.md +5 -1
- data/exe/lrama +0 -1
- data/lib/lrama/command.rb +5 -10
- data/lib/lrama/context.rb +0 -2
- data/lib/lrama/counterexamples/derivation.rb +63 -0
- data/lib/lrama/counterexamples/example.rb +124 -0
- data/lib/lrama/counterexamples/path.rb +69 -0
- data/lib/lrama/counterexamples/state_item.rb +6 -0
- data/lib/lrama/counterexamples/triple.rb +21 -0
- data/lib/lrama/counterexamples.rb +283 -0
- data/lib/lrama/digraph.rb +2 -3
- data/lib/lrama/grammar/auxiliary.rb +7 -0
- data/lib/lrama/grammar/code.rb +0 -1
- data/lib/lrama/grammar/rule.rb +6 -0
- data/lib/lrama/grammar/symbol.rb +4 -11
- data/lib/lrama/grammar.rb +44 -8
- data/lib/lrama/lexer/token/type.rb +8 -0
- data/lib/lrama/lexer/token.rb +4 -2
- data/lib/lrama/lexer.rb +3 -4
- data/lib/lrama/output.rb +1 -1
- data/lib/lrama/parser/token_scanner.rb +3 -6
- data/lib/lrama/parser.rb +9 -0
- data/lib/lrama/state/reduce_reduce_conflict.rb +9 -0
- data/lib/lrama/state/shift_reduce_conflict.rb +9 -0
- data/lib/lrama/state.rb +11 -4
- data/lib/lrama/states/item.rb +38 -2
- data/lib/lrama/states.rb +28 -34
- data/lib/lrama/states_reporter.rb +29 -16
- data/lib/lrama/type.rb +4 -0
- data/lib/lrama/version.rb +1 -1
- data/lib/lrama.rb +2 -0
- data/template/bison/yacc.c +103 -95
- metadata +13 -2
    
        data/lib/lrama/states/item.rb
    CHANGED
    
    | @@ -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  | 
| 28 | 
            -
                    rule.rhs[position | 
| 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 | 
            -
                   | 
| 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 | 
            -
                   | 
| 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 | 
            -
                   | 
| 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 | 
            -
                   | 
| 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:: | 
| 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 | 
            -
                     | 
| 493 | 
            +
                    count = state.reduces.count
         | 
| 505 494 |  | 
| 506 | 
            -
                     | 
| 507 | 
            -
                       | 
| 495 | 
            +
                    for i in 0...count do
         | 
| 496 | 
            +
                      reduce1 = state.reduces[i]
         | 
| 497 | 
            +
                      next if reduce1.look_ahead.nil?
         | 
| 508 498 |  | 
| 509 | 
            -
                       | 
| 510 | 
            -
             | 
| 499 | 
            +
                      for j in (i+1)...count do
         | 
| 500 | 
            +
                        reduce2 = state.reduces[j]
         | 
| 501 | 
            +
                        next if reduce2.look_ahead.nil?
         | 
| 511 502 |  | 
| 512 | 
            -
             | 
| 513 | 
            -
             | 
| 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. | 
| 523 | 
            +
                    end.min_by do |rule, rule_id, count|
         | 
| 530 524 | 
             
                      [-count, rule_id]
         | 
| 531 | 
            -
                    end.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 | 
| 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
    
    
    
        data/lib/lrama/version.rb
    CHANGED
    
    
    
        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"
         |