diff --git a/bin/racc b/bin/racc index a1b3c040..17be1663 100755 --- a/bin/racc +++ b/bin/racc @@ -193,6 +193,9 @@ def main end profiler.report + if states.should_error_on_expect_mismatch? + raise Racc::CompileError, "#{states.grammar.n_expected_srconflicts} shift/reduce conflicts are expected but #{states.n_srconflicts} shift/reduce conflicts exist" + end rescue Racc::Error, Errno::ENOENT, Errno::EPERM => err raise if $DEBUG or debug_flags.any? lineno = err.message.slice(/\A\d+:/).to_s diff --git a/lib/racc/grammar.rb b/lib/racc/grammar.rb index 8519763c..878aaf75 100644 --- a/lib/racc/grammar.rb +++ b/lib/racc/grammar.rb @@ -27,6 +27,7 @@ def initialize(debug_flags = DebugFlags.new) @rules = [] # :: [Rule] @start = nil @n_expected_srconflicts = nil + @error_on_expect_mismatch = nil @prec_table = [] @prec_table_closed = false @closed = false @@ -36,6 +37,7 @@ def initialize(debug_flags = DebugFlags.new) attr_reader :start attr_reader :symboltable attr_accessor :n_expected_srconflicts + attr_accessor :error_on_expect_mismatch def [](x) @rules[x] diff --git a/lib/racc/grammarfileparser.rb b/lib/racc/grammarfileparser.rb index 86117754..ec6faa4f 100644 --- a/lib/racc/grammarfileparser.rb +++ b/lib/racc/grammarfileparser.rb @@ -76,6 +76,9 @@ module Racc raise CompileError, "`expect' seen twice" end @grammar.n_expected_srconflicts = num + }\ + | seq(:ERROR_ON_EXPECT_MISMATCH) {|*| + @grammar.error_on_expect_mismatch = true } g.convdef = seq(:symbol, :STRING) {|sym, code| @@ -493,6 +496,7 @@ def next_line 'options' => :OPTION, 'start' => :START, 'expect' => :EXPECT, + 'error_on_expect_mismatch' => :ERROR_ON_EXPECT_MISMATCH, 'class' => :CLASS, 'rule' => :RULE, 'end' => :END diff --git a/lib/racc/state.rb b/lib/racc/state.rb index f85809fb..d678cf28 100644 --- a/lib/racc/state.rb +++ b/lib/racc/state.rb @@ -73,6 +73,10 @@ def should_report_srconflict? (n_srconflicts() != @grammar.n_expected_srconflicts) end + def should_error_on_expect_mismatch? + should_report_srconflict? && @grammar.error_on_expect_mismatch + end + def srconflict_exist? n_srconflicts() != 0 end diff --git a/test/assets/error_on_expect_mismatch.y b/test/assets/error_on_expect_mismatch.y new file mode 100644 index 00000000..a477e7bd --- /dev/null +++ b/test/assets/error_on_expect_mismatch.y @@ -0,0 +1,8 @@ +class E + expect 0 + error_on_expect_mismatch +rule + list: inlist inlist + inlist: + | A +end diff --git a/test/test_racc_command.rb b/test/test_racc_command.rb index f8f3856e..4fd6ac38 100644 --- a/test/test_racc_command.rb +++ b/test/test_racc_command.rb @@ -108,6 +108,13 @@ def test_expect_y assert_debugfile 'expect.y', [1,0,0,0,1] end + def test_error_on_expect_mismatch + assert_raise_with_message(Test::Unit::AssertionFailedError, /0 shift\/reduce conflicts are expected but 1 shift\/reduce conflicts exist/) { + assert_compile 'error_on_expect_mismatch.y' + } + assert_debugfile 'error_on_expect_mismatch.y', [1,0,0,0,0] + end + def test_nullbug1_y assert_compile 'nullbug1.y' assert_debugfile 'nullbug1.y', [0,0,0,0]