#! /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 #create name for temporary files tmpfile=/tmp/makepC$$ trap "rm -f ${tmpfile}*" 0 1 2 15 #generate class declaration file $tmpfile.classdecl cat < $tmpfile.classdecl #line 48 "mkparserclass" #include class ${prefix} : public parser { public: ${prefix}(); EOF if egrep ErrorGuts $cfile > /dev/null; then echo " virtual void ErrorGuts(int severity, char *severityname, char *msg);" >> $tmpfile.classdecl fi echo "};" >> $tmpfile.classdecl #heading of $prefix.C cat << EOF > ${prefix}.C /* body of class $prefix Created by Andrew's mkparserclass from $cfile */ EOF #copy classdecl (instead of #include $prefix.H) # this avoids multiple declaration when %union is used cat < $tmpfile.classdecl >> ${prefix}.C #process $cfile to produce the rest of $prefix.C cat << EOF > $tmpfile.1 # 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 "#line 81 \"mkparserclass\"" print "static int retval;" print "" print "#define YYACCEPT parser_ACCEPT" print "#define YYABORT parser_ABORT" print "#define YYERROR {return (retval&4) ? 7 : 3;}" print "#define yyclearin {retval = (retval) ? 6 : 4;}" print "#define yyerrok {retval = (retval) ? 6 : 5;}" print "" print "" print "#define yyval (*pyyval)" print " static int" print "reduceActions(int i, YYSTYPE *pyyval, YYSTYPE *yyvsp," print " class parser *parser) {" print " retval = 0;" print " switch (i) {" print "" deleting = 0 intables = 0 next } # insert end of reduceActions function /action file gets copied/ { print "" print " return retval;" 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 138 \"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 $tmpfile.1 $cfile >> ${prefix}.C #generate $prefix.H file cat << EOF > ${prefix}.H /* declaration of class $prefix Created by mkparserclass from $cfile $hfilename */ EOF cat < $tmpfile.classdecl >> ${prefix}.H if test -r $hfile; then echo Reading $hfile. Creating ${prefix}.H #process hfile to make prefix.H cat<$tmpfile.2 BEGIN {print ""} # delete YYSTYPE declaration /#ifndef.*YYSTYPE/,/#endif/ {next} # delete declaration of yylval /yylval/ {next} # otherwise, just copy the whole thing {print} EOF awk -f $tmpfile.2 $hfile >> ${prefix}.H fi rm -f $tmpfile* # Copyright 1994 Carnegie Mellon University All rights reserved. # $Disclaimer: $