#! /bin/sh
set -k

# usage:  mkparserclass prefix [c-file [h-file]]
# 	where 'prefix' is the name of the grammar.  The generated files
#	will have the name prefix_ParseTable (with 'prefix' replaced).
#	The c-file must exist.  If not named in the arguments, its name
#	must be prefix.tab.c.  If the h-file is not specified, it is 
#	taken to be prefix.tab.h;  the h-file need not exist.
#
# Output: files prefix.C and prefix.H suitable for compilation with CC
#	File prefix.C is compiled as any .C file.  File prefix.H is
#	#included by the client program.

export prefix
prefix=$1

# determine file names
# c-file
#	$2, if specified, otherwise prefix.tab.c
#	if file does not exist, exit with error
export cfile
cfile=${2-$1.tab.c}
if test \! -r $cfile; then echo Missing .c file: $cfile; exit 3
	else echo Reading $cfile.  Creating ${prefix}.C;  fi
# h-file
#	$3, if specified,otherwise prefix.tab.h
#	if file does not exist, set name to ""
export hfile
hfile=${3-$1.tab.h}
if test \! -r $hfile; then 
	echo Found no .h file.  Creating ${prefix}.H
	hfilename=""
else
	hfilename=$hfile
fi

#generate initial segment of class declaration in .H file
cat <<EOF > ${prefix}.H
/*  declaration of class $prefix

	Created by mkparserclass from  $cfile  $hfilename
*/

#include <parser.H>

class ${prefix} : public parser {
public:

${prefix}();

EOF

#process cfile to produce prefix.C
awkfile=/tmp/makepC$$
trap "rm -f ${awkfile} ${awkfile}.2" 0 1 2 15 

cat<<EOF>$awkfile
BEGIN {
	print "/* produced by mkparserclass from $cfile */"
	print ""
	print "#include <$prefix.H>"
}

# if we see ErrorGuts declared, append declaration to .H file
/ErrorGuts.*\(.*int/  {if (sawErrorGuts == 0) {
	sawErrorGuts = 1
	print "virtual void ErrorGuts(int severity, char *severityname, char *msg);" >> "${prefix}.H"
}}

# delete all bison.simple stuff
/#line.*bison/ {deleting = 1; next}
/#line/ {deleting = 0}
/Note some compilers choke/ {next}
# insert declaration of reduceActions in place of Bison's parser
/switch \(yyn\)/  {
	print ""
	print "#define yyval (*pyyval)"
	print "	static int"
	print "reduceActions(int i, YYSTYPE *pyyval, YYSTYPE *yyvsp,"
	print "		class parser *parser) {"
	print "	switch (i) {"
	print "" 
	deleting = 0
	intables = 0
	next
}

# insert end of reduceActions function
/action file gets copied/ {
	print ""
	print " return 0;  /* no special action */"
	print "}"
	print "#undef yyval"
	deleting = 1
	next
}

# remove  '#if...YYDEBUG' ... '#endif'     from tables
#	and add them around  yyprhs, yyrhs, yyrline
#	(but NOT arount yytname)
/stdio\.h/ {intables = 1}
/#if.*YYDEBUG/ {if (intables == 1) {inyydebug = 1; next}}
/#endif/ {if (inyydebug == 1) {inyydebug = 0; next}}
/(short yyprhs)|(short yyrhs)|(short yyrline)/ {
	print "#if YYDEBUG != 0"
	print
	inrhsdebug = 1
	next
}
# (continue below)

# delete YYSTYPE declaration
/#ifndef.*YYSTYPE/,/#endif/ {next}

# pass through all lines not handled above
{if (deleting == 0) {print}}

# (continuation of wrapping rhs stuff with #if YYDEBUG ...)
/};/ {if (inrhsdebug == 1) {print "#endif"; inrhsdebug = 0}}

# at end, append the table and class declaration
END {
	print "#line 125 \"mkparserclass\""
	print ""
	print "static struct parser_tables ${prefix}_ParseTable = {"
	print "	YYNTOKENS,	/* num_tokens */"
	print "	YYNNTS,		/* num_nt */"
	print "	YYMAXUTOK,	/* max_user_token */"
	print "	YYNRULES,	/* num_rules */"
	print "	YYNSTATES,	/* num_states */"
	print "	YYFINAL,	/* final_state */"
	print ""
	print "	sizeof(YYSTYPE),	/* eltsz */"
	print ""
	print "	YYFLAG,		/* defflag */"
	print "	YYLAST,		/* table_max */"
	print ""
	print "	(char **)yytname,	/* name */"
	print "	(char *)yytranslate,	/* translate */"
	print ""
	print "	(short *)yyr1,		/* lhs */"
	print "#if YYDDBUG != 0"
	print "	(short *)yyprhs,	/* rhsx */"
	print "	(short *)yyr2,		/* rhssz */"
	print "	(short *)yyrhs,		/* rhs */"
	print "#else"
	print "	(short *)NULL,		/* rhsx */"
	print "	(short *)yyr2,		/* rhssz */"
	print "	(short *)NULL,		/* rhs */"
	print "#endif"
	print "	(short *)yytable,	/* table */"
	print "	(short *)yycheck,	/* valid */"
	print ""
	print "	(short *)yydefact,	/* defred */"
	print "	(short *)yypact,	/* actx */"
	print "	(short *)yydefgoto,	/* defnext */"
	print "	(short *)yypgoto, 	/* nextx */"
	print "	(parser_semfptr)reduceActions	/* actions */"
	print "};"
	print ""
	print "$prefix::$prefix() {"
	print "	(this)->SetTables(&${prefix}_ParseTable);"
	print "}"
}
EOF
awk -f $awkfile $cfile > ${prefix}.C

if  test -r $hfile; then 
	echo Reading $hfile.  Creating ${prefix}.H

	#process hfile to make prefix.H 
	cat<<EOF>$awkfile.2
		#terminate class declaration
		BEGIN {
			print "};"
			print ""
		}
		# delete YYSTYPE declaration
		/#ifndef.*YYSTYPE/,/#endif/ {next}
		# delete declaration of yylval
		/yylval/ {next}
		# otherwise, just copy the whole thing
		{print}
EOF
	awk -f $awkfile.2 $hfile >> ${prefix}.H
else
	#generate final segment of class declaration in .H file
	cat <<EOF >> ${prefix}.H

};

EOF

fi
#rm -f $awkfile $awkfile.2


# Copyright 1994 Carnegie Mellon University All rights reserved.
#  $Disclaimer: 
# Permission to use, copy, modify, and distribute this software and its 
# documentation for any purpose is hereby granted without fee, 
# provided that the above copyright notice appear in all copies and that 
# both that copyright notice, this permission notice, and the following 
# disclaimer appear in supporting documentation, and that the names of 
# IBM, Carnegie Mellon University, and other copyright holders, not be 
# used in advertising or publicity pertaining to distribution of the software 
# without specific, written prior permission.
# 
# IBM, CARNEGIE MELLON UNIVERSITY, AND THE OTHER COPYRIGHT HOLDERS 
# DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT 
# SHALL IBM, CARNEGIE MELLON UNIVERSITY, OR ANY OTHER COPYRIGHT HOLDER 
# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
# OF THIS SOFTWARE.
#  $
