jxf@phobos.cis.ksu.edu (Jerry Frain) (02/22/90)
I recently wrote a program which requires two parsers. Depending upon the type of input received, the program will parse according to one of two grammars. I created a yacc file for each parser, tested them separately, and prepared to link the objects into a larger program. Unfortunately, that's as far as I got. Since yacc creates a lot of global variables when it makes the y.tab.c files, there were many conflict errors when I tried to link the two files. I seem to recall a thread in this newsgroup about this problem quite some time ago, but I did not pay any attention to the solution at the time. Anybody got any ideas as to how I can solve this dilemma? Thanks in advance. I'd be glad to post a summary, if there is much interest. -- Jerry Frain -- Professional Student Kansas State University Internet: jxf@phobos.cis.ksu.edu Dept of Computing & Information Sciences BITNET: MUSTANG@KSUVM.BITNET Manhattan, Kansas UUCP: ...!{rutgers|textbell}!ksuvax1!phobos.cis.ksu.edu!jxf
alan@cogswell.Jpl.Nasa.Gov (Alan S. Mazer) (02/23/90)
In article <25E34681.3787@deimos.cis.ksu.edu>, jxf@phobos.cis.ksu.edu (Jerry Frain) writes: | I created a yacc file for each parser, tested them separately, and prepared | to link the objects into a larger program. Unfortunately, that's as far as | I got. Since yacc creates a lot of global variables when it makes the | y.tab.c files, there were many conflict errors when I tried to link the two | files. We have a program which uses two different grammars and the Makefile runs one y.tab.c through sed to change the names of things. I think there's 40-some things to change. Haven't had any problems with this. If you or anyone else want it, you're welcome. -- Alan # "But seriously, what could go wrong?" ..!cit-vax!elroy!alan alan@elroy.jpl.nasa.gov
kon@mycroft.Stanford.EDU (Ronnie Kon) (02/23/90)
In article <25E34681.3787@deimos.cis.ksu.edu> jxf@phobos.cis.ksu.edu (Jerry Frain) writes: > Since yacc creates a lot of global variables when it makes the >y.tab.c files, there were many conflict errors when I tried to link the two >files. Not only does it make a lot of global variables, but the two routines are both named yyparse, and both call yylex for scanning input. There are two approaches to dealing with this, one correct and tedious to implement, one a kludge that works every bit as well and is much, much, easier. The correct way to do this is to run the yacc output through a sed script which replaces all the globals with unique names. This will be a pain to implement. The kludge is to simply sed with the command sed 's/\<yy/parser1_yy/g' < y.tab.c > parser1.c for the first parser. (The sed script for the second parser is left as an exercize for the reader :-)). You then call these as parser1_yyparse() and parser2_yyparse(), and you set up the scanners to be parser1_yylex() and parser2_yylex(). (If you are using lex, you simply use the same sed scripts as for the yacc files, and it all just works). Note that the yytext and yylval variables (which you are probably using) need not be changed. The sed's will catch all instances of them. -- ------------------------------------------------------------------------------- Ronnie Kon | "I don't know about your brain, ronnie@mindcraft.com | but mine is really bossy" ...!{decwrl,hpda}!mindcrf!ronnie | -- Laurie Anderson -------------------------------------------------------------------------------
chris@mimsy.umd.edu (Chris Torek) (02/23/90)
(I have deleted an unnecessary `usa' Distribution: line.) In article <39@mycroft.stanford.edu> kon@mycroft.Stanford.EDU (Ronnie Kon) writes: >The correct way to do this is to run the yacc output through a sed >script which replaces all the globals with unique names. ... Actually, since yacc is table driven, this is really not the `best' way to do it either, since you wind up with duplicated code. The `best' way depends on space/time tradeoffs. If you want the least space possible, merge the two grammars (and, if necessary, scanners) and see if that gives smaller tables. Depending on the degree of commonality, it might or might not. If you want speed over space, or if the merged tables are larger, change the yacc parser to take parameters giving the tables and (if necessary) the lexing function. You can then share the parser skeleton (/usr/lib/yaccpar, or whatever it is called on your system) while using separate tables. In other words, instead of calling `yyparse()', you would call `parse(&parsedata, &lexdata)', where `parsedata' is a structure containing (pointers to) the parser tables and a function that implements the actions, and where lexdata is a structure containing (pointers to) the scanner tables and the lex function itself and a function that implements the lexer actions. (If the lexer for both grammars are identical, you need not bother with `lexdata'.) This would require substantial changes to yacc (and, if you use it similarly, lex). Changing the names is much easier. Note that this technique does not work with code-driven scanners such as those produced by GLA. If, however, you were to mix GLA and yacc, you could still do this for the parser (and instead of &lexdata, pass a pointer to the GLA lexing function). -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
hadley@ics.uci.edu (Tedd Hadley) (02/24/90)
jxf@phobos.cis.ksu.edu (Jerry Frain) writes: >I seem to recall a thread in this newsgroup about this problem quite some >time ago, but I did not pay any attention to the solution at the time. >Anybody got any ideas as to how I can solve this dilemma? Here's a very practical (as opposed to pedantically correct) solution. Include the following ".h" file in your yacc file. Replace all <unique_name_here> with whatever name you wish. Call to parser becomes <unique_name_here>_yyparse() --- yacc_unique.h --- #define yyact <unique_name_here>_yyact #define yyback <unique_name_here>_yyback #define yybgin <unique_name_here>_yybgin #define yychar <unique_name_here>_yychar #define yychk <unique_name_here>_yychk #define yycrank <unique_name_here>_yycrank #define yydef <unique_name_here>_yydef #define yyerrflag <unique_name_here>_yyerrflag #define yyestate <unique_name_here>_yyestate #define yyexca <unique_name_here>_yyexca #define yyextra <unique_name_here>_yyextra #define yyfnd <unique_name_here>_yyfnd #define yyin <unique_name_here>_yyin #define yyinput <unique_name_here>_yyinput #define yyleng <unique_name_here>_yyleng #define yylex <unique_name_here>_yylex #define yylineno <unique_name_here>_yylineno #define yylook <unique_name_here>_yylook #define yylsp <unique_name_here>_yylsp #define yylstate <unique_name_here>_yylstate #define yylval <unique_name_here>_yylval #define yymatch <unique_name_here>_yymatch #define yymorfg <unique_name_here>_yymorfg #define yynerrs <unique_name_here>_yynerrs #define yyolsp <unique_name_here>_yyolsp #define yyout <unique_name_here>_yyout #define yyoutput <unique_name_here>_yyoutput #define yypact <unique_name_here>_yypact #define yyparse <unique_name_here>_yyparse #define yypgo <unique_name_here>_yypgo #define yyprevious <unique_name_here>_yyprevious #define yyr1 <unique_name_here>_yyr1 #define yyr2 <unique_name_here>_yyr2 #define yysbuf <unique_name_here>_yysbuf #define yysptr <unique_name_here>_yysptr #define yysvec <unique_name_here>_yysvec #define yytchar <unique_name_here>_yytchar #define yytext <unique_name_here>_yytext #define yytop <unique_name_here>_yytop #define yyunput <unique_name_here>_yyunput #define yyv <unique_name_here>_yyv #define yyval <unique_name_here>_yyval #define yyvstop <unique_name_here>_yyvstop --- yacc_unique.h --- And best of all, no `sed' scripts. ++ Tedd Hadley (hadley@ics.uci.edu)
gnb@bby.oz.au (Gregory N. Bond) (02/26/90)
Here is a script I use for making yacc output files static, so you can link n of them in one binary. I use it on the output of getdate.y to make a general gate-parsing library. Tried only on SunOs 3.5 and 4.0.3. (It assumes the .y file contains a global routine that calls the yyparse routine). Usage: sed -f yaccstaticize.sed < y.tab.c > file.c Greg. -- Gregory Bond, Burdett Buckeridge & Young Ltd, Melbourne, Australia Internet: gnb@melba.bby.oz.au non-MX: gnb%melba.bby.oz@uunet.uu.net Uucp: {uunet,pyramid,ubc-cs,ukc,mcvax,prlb2,nttlab...}!munnari!melba.bby.oz!gnb #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: yaccstaticize.sed # Wrapped by gnb@baby on Mon Feb 26 10:29:39 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'yaccstaticize.sed' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'yaccstaticize.sed'\" else echo shar: Extracting \"'yaccstaticize.sed'\" \(93 characters\) sed "s/^X//" >'yaccstaticize.sed' <<'END_OF_FILE' Xs/^short yy/static &/ Xs/^int[ ]*yy/static &/ Xs/^YY[LS]TYPE/static &/ Xs/^yyparse()/static &/ END_OF_FILE if test 93 -ne `wc -c <'yaccstaticize.sed'`; then echo shar: \"'yaccstaticize.sed'\" unpacked with wrong size! fi # end of 'yaccstaticize.sed' fi echo shar: End of shell archive. exit 0 -- Gregory Bond, Burdett Buckeridge & Young Ltd, Melbourne, Australia Internet: gnb@melba.bby.oz.au non-MX: gnb%melba.bby.oz@uunet.uu.net Uucp: {uunet,pyramid,ubc-cs,ukc,mcvax,prlb2,nttlab...}!munnari!melba.bby.oz!gnb -- Gregory Bond, Burdett Buckeridge & Young Ltd, Melbourne, Australia Internet: gnb@melba.bby.oz.au non-MX: gnb%melba.bby.oz@uunet.uu.net Uucp: {uunet,pyramid,ubc-cs,ukc,mcvax,prlb2,nttlab...}!munnari!melba.bby.oz!gnb
johnson@ncrons.StPaul.NCR.COM (Wayne D. Johnson) (02/28/90)
In article <39@mycroft.stanford.edu> kon@mycroft.Stanford.EDU (Ronnie Kon) writes: #In article <25E34681.3787@deimos.cis.ksu.edu> jxf@phobos.cis.ksu.edu (Jerry Frain) writes: #> Since yacc creates a lot of global variables when it makes the #>y.tab.c files, there were many conflict errors when I tried to link the two #>files. # # The kludge is to simply sed with the command # # sed 's/\<yy/parser1_yy/g' < y.tab.c > parser1.c I have seen an implementation where they #defined the yy as somthing else before the compile. Who needs sed. -- Wayne Johnson | Is a baby's life worth more than the right to NCR Comten, Inc. | make a choice? Babies are people too. Roseville MN 55113 +----------------------------------------------------- (Voice) 612-638-7665 (E-MAIL) W.Johnson@StPaul.NCR.COM
kon@wolverine.Stanford.EDU (Ronnie Kon) (03/01/90)
In article <238@ncrons.StPaul.NCR.COM> johnson@ncrons.StPaul.NCR.COM (Wayne D. Johnson) writes: ># ># The kludge is to simply sed with the command ># ># sed 's/\<yy/parser1_yy/g' < y.tab.c > parser1.c > >I have seen an implementation where they #defined the yy as >somthing else before the compile. Who needs sed? > This will not work with a functioning C preprocessor. Only complete identifiers should be replaced. Thus a variable named "yy" would get changed, but "yytext" will not. -- ------------------------------------------------------------------------------- Ronnie Kon | "I don't know about your brain, ronnie@mindcraft.com | but mine is really bossy" ...!{decwrl,hpda}!mindcrf!ronnie | -- Laurie Anderson -------------------------------------------------------------------------------
meo@stiatl.UUCP (Miles O'Neal) (03/18/90)
I just rename y.lex.c to something more useful, such as parse_newt.c. Makefiles do this just fine, but even without make it's no trouble. -Miles O'Neal meo@SalesTech.com emory!stiatl!meo