/* * main.c -- main program for PCCTS ANTLR. * * 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.33 * Terence Parr * Parr Research Corporation * with Purdue University and AHPCRC, University of Minnesota * 1989-2001 */ /* To set a breakpoint just before exit look for "cleanUp". */ /* To set a breakpoint for fatal error look for "fatal_intern" */ #include #include "pcctscfg.h" #include "stdpccts.h" #define MAX_INT_STACK 50 static int istack[MAX_INT_STACK]; /* Int stack */ static int isp = MAX_INT_STACK; static int DontAcceptFiles = 0; /* if stdin, don't read files */ static int DontAcceptStdin = 0; /* if files seen first, don't accept stdin */ static int tnodes_used_in_guard_predicates_etc; /* MR10 */ /* C m d - L i n e O p t i o n S t r u c t & F u n c s */ typedef struct _Opt { char *option; int arg; #ifdef __cplusplus void (*process)(...); #else void (*process)(); #endif char *descr; } Opt; #ifdef __USE_PROTOS extern void ProcessArgs(int, char **, Opt *); #else extern void ProcessArgs(); #endif #ifdef __USE_PROTOS int ci_strequ(char *a,char *b) #else int ci_strequ(a,b) char *a; char *b; #endif { for ( ;*a != 0 && *b != 0; a++, b++) { if (toupper(*a) != toupper(*b)) return 0; } return (*a == *b); } static void #ifdef __USE_PROTOS pStdin( void ) #else pStdin( ) #endif { if ( DontAcceptStdin ) { warnNoFL("'-' (stdin) ignored as files were specified first"); return; } require(NumFiles 8 ) { /* MR6 */ warnNoFL("tab width must be between 1 and 8"); /* MR6 */ TabWidth=0; /* MR6 */ } /* MR6 */ } /* MR6 */ static int ambAidDepthSpecified=0; /* MR11 */ static void /* MR11 */ #ifdef __USE_PROTOS pAAd( char *s, char *t ) /* MR11 */ #else pAAd( s, t ) /* MR11 */ char *s; /* MR11 */ char *t; /* MR11 */ #endif { /* MR11 */ ambAidDepthSpecified=1; /* MR11 */ MR_AmbAidDepth = atoi(t); /* MR11 */ } /* MR11 */ static void /* MR11 */ #ifdef __USE_PROTOS pTreport( char *s, char *t ) /* MR11 */ #else pTreport( s, t ) /* MR11 */ char *s; /* MR11 */ char *t; /* MR11 */ #endif { /* MR11 */ TnodesReportThreshold = atoi(t); /* MR11 */ } /* MR11 */ #ifdef __USE_PROTOS void chkGTFlag(void) /* 7-Apr-97 MR1 */ #else void chkGTFlag() /* 7-Apr-97 MR1 */ #endif { if ( !GenAST ) warn("#-variable or other AST item referenced w/o -gt option"); } #ifdef __USE_PROTOS static void pInfo(char *s, char *t) /* MR10 */ #else static void pInfo(s,t) /* MR10 */ char *s; char *t; #endif { char *p; int q; for (p=t; *p != 0; p++) { q=tolower(*p); if (q=='t') { InfoT=1; } else if (q=='p') { InfoP=1; } else if (q=='m') { InfoM=1; } else if (q=='o') { InfoO=1; } else if (q=='0') { ; /* nothing */ } else if (q=='f') { InfoF=1; } else { warnNoFL(eMsgd("unrecognized -info option \"%c\"",(int)*p)); }; }; } #ifdef __USE_PROTOS static void pCGen(void) { CodeGen = FALSE; LexGen = FALSE; } static void pLGen(void) { LexGen = FALSE; } static void pXTGen(void){ MR_Inhibit_Tokens_h_Gen = TRUE; } static void pTGen(void) { TraceGen = TRUE; } static void pSGen(void) { GenExprSetsOpt = FALSE; } static void pPrt(void) { PrintOut = TRUE; pCGen(); pLGen(); } static void pPrtA(void) { PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); } static void pAst(void) { GenAST = TRUE; } static void pANSI(void) { GenANSI = TRUE; } static void pCr(void) { GenCR = TRUE; } static void pNOPURIFY(void) { PURIFY = FALSE; } /*static void pCt(void) { warnNoFL("-ct option is now the default"); }*/ static void pLI(void) { GenLineInfo = TRUE; GenLineInfoMS = FALSE; } /* MR14 */ static void pLIms(void) { GenLineInfo = TRUE; GenLineInfoMS = TRUE; } /* MR14 */ static void pFr(char *s, char *t) {RemapFileName = t;} static void pFe(char *s, char *t) {ErrFileName = t;} static void pFl(char *s, char *t) {DlgFileName = t;} static void pFm(char *s, char *t) {ModeFileName = t;} static void pFt(char *s, char *t) {DefFileName = t;} static void pE1(void) { elevel = 1; } static void pE2(void) { elevel = 2; } static void pE3(void) { elevel = 3; } static void pEGen(void) { GenEClasseForRules = 1; } static void pDL(void) { DemandLookahead = 1; if ( GenCC ) { warnNoFL("-gk does not work currently in C++ mode; -gk turned off"); DemandLookahead = 0; } } static void pAA(char *s,char *t) {MR_AmbAidRule = t;} /* MR11 */ static void pAAm(char *s){MR_AmbAidMultiple = 1;} /* MR11 */ static void pGHdr(void) { GenStdPccts = 1; } static void pFHdr(char *s, char *t) { stdpccts = t; pGHdr(); } static void pW1(void) { WarningLevel = 1; } static void pNewAST(void) { NewAST = 1; } /* MR13 */ static void ptmakeInParser(void) { tmakeInParser = 1; } /* MR23 */ static void pAlpha(void) { AlphaBetaTrace = 1; } /* MR14 */ static void pMR_BlkErr(void) { MR_BlkErr = 1; } /* MR21 */ static void pStdout(void) {UseStdout = 1; } /* MR6 */ static void pW2(void) { WarningLevel = 2; } static void pCC(void) { GenCC = TRUE; } #else static void pCGen() { CodeGen = FALSE; LexGen = FALSE; } static void pLGen() { LexGen = FALSE; } static void pXTGen(){ MR_Inhibit_Tokens_h_Gen = TRUE; } /* MR14 */ static void pTGen() { TraceGen = TRUE; } static void pSGen() { GenExprSetsOpt = FALSE; } static void pPrt() { PrintOut = TRUE; pCGen(); pLGen(); } static void pPrtA() { PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); } static void pAst() { GenAST = TRUE; } static void pANSI() { GenANSI = TRUE; } static void pCr() { GenCR = TRUE; } static void pNOPURIFY() { PURIFY = FALSE; } /*static void pCt() { warnNoFL("-ct option is now the default"); }*/ static void pLI() { GenLineInfo = TRUE; GenLineInfoMS = FALSE; } /* MR14 */ static void pLIms() { GenLineInfo = TRUE; GenLineInfoMS = TRUE; } /* MR14 */ static void pFr(s,t) char *s, *t; {RemapFileName = t;} static void pFe(s,t) char *s, *t; {ErrFileName = t;} static void pFl(s,t) char *s, *t; {DlgFileName = t;} static void pFm(s,t) char *s, *t; {ModeFileName = t;} static void pFt(s,t) char *s, *t; {DefFileName = t;} static void pE1() { elevel = 1; } static void pE2() { elevel = 2; } static void pE3() { elevel = 3; } static void pEGen() { GenEClasseForRules = 1; } static void pDL() { DemandLookahead = 1; if ( GenCC ) { warnNoFL("-gk does not work currently in C++ mode; -gk turned off"); DemandLookahead = 0; } } static void pAA(s,t) char *s; char *t; {MR_AmbAidRule = t;} /* MR11 BJS 20-Mar-98 */ static void pAAm(s) char *s; {MR_AmbAidMultiple = 1;} /* MR11 BJS 20-Mar-98 */ static void pGHdr() { GenStdPccts = 1; } static void pFHdr(s,t) char *s, *t; { stdpccts = t; pGHdr(); } static void pW1() { WarningLevel = 1; } static void pNewAST() { NewAST = 1; } /* MR13 */ static void ptmakeInParser() { tmakeInParser = 1; } /* MR23 */ static void pAlpha() { AlphaBetaTrace = 1; } /* MR14 */ static void pMR_BlkErr() { MR_BlkErr = 1; } /* MR21 */ static void pStdout() {UseStdout = 1; } /* MR6 */ static void pW2() { WarningLevel = 2; } static void pCC() { GenCC = TRUE; } #endif static void #ifdef __USE_PROTOS pPre( char *s, char *t ) #else pPre( s, t ) char *s; char *t; #endif { RulePrefix = t; } static void #ifdef __USE_PROTOS pOut( char *s, char *t ) #else pOut( s, t ) char *s; char *t; #endif { OutputDirectory = t; } static void #ifdef __USE_PROTOS pPred( void ) #else pPred( ) #endif { warnNoFL("-pr is no longer used (predicates employed if present); see -prc, -mrhoist, -mrhoistk"); /* ** if ( DemandLookahead ) ** warnNoFL("-gk conflicts with -pr; -gk turned off"); ** DemandLookahead = 0; ** HoistPredicateContext = 0; */ } static void #ifdef __USE_PROTOS pPredCtx( char *s, char *t ) #else pPredCtx(s,t) char *s; char *t; #endif { if ( ci_strequ(t,"on")) HoistPredicateContext = 1; else if ( ci_strequ(t,"off")) HoistPredicateContext = 0; if ( DemandLookahead ) { warnNoFL("-gk incompatible with semantic predicate usage; -gk turned off"); DemandLookahead = 0; } } static void #ifdef __USE_PROTOS pMRhoist( char *s, char *t ) #else pMRhoist(s,t) char *s; char *t; #endif { if ( ci_strequ(t,"on")) MRhoisting = 1; else if ( ci_strequ(t,"off")==0 ) MRhoisting = 0; if (MRhoisting) { fprintf(stderr,"Maintenance Release style hoisting enabled for predicates with lookahead depth = 1\n"); fprintf(stderr," No longer considered experimental\n"); fprintf(stderr," Can't consider suppression for predicates with lookahead depth > 1\n"); fprintf(stderr," Implies -prc on but does *not* imply -mrhoistk for k>1 predicates\n"); fprintf(stderr," This is a reminder, not a warning or error.\n"); }; } static void #ifdef __USE_PROTOS pMRhoistk( char *s, char *t ) #else pMRhoistk(s,t) char *s; char *t; #endif { if ( ci_strequ(t,"on")) MRhoistingk = 1; else if ( ci_strequ(t,"off")==0 ) MRhoistingk = 0; if (MRhoistingk) { fprintf(stderr,"EXPERIMENTAL Maintenance Release style hoisting enabled\n"); fprintf(stderr," Applies to predicates with lookahead depth > 1\n"); fprintf(stderr," Implies -prc on and -mrhoist on\n"); }; } static void #ifdef __USE_PROTOS pTRes( char *s, char *t ) #else pTRes( s, t ) char *s; char *t; #endif { TreeResourceLimit = atoi(t); if ( TreeResourceLimit <= 0 ) { warnNoFL("analysis resource limit (# of tree nodes) must be greater than 0"); TreeResourceLimit = -1; /* set to no limit */ } } Opt options[] = { #ifdef __cplusplus { "-CC", 0, (void (*)(...)) pCC, "Generate C++ output (default=FALSE)"}, { "-ck", 1, (void (*)(...)) pCk, "Set compressed lookahead depth; fast approximate lookahead"}, { "-cr", 0, (void (*)(...)) pCr, "Generate cross reference (default=FALSE)"}, { "-e1", 0, (void (*)(...)) pE1, "Ambiguities/errors shown in low detail (default)"}, { "-e2", 0, (void (*)(...)) pE2, "Ambiguities/errors shown in more detail"}, { "-e3", 0, (void (*)(...)) pE3, "Ambiguities for k>1 grammars shown with exact tuples (not lookahead sets)"}, { "-f", 1, (void (*)(...)) pFileList,"Read names of grammar files from specified file"}, /* MR14 */ { "-fe", 1, (void (*)(...)) pFe, "Rename err.c"}, { "-fh", 1, (void (*)(...)) pFHdr, "Rename stdpccts.h header (turns on -gh)"}, { "-fl", 1, (void (*)(...)) pFl, "Rename lexical output--parser.dlg"}, { "-fm", 1, (void (*)(...)) pFm, "Rename mode.h"}, { "-fr", 1, (void (*)(...)) pFr, "Rename remap.h"}, { "-ft", 1, (void (*)(...)) pFt, "Rename tokens.h"}, { "-ga", 0, (void (*)(...)) pANSI, "Generate ANSI-compatible code (default=FALSE)"}, { "-gc", 0, (void (*)(...)) pCGen, "Do not generate output parser code (default=FALSE)"}, { "-gd", 0, (void (*)(...)) pTGen, "Generate code to trace rule invocation (default=FALSE)"}, { "-ge", 0, (void (*)(...)) pEGen, "Generate an error class for each non-terminal (default=FALSE)"}, { "-gh", 0, (void (*)(...)) pGHdr, "Generate stdpccts.h for non-ANTLR-generated-files to include"}, { "-gk", 0, (void (*)(...)) pDL, "Generate parsers that delay lookahead fetches until needed"}, { "-gl", 0, (void (*)(...)) pLI, "Generate line info about grammar actions in parser"}, { "-glms", 0, (void (*)(...)) pLIms,"Like -gl but replace '\\' with '/' in #line filenames for MS C/C++ systems"}, { "-gp", 1, (void (*)(...)) pPre, "Prefix all generated rule functions with a string"}, { "-gs", 0, (void (*)(...)) pSGen, "Do not generate sets for token expression lists (default=FALSE)"}, { "-gt", 0, (void (*)(...)) pAst, "Generate code for Abstract-Syntax-Trees (default=FALSE)"}, { "-gx", 0, (void (*)(...)) pLGen, "Do not generate lexical (dlg-related) files (default=FALSE)"}, { "-gxt",0, (void (*)(...)) pXTGen, "Do not generate tokens.h (default=FALSE)"}, { "-k", 1, (void (*)(...)) pLLK, "Set full LL(k) lookahead depth (default==1)"}, { "-o", 1, (void (*)(...)) pOut, OutputDirectoryOption}, { "-p", 0, (void (*)(...)) pPrt, "Print out the grammar w/o actions (default=no)"}, { "-pa", 0, (void (*)(...)) pPrtA, "Print out the grammar w/o actions & w/FIRST sets (default=no)"}, { "-pr",0, (void (*)(...)) pPred, "no longer used; predicates employed if present"}, { "-prc", 1, (void (*)(...)) pPredCtx,"Turn on/off computation of context for hoisted predicates"}, { "-rl", 1, (void (*)(...)) pTRes, "Limit max # of tree nodes used by grammar analysis"}, { "-stdout",0, (void (*)(...)) pStdout,"Send grammar.c/grammar.cpp to stdout"}, /* MR6 */ { "-tab", 1, (void (*)(...)) pTab, "Width of tabs (1 to 8) for grammar.c/grammar.cpp files"}, /* MR6 */ { "-w1", 0, (void (*)(...)) pW1, "Set the warning level to 1 (default)"}, { "-w2", 0, (void (*)(...)) pW2, "Ambiguities yield warnings even if predicates or (...)? block"}, { "-", 0, (void (*)(...)) pStdin, "Read grammar from stdin" }, { "-mrhoist",1, (void (*)(...)) pMRhoist, /* MR9 */ "Turn on/off k=1 Maintenance Release style hoisting"}, /* MR9 */ { "-mrhoistk",1, (void (*)(...)) pMRhoistk, /* MR9 */ "Turn on/off EXPERIMENTAL k>1 Maintenance Release style hoisting"}, /* MR13 */ { "-aa" , 1, (void (*)(...)) pAA, "Ambiguity aid for a rule (rule name or line number)"}, /* MR11 */ { "-aam" , 0, (void (*)(...)) pAAm, "Lookahead token may appear multiple times in -aa listing"}, /* MR11 */ { "-aad" , 1, (void (*)(...)) pAAd, "Limits exp growth of -aa listing - default=1 (max=ck value)"}, /* MR11 */ { "-info", 1, (void (*)(...)) pInfo, "Extra info: p=pred t=tnodes f=first/follow m=monitor o=orphans 0=noop"}, /* MR12 */ { "-treport",1,(void (*)(...)) pTreport, "Report when tnode usage exceeds value during ambiguity resolution"}, /* MR11 */ { "-newAST", 0, (void (*)(...)) pNewAST, "In C++ mode use \"newAST(...)\" rather than \"new AST(...)\""}, /* MR13 */ { "-tmake", 0, (void (*)(...)) ptmakeInParser, "In C++ mode use parser's tmake method rather than \"ASTBase::tmake(...)\""}, /* MR23 */ { "-alpha",0,(void (*)(...)) pAlpha, "Provide additional information for \"(alpha)? beta\" error messages"}, /* MR14 */ { "-mrblkerr",0,(void (*)(...)) pMR_BlkErr, /* MR21 */ "EXPERIMENTAL change to (...)* and (...)+ syntax error sets"}, /* MR21 */ { "-nopurify",0,(void (*)(...)) pNOPURIFY, "Don't use the notorious PURIFY macro (replaced by MR23 initial value syntax) to zero return arguments of rules"}, /* MR23 */ { "*", 0, (void (*)(...)) pFile, "" }, /* anything else is a file */ #else { "-CC", 0, pCC, "Generate C++ output (default=FALSE)"}, { "-cr", 0, pCr, "Generate cross reference (default=FALSE)"}, { "-ck", 1, pCk, "Set compressed lookahead depth; fast approximate lookahead"}, { "-e1", 0, pE1, "Ambiguities/errors shown in low detail (default)"}, { "-e2", 0, pE2, "Ambiguities/errors shown in more detail"}, { "-e3", 0, pE3, "Ambiguities for k>1 grammars shown with exact tuples (not lookahead sets)"}, { "-f", 1, pFileList,"Read names of grammar files from specified file"}, /* MR14 */ { "-fe", 1, pFe, "Rename err.c"}, { "-fh", 1, pFHdr, "Rename stdpccts.h header (turns on -gh)"}, { "-fl", 1, pFl, "Rename lexical output--parser.dlg"}, { "-fm", 1, pFm, "Rename mode.h"}, { "-fr", 1, pFr, "Rename remap.h"}, { "-ft", 1, pFt, "Rename tokens.h"}, { "-ga", 0, pANSI, "Generate ANSI-compatible code (default=FALSE)"}, { "-gc", 0, pCGen, "Do not generate output parser code (default=FALSE)"}, { "-gd", 0, pTGen, "Generate code to trace rule invocation (default=FALSE)"}, { "-ge", 0, pEGen, "Generate an error class for each non-terminal (default=FALSE)"}, { "-gh", 0, pGHdr, "Generate stdpccts.h for non-ANTLR-generated-files to include"}, { "-gk", 0, pDL, "Generate parsers that delay lookahead fetches until needed"}, { "-gl", 0, pLI, "Generate line info about grammar actions in C parser"}, { "-glms", 0, pLIms,"Like -gl but replace '\\' with '/' in #line filenames for MS C/C++ systems"}, { "-gp", 1, pPre, "Prefix all generated rule functions with a string"}, { "-gs", 0, pSGen, "Do not generate sets for token expression lists (default=FALSE)"}, { "-gt", 0, pAst, "Generate code for Abstract-Syntax-Trees (default=FALSE)"}, { "-gx", 0, pLGen, "Do not generate lexical (dlg-related) files (default=FALSE)"}, { "-gxt",0, pXTGen, "Do not generate tokens.h (default=FALSE)"}, { "-k", 1, pLLK, "Set full LL(k) lookahead depth (default==1)"}, { "-o", 1, pOut, OutputDirectoryOption}, { "-p", 0, pPrt, "Print out the grammar w/o actions (default=no)"}, { "-pa", 0, pPrtA, "Print out the grammar w/o actions & w/FIRST sets (default=no)"}, { "-pr",0, pPred, "no longer used; predicates employed if present"}, { "-prc", 1, pPredCtx,"Turn on/off computation of context for hoisted predicates"}, { "-rl", 1, pTRes, "Limit max # of tree nodes used by grammar analysis"}, { "-stdout",0, pStdout, "Send grammar.c/grammar.cpp to stdout"}, /* MR6 */ { "-tab", 1, pTab, "Width of tabs (1 to 8) for grammar.c/grammar.cpp files"}, /* MR6 */ { "-w1", 0, pW1, "Set the warning level to 1 (default)"}, { "-w2", 0, pW2, "Ambiguities yield warnings even if predicates or (...)? block"}, { "-mrhoist",1,pMRhoist, /* MR9 */ "Turn on/off k=1 Maintenance Release style hoisting"}, /* MR9 */ { "-mrhoistk",1,pMRhoistk, /* MR13 */ "Turn on/off k>1 EXPERIMENTAL Maintenance Release style hoisting"}, /* MR13 */ { "-aa" ,1,pAA, "Ambiguity aid for a rule (rule name or line number)"}, /* MR11 */ { "-aam" ,0,pAAm, "Lookahead token may appear multiple times in -aa listing"}, /* MR11 */ { "-aad" ,1,pAAd, "Limits exp growth of -aa listing - default=1 (max=ck value)"}, /* MR11 */ { "-info",1,pInfo, "Extra info: p=pred t=tnodes f=first/follow m=monitor o=orphans 0=noop"}, /* MR11 */ { "-treport",1,pTreport, "Report when tnode usage exceeds value during ambiguity resolution"}, /* MR11 */ { "-newAST", 0, pNewAST, "In C++ mode use \"newAST(...)\" rather than \"new AST(...)\""}, /* MR13 */ { "-tmake", 0, ptmakeInParser, "In C++ mode use parser's tmake method rather than \"ASTBase::tmake(...)\""}, /* MR23 */ { "-alpha",0, pAlpha, "Provide additional information for \"(alpha)? beta\" error messages"}, /* MR14 */ { "-mrblkerr",0,pMR_BlkErr, /* MR21 */ "EXPERIMENTAL change to (...)* and (...)+ syntax error sets"}, /* MR21 */ { "-nopurify",0,pNOPURIFY, "Don't use the notorious PURIFY macro (replaced by MR23 initial value syntax) to zero return arguments of rules"}, /* MR23 */ { "-", 0, pStdin, "Read grammar from stdin" }, { "*", 0, pFile, "" }, /* anything else is a file */ #endif { NULL, 0, NULL } }; void readDescr(); void cleanUp(); #ifdef __USE_PROTOS static void buildRulePtr( void ); static void help( void ); static void init( void ); static void CompleteTokenSetRefs( void ); static void ensure_no_C_file_collisions(char *); static void CompleteContextGuards(void); #else static void buildRulePtr( ); static void help( ); static void init( ); static void CompleteTokenSetRefs( ); static void ensure_no_C_file_collisions(); static void CompleteContextGuards(); #endif static void #ifdef __USE_PROTOS /* */ report_numericPredLabels(ActionNode *a) #else report_numericPredLabels(a) ActionNode *a; #endif { /* MR10 */ warnFL("numeric references to attributes (e.g. $i or $i.j) in semantic pred will be null during guess mode", /* MR10 */ FileStr[a->file],a->line); /* MR10 */ } /* MR10 */ /* M a i n */ int #ifdef __USE_PROTOS main( int argc, char *argv[] ) #else main( argc, argv ) int argc; char *argv[]; #endif { int i; static char EPSTR[] = "[Ep]"; Save_argc=argc; /* MR10 */ Save_argv=argv; /* MR10 */ /* malloc_debug(8);*/ #ifdef SPECIAL_INITS special_inits(); /* MR1 */ #endif fprintf(stderr, "Antlr parser generator Version %s 1989-2001\n", Version); if ( argc == 1 ) { help(); zzDIE; } ProcessArgs(argc-1, &(argv[1]), options); /* MR14 */ if (MR_AmbAidRule && AlphaBetaTrace) { /* MR14 */ fatal("Can't specify both -aa (ambiguity aid) and -alpha (\"(alpha)? beta\" aid)"); /* MR14 */ } if (MRhoistingk) { /* MR13 */ HoistPredicateContext=1; /* MR13 */ MRhoisting=1; /* MR13 */ }; /* MR13 */ if (MRhoisting && ! HoistPredicateContext) { /*** warnNoFL("Using \"-mrhoist\" forces \"-prc on\""); ***/ HoistPredicateContext=1; }; if (HoistPredicateContext && ! MRhoisting) { warnNoFL("When using predicate context (-prc on) -mrhoist on is recommended"); } /* Fix lookahead depth */ /* Compressed lookahead must always be larger than or equal to full lookahead */ if ( CLL_k < LL_k && CLL_k>0 ) { warnNoFL("must have compressed lookahead >= full LL(k) lookahead (setting -ck to -k)"); CLL_k = LL_k; } if ( CLL_k == -1 ) CLL_k = LL_k; OutputLL_k = CLL_k; if ( ((CLL_k-1)&CLL_k)!=0 ) { /* output ll(k) must be power of 2 */ int n; for(n=1; n 1) { warnNoFL("The -mrblkerr option is designed only for k=1 ck=1 grammars"); } }; if ( ! ambAidDepthSpecified) { MR_AmbAidDepth=1; } else { if (MR_AmbAidDepth > CLL_k || MR_AmbAidDepth <= 0) { warnNoFL(eMsgd( "Ambiguity aid depth (\"-aad ...\") must be a number between 1 and max(k,ck)=%d",CLL_k)); MR_AmbAidDepth=1; }; if (MR_AmbAidDepth == 0) { MR_AmbAidDepth=2; }; }; if (MR_AmbAidRule != NULL) MR_AmbAidLine=atoi(MR_AmbAidRule); fpTrans = &(C_Trans[0]); /* Translate to C Language */ fpJTrans = &(C_JTrans[0]); init(); lexclass(LexStartSymbol); readDescr(); LastTokenCounted = TokenNum; RemapForcedTokens(); if ( CannotContinue ) {cleanUp(); zzDIE;} if ( GenCC && no_classes_found ) fatal("required grammar class not found (exiting...)"); if ( WarningLevel>1 && HdrAction == NULL ) warnNoFL("no #header action was found"); if ( FoundAtOperator && ! FoundExceptionGroup) { warnNoFL("found the exception operator '@' - but no exception group was found"); }; EpToken = addTname(EPSTR); /* add imaginary token epsilon */ set_orel(EpToken, &imag_tokens); /* this won't work for hand-built scanners since EofToken is not * known. Forces EOF to be token type 1. */ set_orel(EofToken, &imag_tokens); set_size(NumWords(TokenNum-1)); /* compute the set of all known token types * It represents the set of tokens from 1 to last_token_num + the * reserved positions above that (if any). Don't include the set of * imaginary tokens such as the token/error classes or EOF. */ { set a; a = set_dup(reserved_positions); for (i=1; inext; p!=NULL; p=p->next) { UserAction *ua = (UserAction *)p->elem; dumpAction( ua->action, Parser_h, 0, ua->file, ua->line, 1); } } GenParser_c_Hdr(); fprintf(Parser_h, "protected:\n"); /* MR20 */ NewSetWd(); TRANS(SynDiag); /* Translate to the target language */ DumpSetWd(); GenRuleMemberDeclarationsForCC(Parser_h, SynDiag); if ( class_after_actions != NULL ) { ListNode *p; for (p = class_after_actions->next; p!=NULL; p=p->next) { UserAction *ua = (UserAction *)p->elem; dumpAction( ua->action, Parser_h, 0, ua->file, ua->line, 1); } } DumpRemainingTokSets(); fprintf(Parser_h, "};\n"); fprintf(Parser_h, "\n#endif /* %s_h */\n", CurrentClassName); fclose( Parser_h ); fclose( Parser_c ); } } MR_orphanRules(stderr); if (LTinTokenAction && WarningLevel >= 2) { if (GenCC) { warnNoFL("At least one <> following a token match contains a reference to LT(...)\n this will reference the immediately preceding token,\n not the one which follows as is the case with semantic predicates."); } warnNoFL("At least one <> following a token match contains a reference to LA(...) or LATEXT(...)\n this will reference the immediately preceding token,\n not the one which follows as is the case with semantic predicates."); } if ( PrintOut ) { if ( SynDiag == NULL ) {warnNoFL("no grammar description recognized");} else PRINT(SynDiag); } #ifdef DBG_LL1 #endif GenRemapFile(); /* create remap.h */ /* MR10 */ if (FoundGuessBlk) { #ifdef __cplusplus__ /* MR10 */ list_apply(NumericPredLabels, (void (*)(void *))report_numericPredLabels); #else #ifdef __USE_PROTOS /* MR10 */ list_apply(NumericPredLabels, (void (*)(void *))report_numericPredLabels); #else /* MR10 */ list_apply(NumericPredLabels,report_numericPredLabels); #endif #endif /* MR10 */ }; if (InfoT && TnodesAllocated > 0) { if (TnodesPeak > 10000) { fprintf(stdout,"\nTree Nodes: peak %dk created %dk lost %d\n", (TnodesPeak/1000), (TnodesAllocated/1000), TnodesInUse-tnodes_used_in_guard_predicates_etc); } else { fprintf(stdout,"\nTree Nodes: peak %d created %d lost %d\n", TnodesPeak, TnodesAllocated, TnodesInUse-tnodes_used_in_guard_predicates_etc); }; }; if (InfoF) { DumpFcache(); }; if (MR_skipped_e3_report) { fprintf(stderr,"note: use -e3 to get exact information on ambiguous tuples\n"); }; if (MR_BadExprSets != 0) { fprintf(stderr,"note: Unreachable C or C++ code was generated for empty expression sets,\n"); fprintf(stderr," probably due to undefined rules or infinite left recursion.\n"); fprintf(stderr," To locate: search the generated code for \"empty set expression\"\n"); }; if (MR_AmbAidRule != NULL && MR_matched_AmbAidRule==0) { RuleEntry *q = (RuleEntry *) hash_get(Rname,MR_AmbAidRule); if (MR_AmbAidLine == 0 && q == NULL) { warnNoFL(eMsg2("there is no rule \"%s\" so \"-aa %s\" will never match", MR_AmbAidRule,MR_AmbAidRule)); } else { warnNoFL(eMsg1("there was no ambiguity that matched \"-aa %s\"",MR_AmbAidRule)); }; }; if (AlphaBetaTrace) { if (MR_AlphaBetaMessageCount == 0) { fprintf(stderr,"note: there were no messages about \"(alpha)? beta\" blocks added to the generated code\n"); } else { fprintf(stderr,"note: there were %d messages about \"(alpha)? beta\" blocks added to the generated code\n", MR_AlphaBetaMessageCount); } if (set_null(MR_CompromisedRules)) { fprintf(stderr,"note: the list of rules with compromised follow sets is empty\n"); } else { fprintf(stderr,"note: the following is a list of rules which *may* have incorrect\n"); fprintf(stderr," follow sets computed as a result of an \"(alpha)? beta\" block\n"); fprintf(stderr,"\n"); MR_dumpRuleSet(MR_CompromisedRules); fprintf(stderr,"\n"); } } cleanUp(); exit(PCCTS_EXIT_SUCCESS); return 0; /* MR11 make compilers happy */ } static void #ifdef __USE_PROTOS init( void ) #else init( ) #endif { SignalEntry *q; Tname = newHashTable(); Rname = newHashTable(); Fcache = newHashTable(); Tcache = newHashTable(); Sname = newHashTable(); Pname = newHashTable(); /* MR11 */ /* Add default signal names */ q = (SignalEntry *)hash_add(Sname, "NoViableAlt", (Entry *)newSignalEntry("NoViableAlt")); require(q!=NULL, "cannot alloc signal entry"); q->signum = sigNoViableAlt; q = (SignalEntry *)hash_add(Sname, "MismatchedToken", (Entry *)newSignalEntry("MismatchedToken")); require(q!=NULL, "cannot alloc signal entry"); q->signum = sigMismatchedToken; q = (SignalEntry *)hash_add(Sname, "NoSemViableAlt", (Entry *)newSignalEntry("NoSemViableAlt")); require(q!=NULL, "cannot alloc signal entry"); q->signum = sigNoSemViableAlt; reserved_positions = empty; all_tokens = empty; imag_tokens = empty; tokclasses = empty; TokenStr = (char **) calloc(TSChunk, sizeof(char *)); require(TokenStr!=NULL, "main: cannot allocate TokenStr"); FoStack = (int **) calloc(CLL_k+1, sizeof(int *)); require(FoStack!=NULL, "main: cannot allocate FoStack"); FoTOS = (int **) calloc(CLL_k+1, sizeof(int *)); require(FoTOS!=NULL, "main: cannot allocate FoTOS"); Cycles = (ListNode **) calloc(CLL_k+1, sizeof(ListNode *)); require(Cycles!=NULL, "main: cannot allocate Cycles List"); MR_CompromisedRules=empty; /* MR14 */ } static void #ifdef __USE_PROTOS help( void ) #else help( ) #endif { Opt *p = options; fprintf(stderr, "antlr [options] f1 f2 ... fn\n"); while ( *(p->option) != '*' ) { fprintf(stderr, " %-9s%s %s\n", p->option, (p->arg)?"___":" ", p->descr); p++; } } /* The RulePtr array is filled in here. RulePtr exists primarily * so that sets of rules can be maintained for the FOLLOW caching * mechanism found in rJunc(). RulePtr maps a rule num from 1 to n * to a pointer to its RuleBlk junction where n is the number of rules. */ static void #ifdef __USE_PROTOS buildRulePtr( void ) #else buildRulePtr( ) #endif { int r=1; Junction *p = SynDiag; RulePtr = (Junction **) calloc(NumRules+1, sizeof(Junction *)); require(RulePtr!=NULL, "cannot allocate RulePtr array"); while ( p!=NULL ) { require(r<=NumRules, "too many rules???"); RulePtr[r++] = p; p = (Junction *)p->p2; } } void #ifdef __USE_PROTOS dlgerror(const char *s) #else dlgerror(s) char *s; #endif { fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); fprintf(stderr, " lexical error: %s (text was '%s')\n", ((s == NULL) ? "Lexical error" : s), zzlextext); } void #ifdef __USE_PROTOS readDescr( void ) #else readDescr( ) #endif { zzerr = dlgerror; input = NextFile(); if ( input==NULL ) fatal("No grammar description found (exiting...)"); ANTLR(grammar(), input); tnodes_used_in_guard_predicates_etc=TnodesInUse; /* MR10 */ } FILE * #ifdef __USE_PROTOS NextFile( void ) #else NextFile( ) #endif { FILE *f; for (;;) { CurFile++; if ( CurFile >= NumFiles ) return(NULL); if ( ci_strequ(FileStr[CurFile],"stdin")) return stdin; f = fopen(FileStr[CurFile], "r"); if ( f == NULL ) { warnNoFL( eMsg1("file %s doesn't exist; ignored", FileStr[CurFile]) ); } else { return(f); } } } /* * Return a string corresponding to the output file name associated * with the input file name passed in. * * Observe the following rules: * * f.e --> f".c" * f --> f".c" * f. --> f".c" * f.e.g --> f.e".c" * * Where f,e,g are arbitrarily long sequences of characters in a file * name. * * In other words, if a ".x" appears on the end of a file name, make it * ".c". If no ".x" appears, append ".c" to the end of the file name. * * C++ mode using .cpp not .c. * * Use malloc() for new string. */ char * #ifdef __USE_PROTOS outname( char *fs ) #else outname( fs ) char *fs; #endif { if ( GenCC) { return outnameX(fs,CPP_FILE_SUFFIX); } else { return outnameX(fs,".c"); }; } char * #ifdef __USE_PROTOS outnameX( char *fs ,char *suffix) #else outnameX( fs , suffix ) char *fs; char *suffix; #endif { static char buf[MaxFileName+1]; char *p; require(fs!=NULL&&*fs!='\0', "outname: NULL filename"); p = buf; strcpy(buf, fs); while ( *p != '\0' ) {p++;} /* Stop on '\0' */ while ( *p != '.' && p != buf ) {--p;} /* Find '.' */ if ( p != buf ) *p = '\0'; /* Found '.' */ require(strlen(buf) + 2 < (size_t)MaxFileName, "outname: filename too big"); strcat(buf,suffix); return( buf ); } void #ifdef __USE_PROTOS fatalFL( char *err_, char *f, int l ) #else fatalFL( err_, f, l ) char *err_; char *f; int l; #endif { fprintf(stderr, ErrHdr, f, l); fprintf(stderr, " %s\n", err_); cleanUp(); exit(PCCTS_EXIT_FAILURE); } void #ifdef __USE_PROTOS fatal_intern( char *err_, char *f, int l ) #else fatal_intern( err_, f, l ) char *err_; char *f; int l; #endif { fprintf(stderr, ErrHdr, f, l); fprintf(stderr, " #$%%*&@# internal error: %s\n", err_); fprintf(stderr, ErrHdr, f, l); fprintf(stderr, " [complain to nearest government official\n"); fprintf(stderr, ErrHdr, f, l); fprintf(stderr, " or send hate-mail to parrt@parr-research.com;\n"); fprintf(stderr, ErrHdr, f, l); fprintf(stderr, " please pray to the ``bug'' gods that there is a trival fix.]\n"); cleanUp(); exit(PCCTS_EXIT_FAILURE); } void #ifdef __USE_PROTOS cleanUp( void ) #else cleanUp( ) #endif { if ( DefFile != NULL) fclose( DefFile ); } /* sprintf up to 3 strings */ char * #ifdef __USE_PROTOS eMsg3( char *s, char *a1, char *a2, char *a3 ) #else eMsg3( s, a1, a2, a3 ) char *s; char *a1; char *a2; char *a3; #endif { static char buf[250]; /* DANGEROUS as hell !!!!!! */ sprintf(buf, s, a1, a2, a3); return( buf ); } /* sprintf a decimal */ char * #ifdef __USE_PROTOS eMsgd( char *s, int d ) #else eMsgd( s, d ) char *s; int d; #endif { static char buf[250]; /* DANGEROUS as hell !!!!!! */ sprintf(buf, s, d); return( buf ); } char * #ifdef __USE_PROTOS eMsgd2( char *s, int d1,int d2) #else eMsgd2( s, d1, d2 ) char *s; int d1; int d2; #endif { static char buf[250]; /* DANGEROUS as hell !!!!!! */ sprintf(buf, s, d1, d2); return( buf ); } void #ifdef __USE_PROTOS s_fprT( FILE *f, set e ) #else s_fprT( f, e ) FILE *f; set e; #endif { register unsigned *p; unsigned *q; if ( set_nil(e) ) return; if ( (q=p=set_pdq(e)) == NULL ) fatal_internal("Can't alloc space for set_pdq"); fprintf(f, "{"); while ( *p != nil ) { fprintf(f, " %s", TerminalString(*p)); p++; } fprintf(f, " }"); free((char *)q); } /* Return the token name or regular expression for a token number. */ char * #ifdef __USE_PROTOS TerminalString( int token ) #else TerminalString( token ) int token; #endif { int j; static char imag_name[25]; /* look in all lexclasses for the token */ if ( TokenString(token) != NULL ) return TokenString(token); for (j=0; j0, "pushint: stack overflow"); istack[--isp] = i; } int #ifdef __USE_PROTOS popint( void ) #else popint( ) #endif { require(isp 0 ) { p = options; while ( p->option != NULL ) { if ( strcmp(p->option, "*") == 0 || ci_strequ(p->option, *argv) == 1 ) { if ( p->arg ) { /* MR9 26-Sep-97 Check for argv valid */ if (argc-- > 0) { (*p->process)( *argv, *(argv+1) ); argv++; } else { fprintf(stderr,"error: required argument for option %s omitted\n",*argv); exit(PCCTS_EXIT_FAILURE); }; } else (*p->process)( *argv ); break; } p++; } argv++; } } static void #ifdef __USE_PROTOS CompleteContextGuards(void) #else CompleteContextGuards() #endif { ListNode * p; Predicate * pred; if (ContextGuardPredicateList == NULL) return; for (p=ContextGuardPredicateList->next; p != NULL; p=p->next) { pred=(Predicate *)p->elem; recomputeContextGuard(pred); } } /* Go back into the syntax diagram and compute all meta tokens; i.e. * turn all '.', ranges, token class refs etc... into actual token sets */ static void #ifdef __USE_PROTOS CompleteTokenSetRefs(void) #else CompleteTokenSetRefs() #endif { ListNode *p; if ( MetaTokenNodes==NULL ) return; for (p = MetaTokenNodes->next; p!=NULL; p=p->next) { set a,b; TokNode *q = (TokNode *)p->elem; if ( q->wild_card ) { q->tset = all_tokens; } else if ( q->tclass!=NULL ) { if ( q->complement ) q->tset = set_dif(all_tokens, q->tclass->tset); else q->tset = q->tclass->tset; } else if ( q->upper_range!=0 ) { /* we have a range on our hands: make a set from q->token .. q->upper_range */ int i; a = empty; for (i=q->token; i<=q->upper_range; i++) { set_orel(i, &a); } /* MR13 */ /* MR13 */ if (q->complement) { /* MR13 */ q->tset = set_dif(all_tokens, a); /* MR13 */ set_free(a); /* MR13 */ } else { /* MR13 */ q->tset = a; /* MR13 */ } } /* at this point, it can only be a complemented single token */ else if ( q->complement ) { a = set_of(q->token); b = set_dif(all_tokens, a); set_free(a); q->tset=b; } else fatal("invalid meta token"); } } /* MR10: Jeff Vincent MR10: Changed to remove directory information from n only if MR10: if OutputDirectory was changed by user (-o option) */ char * #ifdef __USE_PROTOS OutMetaName(char *n) #else OutMetaName(n) char *n; #endif { static char *dir_sym = DirectorySymbol; static char newname[MaxFileName+1]; char *p; /* If OutputDirectory is same as TopDirectory (platform default) then leave n alone. */ if (strcmp(OutputDirectory, TopDirectory) == 0) /* TopDirectory is "." on Unix. */ return n; /* p will point to filename without path information */ if ((p = strrchr(n, *dir_sym)) != NULL) /* Directory symbol is "/" on Unix. */ p++; else p = n; /* Copy new output directory into newname[] */ strcpy(newname, OutputDirectory); /* if new output directory does not have trailing dir_sym, add it! */ if (newname[strlen(newname)-1] != *dir_sym) { strcat(newname, dir_sym); } strcat(newname, p); return newname; } char * #ifdef __USE_PROTOS pcctsBaseName(char *n) /* MR32 */ #else pcctsBaseName(n) char *n; #endif { static char newname[MaxFileName+1]; static char* dir_sym = DirectorySymbol; int count = 0; char *p; p = n; while ( *p != '\0' ) {p++;} /* go to end of string */ while ( (*p != *dir_sym) && (p != n) ) {--p;} /* Find last DirectorySymbol */ while ( *p == *dir_sym) p++; /* step forward if we're on a dir symbol */ while ( *p != '\0' && *p != '.') { newname[count++] = *p; p++; } /* create a new name */ newname[count] = '\0'; return newname; } static void #ifdef __USE_PROTOS ensure_no_C_file_collisions(char *class_c_file) #else ensure_no_C_file_collisions(class_c_file) char *class_c_file; #endif { int i; for (i=0; i= NumFiles && CurFile >= 1 ) CurFile--; fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); fprintf(stderr, " warning: %s\n", err); } void #ifdef __USE_PROTOS warnNoCR( char *err ) #else warnNoCR( err ) char *err; #endif { /* back up the file number if we hit an error at the end of the last file */ if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--; fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); fprintf(stderr, " warning: %s", err); } void #ifdef __USE_PROTOS errNoFL(char *err) #else errNoFL(err) char *err; #endif { fprintf(stderr, "error: %s\n", err); } void #ifdef __USE_PROTOS errFL(char *err,char *f,int l) #else errFL(err,f,l) char *err; char *f; int l; #endif { fprintf(stderr, ErrHdr, f, l); fprintf(stderr, " error: %s\n", err); } void #ifdef __USE_PROTOS err(char *err) #else err(err) char *err; #endif { /* back up the file number if we hit an error at the end of the last file */ if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--; fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); fprintf(stderr, " error: %s\n", err); } void #ifdef __USE_PROTOS errNoCR( char *err ) #else errNoCR( err ) char *err; #endif { /* back up the file number if we hit an error at the end of the last file */ if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--; fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); fprintf(stderr, " error: %s", err); } UserAction * #ifdef __USE_PROTOS newUserAction(char *s) #else newUserAction(s) char *s; #endif { UserAction *ua = (UserAction *) calloc(1, sizeof(UserAction)); require(ua!=NULL, "cannot allocate UserAction"); ua->action = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); strcpy(ua->action, s); return ua; } /* Added by TJP September 1994 */ /* Take in file.h and return file_h; names w/o '.'s are left alone */ char * #ifdef __USE_PROTOS gate_symbol(char *name) #else gate_symbol(name) char *name; #endif { static char buf[100]; char *p; sprintf(buf, "%s", name); for (p=buf; *p!='\0'; p++) { if ( *p=='.' ) *p = '_'; } return buf; } char * #ifdef __USE_PROTOS makeAltID(int blockid, int altnum) #else makeAltID(blockid, altnum) int blockid; int altnum; #endif { static char buf[100]; char *p; sprintf(buf, "_blk%d_alt%d", blockid, altnum); p = (char *)malloc(strlen(buf)+1); strcpy(p, buf); return p; }