From 1a2546c2be839baa7d0a50dc056d4d6987d26852 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 13 May 2019 21:25:22 +0900 Subject: Backport racc-1.4.15 from upstream. --- lib/racc/logfilegenerator.rb | 211 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 lib/racc/logfilegenerator.rb (limited to 'lib/racc/logfilegenerator.rb') diff --git a/lib/racc/logfilegenerator.rb b/lib/racc/logfilegenerator.rb new file mode 100644 index 0000000000..b95b1afaa2 --- /dev/null +++ b/lib/racc/logfilegenerator.rb @@ -0,0 +1,211 @@ +# +# $Id: a7e9663605afdda065d305b250a9805e3bd3fa70 $ +# +# Copyright (c) 1999-2006 Minero Aoki +# +# This program is free software. +# You can distribute/modify this program under the terms of +# the GNU LGPL, Lesser General Public License version 2.1. +# For details of the GNU LGPL, see the file "COPYING". +# + +module Racc + + class LogFileGenerator + + def initialize(states, debug_flags = DebugFlags.new) + @states = states + @grammar = states.grammar + @debug_flags = debug_flags + end + + def output(out) + output_conflict out; out.puts + output_useless out; out.puts + output_rule out; out.puts + output_token out; out.puts + output_state out + end + + # + # Warnings + # + + def output_conflict(out) + @states.each do |state| + if state.srconf + out.printf "state %d contains %d shift/reduce conflicts\n", + state.stateid, state.srconf.size + end + if state.rrconf + out.printf "state %d contains %d reduce/reduce conflicts\n", + state.stateid, state.rrconf.size + end + end + end + + def output_useless(out) + @grammar.each do |rl| + if rl.useless? + out.printf "rule %d (%s) never reduced\n", + rl.ident, rl.target.to_s + end + end + @grammar.each_nonterminal do |t| + if t.useless? + out.printf "useless nonterminal %s\n", t.to_s + end + end + end + + # + # States + # + + def output_state(out) + out << "--------- State ---------\n" + + showall = @debug_flags.la || @debug_flags.state + @states.each do |state| + out << "\nstate #{state.ident}\n\n" + + (showall ? state.closure : state.core).each do |ptr| + pointer_out(out, ptr) if ptr.rule.ident != 0 or showall + end + out << "\n" + + action_out out, state + end + end + + def pointer_out(out, ptr) + buf = sprintf("%4d) %s :", ptr.rule.ident, ptr.rule.target.to_s) + ptr.rule.symbols.each_with_index do |tok, idx| + buf << ' _' if idx == ptr.index + buf << ' ' << tok.to_s + end + buf << ' _' if ptr.reduce? + out.puts buf + end + + def action_out(f, state) + sr = state.srconf && state.srconf.dup + rr = state.rrconf && state.rrconf.dup + acts = state.action + keys = acts.keys + keys.sort! {|a,b| a.ident <=> b.ident } + + [ Shift, Reduce, Error, Accept ].each do |klass| + keys.delete_if do |tok| + act = acts[tok] + if act.kind_of?(klass) + outact f, tok, act + if sr and c = sr.delete(tok) + outsrconf f, c + end + if rr and c = rr.delete(tok) + outrrconf f, c + end + + true + else + false + end + end + end + sr.each {|tok, c| outsrconf f, c } if sr + rr.each {|tok, c| outrrconf f, c } if rr + + act = state.defact + if not act.kind_of?(Error) or @debug_flags.any? + outact f, '$default', act + end + + f.puts + state.goto_table.each do |t, st| + if t.nonterminal? + f.printf " %-12s go to state %d\n", t.to_s, st.ident + end + end + end + + def outact(f, t, act) + case act + when Shift + f.printf " %-12s shift, and go to state %d\n", + t.to_s, act.goto_id + when Reduce + f.printf " %-12s reduce using rule %d (%s)\n", + t.to_s, act.ruleid, act.rule.target.to_s + when Accept + f.printf " %-12s accept\n", t.to_s + when Error + f.printf " %-12s error\n", t.to_s + else + raise "racc: fatal: wrong act for outact: act=#{act}(#{act.class})" + end + end + + def outsrconf(f, confs) + confs.each do |c| + r = c.reduce + f.printf " %-12s [reduce using rule %d (%s)]\n", + c.shift.to_s, r.ident, r.target.to_s + end + end + + def outrrconf(f, confs) + confs.each do |c| + r = c.low_prec + f.printf " %-12s [reduce using rule %d (%s)]\n", + c.token.to_s, r.ident, r.target.to_s + end + end + + # + # Rules + # + + def output_rule(out) + out.print "-------- Grammar --------\n\n" + @grammar.each do |rl| + if @debug_flags.any? or rl.ident != 0 + out.printf "rule %d %s: %s\n", + rl.ident, rl.target.to_s, rl.symbols.join(' ') + end + end + end + + # + # Tokens + # + + def output_token(out) + out.print "------- Symbols -------\n\n" + + out.print "**Nonterminals, with rules where they appear\n\n" + @grammar.each_nonterminal do |t| + tmp = <