#include #include #include #if __MSDOS__ || MSDOS || WIN32 || __WIN32__ # include #else # include # define O_BINARY 0 #endif #if NEXTSTEP # include #endif #include #include "crt.h" #include "crx.h" #include "cra.h" #include "crf.h" #include "crp.h" #include "crs.h" struct ErrDesc { int nr, line, col; struct ErrDesc *next; }; static FILE *lst; static struct ErrDesc *FirstErr = NULL, *LastErr; int Errors = 0; extern Error_Func Custom_Error; static char *ErrorMsg[] = { #include "cre.h" "User error number clash", "" }; static char Version[] = "1.17 (C/C++ Version)"; static char ReleaseDate[] = "Sep 17 2002"; /* --------------------------- Help ------------------------------------------ */ static void Help(void) { fprintf(stdout, "Coco/R - Compiler-Compiler V%s " "(Frankie Arzu, %s)\n\n" "Usage: COCOR [(/|-)Options] for Dos/Windows\n" "Usage: COCOR [-Options] for Unix\n" "Example: COCOR -C -S Test.atg\n\n" "Options:\n" "A - Trace automaton C - Generate compiler module\n" "D - Include source debugging information (#line)\n" "F - Give Start and Follower sets G - Print top-down graph\n" "L - Force listing O - Terminal conditions use OR only\n" "P - Generate parser only S - Print symbol table\n" "T - Grammar tests only Q - Quiet (Edit) mode\n" "X - Generate C++ with classes Z - Force extensions to .hpp and .cpp\n\n" "Environment variables:\n" "CRFRAMES: Search directory for frames file. If not specified,\n" " frames must be in the working directory.\n" "CRHEXT: Extension for the '.h' generated files. If not specified,\n" " '.h' for C, '.hpp' for C++ (Dos and Unix). \n" "CRCEXT: Extension for the '.c' generated files. If not specified,\n" " '.c' for C, '.cpp' for C++ (Dos and Unix). \n" "Frame and extension options may also be set using -Dvarname=value\n", Version, ReleaseDate); } void StoreError(int nr, int line, int col, long pos) /* Store an error message for later printing */ { struct ErrDesc *NextErr; NextErr = (struct ErrDesc *) malloc(sizeof(struct ErrDesc)); NextErr->nr = nr; NextErr->line = line; NextErr->col = col; NextErr->next = NULL; if (FirstErr == NULL) FirstErr = NextErr; else LastErr->next = NextErr; LastErr = NextErr; Errors++; } static long GetLine(long pos, char *line) /* Read a source line. Return empty line if eof */ { char ch; int i; int col = 1; ch = S_CurrentCh(pos); while (ch && ch != LF_CHAR && ch != EOF_CHAR) { if (ch == TAB_CHAR) { i = TAB_SIZE - (col % TAB_SIZE) + 1; while (i--) { *line++ = ' '; col++; } } else if (ch != CR_CHAR) { *line++ = ch; col++; } pos++; ch = S_CurrentCh(pos); } *line = 0; if (ch != EOF_CHAR) return pos + 1; else return -1; } static void PrintErrMsg(int nr) { if (nr <= MAXERROR) fprintf(lst, "%s", ErrorMsg[nr]); else switch (nr) { case 101: fprintf(lst, "character set may not be empty"); break; case 102: fprintf(lst, "string literal may not extend over line end"); break; case 103: fprintf(lst, "a literal must not have attributes"); break; case 104: fprintf(lst, "this symbol kind not allowed in production"); break; case 105: fprintf(lst, "attribute mismatch between declaration and use"); break; case 106: fprintf(lst, "undefined string in production"); break; case 107: fprintf(lst, "name declared twice"); break; case 108: fprintf(lst, "this type not allowed on left side of production"); break; case 109: fprintf(lst, "earlier semantic action was not terminated"); break; case 111: fprintf(lst, "no production found for grammar name"); break; case 112: fprintf(lst, "grammar symbol must not have attributes"); break; case 113: fprintf(lst, "a literal must not be declared with a structure"); break; case 114: fprintf(lst, "semantic action not allowed here"); break; case 115: fprintf(lst, "undefined name"); break; case 116: fprintf(lst, "attributes not allowed in token declaration"); break; case 117: fprintf(lst, "name does not match name in heading"); break; case 118: fprintf(lst, "unacceptable constant value"); break; case 119: fprintf(lst, "may not ignore CHR(0)"); break; case 120: fprintf(lst, "token might be empty"); break; case 121: fprintf(lst, "token must not start with an iteration"); break; case 122: fprintf(lst, "comment delimiters may not be structured"); break; case 123: fprintf(lst, "only terminals may be weak"); break; case 124: fprintf(lst, "literal tokens may not contain white space"); break; case 125: fprintf(lst, "comment delimiter must be 1 or 2 characters long"); break; case 126: fprintf(lst, "character set contains more than one character"); break; case 127: fprintf(lst, "\ncould not make deterministic automaton, check previous token errors"); break; case 129: fprintf(lst, "literal tokens may not be empty"); break; case 130: fprintf(lst, "IGNORE CASE must appear earlier"); break; } fprintf(lst, " (E%d)",nr); } static void PrintErr(int nr, int col) { fprintf(lst, "*****"); while (col--) fprintf(lst, " "); fprintf(lst, " ^ "); PrintErrMsg(nr); fprintf(lst, "\n"); } static void PrintListing(void) /* Print a source listing with error messages */ { struct ErrDesc *nextErr; int lnr, errC; long srcPos; char line[255]; fprintf(lst, "Listing:\n\n"); srcPos = 0; nextErr = FirstErr; srcPos = GetLine(srcPos, line); lnr = 1; errC = 0; while (srcPos != -1) { fprintf(lst, "%5d %s\n", lnr, line); while (nextErr != NULL && nextErr->line == lnr) { PrintErr(nextErr->nr, nextErr->col); errC++; nextErr = nextErr->next; } srcPos = GetLine(srcPos, line); lnr++; } if (nextErr != NULL) { fprintf(lst, "%5d\n", lnr); while (nextErr != NULL) { PrintErr(nextErr->nr, nextErr->col); errC++; nextErr = nextErr->next; } } fprintf(lst, "\n\n%5d syntax errors\n", errC); } void SummarizeErrors(void) /* Summarize error messages */ { struct ErrDesc *nextErr; nextErr = FirstErr; while (nextErr != NULL) { if (Q_option) fprintf(lst, "%s (%d, %d) ", source_name, nextErr->line, nextErr->col); else fprintf(lst, "\"%s\", Line %d, Col %d: ", source_name, nextErr->line, nextErr->col); PrintErrMsg(nextErr->nr); fprintf(lst, "\n"); nextErr = nextErr->next; } } static void param_options(int argc,char *argv[]) { int i; for (i = 1; i < argc; i++) #if __MSDOS__ || MSDOS || WIN32 || __WIN32__ if (*argv[i] == '-' || *argv[i] == '/') SetOptions(argv[i]); #else if (*argv[i] == '-') SetOptions(argv[i]); #endif else strcpy(source_name, argv[i]); } static void FileGetName(char *name, char *filename) { int i; strcpy(name, filename); i = strlen(name)-1; while (i>0 && name[i] != '.') i--; name[i]='\0'; } int main(int argc, char *argv[]) { char name[100]; lst = stderr; if (argc == 1) { Help(); exit(EXIT_FAILURE); } InitFrameVars(); source_name[0] = '\0'; param_options(argc, argv); /* check on correct parameter usage */ if (source_name[0] == 0) { fprintf(stderr, "No input file specified"); exit(EXIT_FAILURE); } /* open the Source file (Scanner.S_src) */ if ((S_src = open(source_name, O_RDONLY|O_BINARY)) == -1) { fprintf(stderr, "Unable to open input file %s\n", source_name); exit(EXIT_FAILURE); } /* open the listing file */ if (L_option) { FileGetName(name, source_name); strcat(name, ".lst"); lstfile = OpenFile(name, "w", 1); } else if (!Q_option) lstfile = stderr; else lstfile = stdout; /* install error reporting procedure */ Custom_Error = (Error_Func) StoreError; InitTab(); InitScannerTab(); Parse(); close(S_src); lst = lstfile; if (Errors && !L_option) SummarizeErrors(); else if (Errors || L_option) PrintListing(); if (Errors) { /* Check for Syntax Errors */ fclose(lstfile); exit(EXIT_FAILURE); } MakeScanner(); MakeParser(); if (Errors) { /* Check for LL(1) Errors, Undeclared Symbols, etc */ fclose(lstfile); exit(EXIT_FAILURE); } SetupFrameVars(); if (!T_option) { if (!P_option) GenScanner(); GenParser(); GenHeaders(); if (C_option) GenCompiler(); } if (L_option) { if (S_option) { ShowClassTab(); ShowTermTab(); ShowCommentTab(); ShowSymSetTab(); ShowNTermTab(); } if (A_option) ShowDFA(); fclose(lstfile); } DoneTab(); DoneScannerTab(); return (EXIT_SUCCESS); }