summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/racc/grammar.rb34
-rwxr-xr-xlibexec/racc39
-rw-r--r--test/racc/assets/ifelse.y14
-rw-r--r--test/racc/test_racc_command.rb15
4 files changed, 77 insertions, 25 deletions
diff --git a/lib/racc/grammar.rb b/lib/racc/grammar.rb
index fa81534338..3444dfcce3 100644
--- a/lib/racc/grammar.rb
+++ b/lib/racc/grammar.rb
@@ -86,14 +86,15 @@ module Racc
end
def n_useless_nonterminals
- @n_useless_nonterminals ||=
- begin
- n = 0
- @symboltable.each_nonterminal do |sym|
- n += 1 if sym.useless?
- end
- n
- end
+ @n_useless_nonterminals ||= each_useless_nonterminal.count
+ end
+
+ def each_useless_nonterminal
+ return to_enum __method__ unless block_given?
+
+ @symboltable.each_nonterminal do |sym|
+ yield sym if sym.useless?
+ end
end
def useless_rule_exist?
@@ -101,14 +102,15 @@ module Racc
end
def n_useless_rules
- @n_useless_rules ||=
- begin
- n = 0
- each do |r|
- n += 1 if r.useless?
- end
- n
- end
+ @n_useless_rules ||= each_useless_rule.count
+ end
+
+ def each_useless_rule
+ return to_enum __method__ unless block_given?
+
+ each do |r|
+ yield r if r.useless?
+ end
end
def nfa
diff --git a/libexec/racc b/libexec/racc
index 0f0f642cd6..2edd6bb07b 100755
--- a/libexec/racc
+++ b/libexec/racc
@@ -1,6 +1,6 @@
#!/usr/bin/env ruby
#
-# $Id$
+#
#
# Copyright (c) 1999-2006 Minero Aoki
#
@@ -184,8 +184,12 @@ def main
log_useless states.grammar
log_conflict states
else
- report_useless states.grammar
- report_conflict states
+ has_useless = report_useless states.grammar
+ has_conflicts = report_conflict states
+ if has_useless || has_conflicts
+ preamble = make_logfile ? 'C' : 'Turn on logging with "-v" and c'
+ $stderr.puts %Q{#{preamble}heck ".output" file for details}
+ end
end
profiler.report
@@ -201,13 +205,29 @@ def make_filename(path, suffix)
path.sub(/(?:\..*?)?\z/, suffix)
end
+LIST_LIMIT = 10
+def report_list(enum, label)
+ c = enum.count
+ if c > 0
+ $stderr.puts "#{c} #{label}:"
+ enum.first(LIST_LIMIT).each do |item|
+ $stderr.puts " #{yield item}"
+ end
+ $stderr.puts " ..." if c > LIST_LIMIT
+ end
+end
+
+# @return [Boolean] if anything was reported
def report_conflict(states)
if states.should_report_srconflict?
+ reported = true
$stderr.puts "#{states.n_srconflicts} shift/reduce conflicts"
end
if states.rrconflict_exist?
+ reported = true
$stderr.puts "#{states.n_rrconflicts} reduce/reduce conflicts"
end
+ reported
end
def log_conflict(states)
@@ -222,16 +242,17 @@ def log_conflict(states)
}
end
+# @return [Boolean] if anything was reported
def report_useless(grammar)
- if grammar.useless_nonterminal_exist?
- $stderr.puts "#{grammar.n_useless_nonterminals} useless nonterminals"
- end
- if grammar.useless_rule_exist?
- $stderr.puts "#{grammar.n_useless_rules} useless rules"
- end
+ reported = report_list(grammar.each_useless_nonterminal, 'useless nonterminals', &:to_s)
+
+ reported ||= report_list(grammar.each_useless_rule, 'useless rules') { |r| "##{r.ident} (#{r.target})" }
+
if grammar.start.useless?
$stderr.puts 'fatal: start symbol does not derive any sentence'
+ reported = true
end
+ reported
end
def log_useless(grammar)
diff --git a/test/racc/assets/ifelse.y b/test/racc/assets/ifelse.y
new file mode 100644
index 0000000000..18dbe4b1a7
--- /dev/null
+++ b/test/racc/assets/ifelse.y
@@ -0,0 +1,14 @@
+class C::Parser
+token tSOMETHING
+rule
+ statement
+ : tSOMETHING
+ | 'if' statement 'then' statement
+ | 'if' statement 'then' statement 'else' statement
+ ;
+
+ dummy
+ : tSOMETHING '+' tSOMETHING
+ | tSOMETHING '-' tSOMETHING
+ ;
+
diff --git a/test/racc/test_racc_command.rb b/test/racc/test_racc_command.rb
index b4fc0c6745..f1116a371f 100644
--- a/test/racc/test_racc_command.rb
+++ b/test/racc/test_racc_command.rb
@@ -318,5 +318,20 @@ module Racc
assert_debugfile 'tp_plus.y', [21, 0, 0, 0]
assert_output_unchanged 'tp_plus.y'
end
+
+ def test_ifelse
+ stderr = nil
+ racc "-o#{@TAB_DIR}/ifelse", "#{ASSET_DIR}/ifelse.y", stdout_filter: ->(s) { stderr = s }
+ stderr = stderr.lines[1..-1].join if RUBY_PLATFORM.match? /java/
+ assert_equal(<<~STDERR, stderr)
+ 1 useless nonterminals:
+ dummy
+ 2 useless rules:
+ #4 (dummy)
+ #5 (dummy)
+ 1 shift/reduce conflicts
+ Turn on logging with "-v" and check ".output" file for details
+ STDERR
+ end
end
end