#! /bin/sh set -k # usage: mkparser prefix [c-file [h-file]] # where 'prefix' is the name of the grammar. # The generated table 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 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 parser declaration in .h file cat < ${prefix}.h /* declaration of parser $prefix Created by mkparser from $cfile $hfilename */ #include extern struct parser *${prefix}_New(); EOF #process cfile to produce prefix.c awkfile=/tmp/makepC$$ trap "rm -f ${awkfile} ${awkfile}.2" 0 1 2 15 cat<$awkfile BEGIN { print "/* produced by mkparser from $cfile */" print "" print "#include " } # if we see ErrorGuts declared, be sure to call parser_SetErrorFunc /${prefix}_ErrorGuts.*\(/ {if (sawErrorGuts == 0) { sawErrorGuts = 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 "" 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(i, pyyval, yyvsp, parser)\nint i;\nYYSTYPE *pyyval;\nYYSTYPE *yyvsp;\n" print " struct parser *parser; {" print " switch (i) {" print "" deleting = 0 next } # insert end of reduceActions function /action file gets copied/ { print "" print " return retval;" print "}" print "#undef yyval" deleting = 1 next } # remove all '#if...YYDEBUG' ... '#endif' # and add them around yyprhs, yyrhs, yyrline # (but NOT arount yytname) /#if.*YYDEBUG/ {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 \"mkparser\"" 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 YYDEBUG != 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 "struct parser *${prefix}_New() {" print " struct parser *self=parser_New();" print " parser_SetTables(self, &${prefix}_ParseTable);" if (sawErrorGuts) { print " parser_SetErrorFunc(self, (parser_errfptr)${prefix}_ErrorGuts);" } print " return self;" 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<$awkfile.2 #terminate class declaration 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 $awkfile.2 $hfile >> ${prefix}.h fi rm -f $awkfile $awkfile.2 # Copyright 1994 Carnegie Mellon University All rights reserved. # $Disclaimer: $