/* * egman.c * * SOFTWARE RIGHTS * * We reserve no LEGAL rights to the Purdue Compiler Construction Tool * Set (PCCTS) -- PCCTS is in the public domain. An individual or * company may do whatever they wish with source code distributed with * PCCTS or the code generated by PCCTS, including the incorporation of * PCCTS, or its output, into commerical software. * * We encourage users to develop software with PCCTS. However, we do ask * that credit is given to us for developing PCCTS. By "credit", * we mean that if you incorporate our source code into one of your * programs (commercial product, research project, or otherwise) that you * acknowledge this fact somewhere in the documentation, research report, * etc... If you like PCCTS and have developed a nice tool with the * output, please mention that you developed it using PCCTS. In * addition, we ask that this header remain intact in our source code. * As long as these guidelines are kept, we expect to continue enhancing * this system and expect to make other tools available as they are * completed. * * ANTLR 1.33MR10 * 2001 * */ #include #include #include "set.h" #include "syn.h" #include "hash.h" #include "generic.h" #include "proto.h" static ExceptionGroup **egArray=NULL; /* ExceptionGroup by BlkLevel */ static LabelEntry **leArray=NULL; /* LabelEntry by BlkLevel */ static Junction **altArray=NULL; /* start of alternates */ static int arraySize=0; static int highWater=0; static ExceptionGroup *lastEG=NULL; /* used in altFixup() */ static int lastBlkLevel=0; /* used in altFixup() */ #ifdef __USE_PROTOS static void arrayCheck(void); #else static void arrayCheck(); #endif /* Called to add an exception group for an alternative EG */ #ifdef __USE_PROTOS void egAdd(ExceptionGroup * eg) #else void egAdd(eg) ExceptionGroup *eg; #endif { int i; ExceptionGroup *nextEG; ExceptionGroup *innerEG; LabelEntry *nextLE; LabelEntry *innerLE; Junction *nextAlt; Junction *innerAlt; lastEG=eg; lastBlkLevel=BlkLevel; arrayCheck(); eg->pendingLink=egArray[BlkLevel]; egArray[BlkLevel]=eg; /* EG for alternates already have their altID filled in */ for (i=BlkLevel+1; i<=highWater ; i++) { for (innerEG=egArray[i]; innerEG != NULL ; innerEG=nextEG) { nextEG=innerEG->pendingLink; innerEG->pendingLink=NULL; innerEG->outerEG=eg; }; egArray[i]=NULL; }; /* * for patching up the LabelEntry you might use an EG for the * current alternative - unlike patching up an alternative EG * i.e. start the loop at BlkLevel rather than (BlkLevel+1) * fill it in only if the EG and the LE are for the very * same alternative if they're at the same BlkLevel * it's easier to leave the LE on this list (filled in) rather than * trying to selectively remove it. It will eventually be * removed anyway when the BlkLevel gets small enough. */ for (i=BlkLevel; i<=highWater ; i++) { for (innerLE=leArray[i]; innerLE != NULL ; innerLE=nextLE) { nextLE=innerLE->pendingLink; if (BlkLevel != i || innerLE->curAltNum == CurAltNum_array[BlkLevel]) { if (innerLE->outerEG == NULL) { innerLE->outerEG=eg; }; }; }; if (BlkLevel != i) leArray[i]=NULL; }; /* * For the start of alternatives it is necessary to make a * distinction between the exception group for the current * alternative and the "fallback" EG for the block which * contains the alternative * * The fallback outerEG is used to handle the case where * no alternative of a block matches. In that case the * signal is "NoViableAlt" (or "NoSemViableAlt" and the * generator needs the EG of the block CONTAINING the * current one. * * rule: ( ( ( a * | b * ) * | c * ) * | d * ); */ for (i=BlkLevel; i <= highWater ; i++) { for (innerAlt=altArray[i]; innerAlt != NULL ; innerAlt=nextAlt) { nextAlt=innerAlt->pendingLink; /* first fill in the EG for the current alternative */ /* but leave it on the list in order to get the fallback EG */ /* if the EG is at the same LEVEL as the alternative then */ /* fill it in only if in the very same alternative */ /* */ /* rule: ( a */ /* | b */ /* | c exception ... */ /* ) */ /* */ /* if the EG is outside the alternative (e.g. BlkLevel < i) */ /* then it doesn't matter about the alternative */ /* */ /* rule: ( a */ /* | b */ /* | c */ /* ) exception ... */ /* */ #if 0 printf("BlkLevel=%d i=%d altnum=%d CurAltNum=%d altID=%s\n", BlkLevel,i,innerAlt->curAltNum,CurAltNum_array[BlkLevel],eg->altID); #endif if (BlkLevel != i || innerAlt->curAltNum == CurAltNum_array[BlkLevel]) { if (innerAlt->exception_label == NULL) { innerAlt->exception_label=eg->altID; }; }; /* ocurs at a later pass then for the exception_label */ /* if an outerEG has been found then fill in the outer EG */ /* remove if from the list when the BlkLevel gets smaller */ if (BlkLevel != i) { if (innerAlt->outerEG == NULL) { innerAlt->outerEG=eg; }; }; }; if (BlkLevel != i) altArray[i]=NULL; }; } #ifdef __USE_PROTOS void leAdd(LabelEntry * le) #else void leAdd(le) LabelEntry *le; #endif { arrayCheck(); le->pendingLink=leArray[BlkLevel]; le->curAltNum=CurAltNum_array[BlkLevel]; leArray[BlkLevel]=le; } #ifdef __USE_PROTOS void altAdd(Junction *alt) #else void altAdd(alt) Junction *alt; #endif { arrayCheck(); #if 0 printf("BlkLevel=%d CurAltNum=%d\n", BlkLevel,CurAltNum_array[BlkLevel]); #endif alt->curAltNum=CurAltNum_array[BlkLevel]; alt->pendingLink=altArray[BlkLevel]; altArray[BlkLevel]=alt; } static void #ifdef __USE_PROTOS arrayCheck(void) #else arrayCheck() #endif { ExceptionGroup **egArrayNew; LabelEntry **leArrayNew; Junction **altArrayNew; int arraySizeNew; int i; if (BlkLevel > highWater) highWater=BlkLevel; if (BlkLevel >= arraySize) { arraySizeNew=BlkLevel+5; /* MR20 */ egArrayNew=(ExceptionGroup **) calloc(arraySizeNew,sizeof(ExceptionGroup *)); leArrayNew=(LabelEntry **) calloc(arraySizeNew,sizeof(LabelEntry *)); altArrayNew=(Junction **) calloc(arraySizeNew,sizeof(Junction *)); for (i=0; ipendingLink; innerEG->pendingLink=NULL; }; egArray[i]=NULL; }; lastEG=NULL; lastBlkLevel=0; } /* always call leFixup() BEFORE egFixup() */ #ifdef __USE_PROTOS void leFixup(void) #else void leFixup() #endif { int i; LabelEntry *nextLE; LabelEntry *innerLE; for (i=BlkLevel; i<=highWater ; i++) { for (innerLE=leArray[i]; innerLE != NULL ; innerLE=nextLE) { nextLE=innerLE->pendingLink; innerLE->pendingLink=NULL; }; leArray[i]=NULL; }; } /* always call altFixup() BEFORE egFixup() */ #ifdef __USE_PROTOS void altFixup(void) #else void altFixup() #endif { int i; Junction *nextAlt; Junction *innerAlt; for (i=BlkLevel; i<=highWater ; i++) { for (innerAlt=altArray[i]; innerAlt != NULL ; innerAlt=nextAlt) { /* if an outerEG has been found then fill in the outer EG */ if (lastBlkLevel <= i) { if (innerAlt->outerEG == NULL) { innerAlt->outerEG=lastEG; }; }; nextAlt=innerAlt->pendingLink; innerAlt->pendingLink=NULL; }; altArray[i]=NULL; }; }