home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************/
- /* y2.c */
- /* YACC source file #2 (of 4). */
- /* Scanner, parser and symbol table code. */
- /************************************************************************/
-
- /************************************************************************/
- /* contents */
- /* */
- /* * y2CpyAction Copy C action to the next ; or closing } */
- /* * y2CpyCode Copy code between %{ and %} to output. */
- /* * y2CpyUnion Copy a union declaration to output. */
- /* * y2Define Define s to be a terminal or nonterminal. */
- /* * y2EnterSymbol Store id or literal in y2Text[], return address.*/
- /* * y2FindName Identify terminal/nonterminal. */
- /* * y2GetToken */
- /* y2Initialize Initialize parser, then call y2yyParse. */
- /* * y2SkipComment Skip over comments. */
- /* * y2TypeOf Determine the type of a symbol. */
- /* * y2Usage */
- /* * y2WriteDefines Post declarations: write out the defines */
- /* y2yyParse Kludged YACC input parser. */
- /* */
- /* * Local to this file. */
- /* */
- /************************************************************************/
-
-
- /************************************************************************/
- /* history */
- /* */
- /* 85Nov22 CrT Below fouled up YYACCEPT/YYERROR. Fixed. */
- /* 85Nov18 CrT User action chunks are now placed in functions rather */
- /* than switch cases. The functions are accessed by an */
- /* array of function pointers. This is because many */
- /* compilers have low limits on the size of functions, */
- /* switch statements, and the number of cases in a */
- /* switch statement. In addition, some compilers implement*/
- /* switch statements with a cascade of comparisons rather */
- /* than a jump table. */
- /* 85Nov17 CrT I had a } wrong in y2Define. Fixed. */
- /* 85Nov17 CrT Changed 'begin:' to 'start:' in y2GetToken, because */
- /* BDS C treats 'begin's as '{'s, with confusing results. */
- /* (This problem reported by Robert A. McIvor in '79.) */
- /* 85Nov15 CrT Global variable names decrypted. */
- /* 85Nov13 CrT Give plaintiff routine in error messages. */
- /* 85Nov12 CrT Function names decrypted. Still unique in first 6 chars.*/
- /* 85Nov10 CrT y2.c reconstructed from 12 subfiles. Cosmetics. */
- /* 83Dec23 SG Adapted for IBM PC/XT & DeSmet C compiler */
- /* 83May15 SG Fixed up option flag handling for RT-11. */
- /* 83Apr12 RBD Make filename[] size per #define'd */
- /* FNAMESIZE so VAX filenames won't blow out. */
- /* Conditionalize time handling for banner. */
- /* Make filespec buffer static for safety, */
- /* since global "infile" is pointed to it. */
- /* 82Mar22 RBD Added header line, changes for 'new' DECUS library */
- /* */
- /* 81Aug27 RBD Modified for use with DECUS LEX */
- /* Variable "yylval" resides in yylex(), not in yypars(); */
- /* Therefore, is defined "extern" here. */
- /* */
- /* Also, the command line processing for the Decus version */
- /* has been changed. A new switch has been added to allow */
- /* specification of the "table" file name(s), and unused */
- /* switch processing removed. */
- /* NOTE */
- /* This probably won't run on UNIX any more. */
- /* */
- /* 7?????? SCJ Created. */
- /* */
- /* credits */
- /* CrT=CrT */
- /* RBD=Bob Denny */
- /* SCJ=Steven C Johnson. */
- /* SG =Scott Guthery */
- /************************************************************************/
-
-
- #include <stdio.h>
- #include "system.h"
- #include "dtxtrn.h"
-
-
-
-
- /* Token types returned by yacc's input scanner: */
- # define IDENTIFIER 257 /* Identifier NOT followed by colo. */
- # define MARK 258 /* %% */
- # define TERMINAL 259 /* %0 or %term or %token */
- # define LEFT 260 /* %< or %left */
- # define RIGHT 261 /* %> or %right */
- # define BINARY 262 /* %2 or %binary or %nonassoc */
- # define PREC 263 /* %= or %prec */
- # define LCURLY 264 /* %{ */
- # define C_IDENTIFIER 265 /* An IDENTIFIER followed by a colon. */
- # define NUMBER 266 /* A number */
- # define START 267 /* %start */
- # define TYPEDEF 268 /* %type */
- # define TYPENAME 269 /* */
- # define UNION 270 /* %union */
- # define ENDFILE 0 /* */
-
-
- /* Arguments for y2Define: */
- #define TYPEtERMINAL 0
- #define TYPEnONTERMINAL 1
- #define TYPEpREC 2
-
-
-
- /* Communication variables between various I/O routines: */
-
- static int y2InputNumberValue; /* Value of an input number. */
- static char y2InputTokenText[ NAMEsIZE ]; /* Input token name. */
-
-
-
- /* Storage for names: */
-
- static char y2Text[ MAXy2TEXT ]; /* Contains text of all names. */
- static char *y2TextFree = y2Text; /* Remaining free space in y2Text[]. */
- static int y2NumberOfDefinedSymbolsWritten = 3;
-
-
-
- /* Storage for user-declared types ("<...>" commands): */
-
- /* Pointers to names of types, secreted in y2Text: */
- static char * y2TypeName[ MAXtYPES ];
-
- static int y2NumberOfTypesDefined;
-
-
-
- /* Symbol tables for tokens and nonterminals: */
-
- /* Table giving external name and internal number for each terminal: */
- struct toksymb y2Terminal[ MAXtERMINALsTATES ];
-
- /* Bit vectors giving associativity and precedence of each terminal: */
- int y2TerminalProperties[ MAXtERMINALsTATES ];
- int y2NextTerminal = 0;
-
- /* Table giving external name and internal number for nonterminals: */
- struct ntsymb y2NonterminalState[ MAXnONTERMINALsTATES ];
- int y2LastNonterminal = -1;
-
- static int y2RootNonterminal; /* "%start" symbol. */
-
-
-
- /* Next internal terminal number to assign: */
- static int y2NextTerminalNumber = 0; /* y2Initialize sets it to 0400 */
-
-
-
- /* Input and output file descriptors: */
-
- FILE * y2InputFD; /* Yacc input file. */
- FILE * y2ActionFD; /* File to saving actions in. */
- FILE * y2DefineFD; /* File for # defines. */
- FILE * y2ytabcFD; /* y.tab.c file. */
- FILE * y2TempFileFD; /* Temp. file to pass 2. */
- FILE * y2OutputFD; /* y.output file. */
-
-
-
- /************************************************************************/
- /* */
- /* Storage for grammar rules. Grammar rules are packed sequentially */
- /* into y2Pool[]. y2Production[i] points to the start of the ith */
- /* grammar rule. A grammar rule consists of a sequence of positive */
- /* integers terminated by a negative integer. The positive integers */
- /* are parts of the rule, the negative integer is -i. Positive */
- /* integers less than FIRSTnONTERMINAL are terminals, others are */
- /* nonterminals -- subtracting FIRSTnONTERMINAL gives the correct */
- /* offset into y2NonterminalState[]. The first entry in the rule is */
- /* the LHS -- the nonterminal being defined -- and the remainder give */
- /* the right hand side. */
- /* */
- /* Actions are always fired at the end of a rule. (Input rules with */
- /* actions in the middle are split into multiple rules.) When actions */
- /* are encountered, a switch case labeled with the rule number is */
- /* generated, and the RULEhASaCTION bit for that rule set. Thus, when */
- /* we later generate code reducing this rule, we need only check the */
- /* RULEhASaCTION and, if set, synthesize a call from the rule number. */
- /* */
- /************************************************************************/
-
- /* Buffer to pack productions into: */
- int y2Pool[ MAXy2POOL ];
-
- /* Pointer to start of free space in y2Pool: */
- int *y2FreePool = y2Pool;
-
- /* Count of number of productions in currently in y2Pool: */
- int y2ThisProduction= 1;
-
- /* Pointers into y2Pool, giving the start of each production in it: */
- int *y2Production[ MAXpRODUCTIONS ];
-
- /* The production precedence levels. Same bit */
- /* vector format as y2TerminalProperties: */
- int y2ProductionProperties[ MAXpRODUCTIONS ] ;
-
-
-
-
-
-
-
-
- /************************************************************************/
- /* y2CpyAction Copy C action to the next ; or closing } */
- /************************************************************************/
- static y2CpyAction( offset ) /* Called only from y2yyParse */
- int offset; /* Number of arguments seen in production */
- {
- int braceDepth, c, match, j, s, tok;
-
- #ifdef OLD
- /* Create a "case...:" for the impending action: */
- fprintf( y2ActionFD, "\ncase %d:", y2ThisProduction );
- #else
- /* Create a function for the impending action: */
- fprintf( y2ActionFD, "static yyA%03d() {", y2ThisProduction );
- #endif
- /* Pass current line number to output: */
- fprintf( y2ActionFD, "\n# line %d\n", y1LineNumber );
-
- braceDepth = 0;
-
- lup:
- c = y1GetChar( y2InputFD );
-
- swtch:
- switch( c ) {
-
- case ';':
- if (braceDepth == 0) {
- putc( c , y2ActionFD );
- goto cpyActEnd;
- }
- goto lcopy;
-
- case '{':
- braceDepth++;
- goto lcopy;
-
- case '$':
- s = 1;
- tok = -1;
- c = y1GetChar( y2InputFD );
-
- if (c == '<') {
-
- /* Type description: */
- y1UngetChar( c, y2InputFD );
- if (y2GetToken() != TYPENAME) {
- y1Error( "y2CpyAction: Bad syntax on $<ident> clause" );
- }
- tok = y2InputNumberValue;
- c = y1GetChar( y2InputFD );
- }
- if (c == '$') {
- fprintf( y2ActionFD, "yyval");
- if (y2NumberOfTypesDefined) {
-
- /* Put out the proper name: */
- if (tok < 0) {
- tok = y2TypeOf( *y2Production[ y2ThisProduction ] );
- }
- fprintf( y2ActionFD, ".%s", y2TypeName[tok] );
- }
- goto lup;
- }
- if (c == '-') {
- s = -s;
- c = y1GetChar( y2InputFD );
- }
- if (isdigit( c )) {
-
- /* Handle a $3 type action argument: */
-
- /* Collect the numerical value in j: */
- j = 0;
- while (isdigit( c )) {
- j = j * 10 + c - '0';
- c = y1GetChar( y2InputFD );
- }
- j = j * s - offset;
-
- /* Can't refer to part of rule not seen yet: */
- if (j > 0) y1Error( "y2CpyAction: Illegal use of $%d", j+offset );
-
- /* Compile code for $n variable reference: */
- fprintf( y2ActionFD, "yypvt[-%d]", -j );
-
- /* Special code if we are stacking unions instead of ints: */
- if (y2NumberOfTypesDefined) {
-
- /* Put out the proper name: */
-
- if (j+offset <= 0 && tok < 0) {
- y1Error(
- "y2CpyAction: Must specify type of $%d",
- j+offset
- );
- }
- if (tok < 0) {
- tok = y2TypeOf(
- y2Production[ y2ThisProduction ][ j+offset ]
- );
- }
- fprintf( y2ActionFD, ".%s", y2TypeName[tok] );
- }
- goto swtch;
- }
- putc( '$' , y2ActionFD );
- if (s < 0) putc( '-', y2ActionFD );
- goto swtch;
-
- case '}':
- if (--braceDepth) goto lcopy;
- putc( c, y2ActionFD );
- goto cpyActEnd;
-
- case '/':
- /* Look for comments: */
- putc( c , y2ActionFD );
- c = y1GetChar( y2InputFD );
- if (c != '*') goto swtch;
-
- /* It really is a comment: */
-
- putc( c , y2ActionFD );
- c = y1GetChar( y2InputFD );
- while (c != EOF) {
- while (c == '*') {
- putc( c , y2ActionFD );
- if ((c = y1GetChar( y2InputFD )) == '/') goto lcopy;
- }
- putc( c , y2ActionFD );
- if (c == '\n') ++y1LineNumber;
- c = y1GetChar( y2InputFD );
- }
- y1Error( "y2CpyAction: EOF inside comment" );
-
- case '\'':
- /* Character constant: */
- match = '\'';
- goto string;
-
- case '"':
- /* Character string: */
- match = '"';
-
- string:
-
- putc( c, y2ActionFD );
- while (c = y1GetChar( y2InputFD )) {
- if (c == '\\') {
- putc( c , y2ActionFD );
- c = y1GetChar(y2InputFD);
- if (c == '\n') ++y1LineNumber;
- } else if( c==match ) {
- goto lcopy;
- } else if( c=='\n' ) {
- y1Error( "y2CpyAction: Newline in string or char constant" );
- }
- putc( c , y2ActionFD );
- }
- y1Error( "y2CpyAction: EOF in string or character constant" );
-
- case EOF:
- /* EOF: */
- y1Error( "y2CpyAction: Action does not terminate" );
-
- case '\n':
- ++y1LineNumber;
- goto lcopy;
- }
-
- lcopy:
- putc( c, y2ActionFD );
- goto lup;
-
-
- cpyActEnd:
- #ifdef OLD
- /* Wrap up this "case" in the action switch statement: */
- fprintf( y2ActionFD, " break;" );
- #else
- /* Wrap up this action fn: */
- fprintf( y2ActionFD, "\n return -1;\n}\n\n" );
- #endif
- }
-
-
- /************************************************************************/
- /* y2CpyCode Copy code between \{ and \} to output. */
- /************************************************************************/
- static y2CpyCode() {
-
- int c;
-
- c = y1GetChar( y2InputFD );
-
- if (c == '\n') {
- c = y1GetChar( y2InputFD );
- y1LineNumber++;
- }
-
- /* Pass line number to output file: */
- fprintf( y2ytabcFD, "\n# line %d\n", y1LineNumber );
-
- /* Copy the code over: */
- while (c != EOF) {
- if (c == '\\') {
- if ((c = y1GetChar(y2InputFD)) == '}') return;
- else putc('\\', y2ytabcFD );
- }
- if (c == '%') {
- if ((c = y1GetChar(y2InputFD)) == '}') return;
- else putc('%', y2ytabcFD );
- }
- putc( c , y2ytabcFD );
- if (c == '\n') ++y1LineNumber;
- c = y1GetChar(y2InputFD);
- }
- y1Error( "y2CpyCode: EOF before %%}" );
- }
-
-
- /************************************************************************/
- /* y2CpyUnion Copy a union declaration to output. */
- /************************************************************************/
- static y2CpyUnion() { /* Called only from y2yyParse */
-
- /**********************************************/
- /* Copy the union declaration to the output. */
- /* Copy also to the .h file if one requested. */
- /**********************************************/
-
- int level, c;
-
- /* Pass input line number to output for debugging purposes: */
- fprintf( y2ytabcFD, "\n# line %d\n", y1LineNumber );
-
- fprintf( y2ytabcFD, "\n#define UNION 1\n");
- fprintf( y2ytabcFD, "typedef union " );
- if (y2DefineFD) fprintf( y2DefineFD, "\ntypedef union " );
-
- level = 0;
- loop {
- if ((c = y1GetChar( y2InputFD )) == EOF) {
- y1Error( "y2CpyUnion: EOF encountered while processing %%union" );
- }
- putc( c, y2ytabcFD );
- if (y2DefineFD) putc( c, y2DefineFD );
-
- switch (c) {
- case '\n': ++y1LineNumber; break;
- case '{': ++level; break;
- case '}':
- if (!--level) {
-
- /* We are finished copying: */
- fprintf( y2ytabcFD, " YYSTYPE;\n" );
- if (y2DefineFD) {
- fprintf(
- y2DefineFD,
- " YYSTYPE;\nextern YYSTYPE yylval;\n"
- );
- }
- return;
- }
- }
- }
- }
-
-
- /************************************************************************/
- /* y2Define Define s to be a terminal or nonterminal. */
- /************************************************************************/
- y2Define( t, s ) /* Called by y2FindName and y2Initialize */
- int t;
- register char *s;
- {
- /*****************************************************/
- /* Define s to be a terminal if t=TYPEtERMINAL */
- /* or a nonterminal if t=TYPEnONTERMINAL */
- /* or a (???--CrT) t=TYPEpREC */
- /*****************************************************/
-
- register val;
-
- if (t != TYPEtERMINAL) {
- if (++y2LastNonterminal >= MAXnONTERMINALsTATES) {
- y1Error(
- "y2Define Too many nonterminals, limit %d",
- MAXnONTERMINALsTATES
- );
- }
- y2NonterminalState[ y2LastNonterminal ].name = y2EnterSymbol(s);
-
- return( FIRSTnONTERMINAL + y2LastNonterminal );
- }
-
- /* Must be a terminal */
- if (++y2NextTerminal >= MAXtERMINALsTATES) {
- y1Error( "y2Define: Too many terminals, limit %d",MAXtERMINALsTATES);
- }
- y2Terminal[ y2NextTerminal ].name = y2EnterSymbol(s);
-
- /* Establish value for token: */
-
- if (s[0] == ' ' && s[2] == '\0') {
-
- /* Single character literal: */
- val = s[1];
-
- } else if (s[0] != ' ' || s[1] != '\\') {
-
- val = y2NextTerminalNumber++;
-
- } else {
-
- /* Escape sequence: */
- if (s[3] == '\0' ) {
-
- /* Single character escape sequence: */
- switch ( s[2] ) {
- /* Character which is escaped: */
- case 'n': val = '\n'; break;
- case 'r': val = '\r'; break;
- case 'b': val = '\b'; break;
- case 't': val = '\t'; break;
- case 'f': val = '\f'; break;
- case '\'': val = '\''; break;
- case '"': val = '"'; break;
- case '\\': val = '\\'; break;
- default:
- y1Error( "y2Define: Invalid escape" );
- }
-
- } else if (s[2] <= '7' && s[2] >= '0') {
-
- /* \nnn sequence: */
- if (
- s[3] < '0'
- ||
- s[3] > '7'
- ||
- s[4] < '0'
- ||
- s[4] > '7'
- ||
- s[5] != '\0'
- ) {
- y1Error( "y2Define Illegal \\nnn construction" );
- }
-
- /****************************************************************/
- /* CrT: Naive code to translate \nnn to octal char is: */
- /* val = 64 * (s[2]-'0') + 8 * (s[3]-'0') + (s[4]-'0'); */
- /* Factoring the '0's out for speed (?!?!!??) gives SCJ's: */
- /****************************************************************/
- val = 64 * s[2] + 8 * s[3] + s[4] - 73 * '0';
- if (val == 0) y1Error( "y2Define: '\\000' is illegal" );
- }
- }
- y2Terminal[ y2NextTerminal ].value = val;
- y2TerminalProperties[ y2NextTerminal ] = 0;
-
- return y2NextTerminal;
- }
-
-
- /************************************************************************/
- /* y2EnterSymbol Store id or literal in y2Text[], return address.*/
- /************************************************************************/
- static char *y2EnterSymbol( s ) /* Called by y2Define and y2GetToken */
- register char *s;
- {
- char *temp;
-
- temp = y2TextFree;
- do {
- if (y2TextFree >= &y2Text[ MAXy2TEXT ]) {
-
- y1Error( "y2EnterSymbol: Too many chars in id's and literals" );
-
- } else {
-
- *y2TextFree++ = *s;
-
- }
- } while (*s++);
-
- return temp;
- }
-
-
- /************************************************************************/
- /* y2FindName */
- /************************************************************************/
- static y2FindName( t, s ) /* Called only from y2yyParse */
- int t; /* TYPEtERMINAL, TYPEnONTERMINAL or TYPEpREC. */
- register char *s;
- {
- int i;
-
- /* Handle literals: */
- if (s[0] == ' ') t = TYPEtERMINAL;
-
- /* May be a terminal: */
- FORaLLtERMINALS(i) {
- if (!strcmp( s, y2Terminal[i].name )) return i;
- }
-
- /* May be a nonterminal: */
- FORaLLnONTERMINALS(i) {
- if (!strcmp( s, y2NonterminalState[i].name )) {
- return i+FIRSTnONTERMINAL;
- }
- }
-
- /* Identifiers in "%prec id" statements should be predeclared: */
- if (t == TYPEpREC) {
- y1Error( "y2FindName: %s should have been defined earlier", s );
- }
-
- /* Create an entry for undefined name: */
- return y2Define( t, s );
- }
-
-
- /************************************************************************/
- /* y2GetToken */
- /************************************************************************/
- static y2GetToken() { /* Called from y2yyParse, y2CpyAction */
-
- static int peekline;
-
- register len;
- register base;
- register c;
-
- int match;
- int percentCommand;
- int i;
-
- start:
- percentCommand = FALSE;
- y1LineNumber += peekline;
- peekline = 0;
- c = y1GetChar( y2InputFD );
-
- /* Skip any leading whitespace: */
- while (
- c == ' '
- ||
- c == '\n'
- ||
- c == '\t'
- ||
- c == '\f'
- ||
- c == '\r'
- ) {
- if (c == '\n') ++y1LineNumber;
- c = y1GetChar( y2InputFD );
- }
-
- /* Skip comments: */
- if (c == '/') {
- /* Skip comment: */
- y1LineNumber += y2SkipComment();
- goto start;
- }
-
- /* We have nonwhitespace noncomment: decide what kind of token: */
- switch (c) {
-
- case EOF:
- /* EOF: */
- return ENDFILE;
-
- case '{':
- /* Action: */
- y1UngetChar( c, y2InputFD );
- return( '=' );
-
- case '<':
- /* Get, and look up, a type name (union member name): */
- len = 0;
- while (
- (c = y1GetChar( y2InputFD )) != '>'
- &&
- c >= 0
- &&
- c != '\n'
- ) {
- y2InputTokenText[ i ] = c;
-
- /* Truncate too-long type names: */
- if (++len >= NAMEsIZE) --len;
- }
-
- /* Check for '>' missing: */
- if (c != '>') y1Error( "y2GetToken: Unterminated < ... > clause" );
-
- /* Tie off name: */
- y2InputTokenText[ len ] = '\0';
-
- /* If typename already entered, don't enter it again: */
- for (i = 1; i <= y2NumberOfTypesDefined; ++i) {
- if (!strcmp( y2TypeName[i], y2InputTokenText )) {
- y2InputNumberValue = i;
- return( TYPENAME );
- }
- }
-
- /* Enter typename: */
- y2TypeName[ y2InputNumberValue = ++y2NumberOfTypesDefined ] = (
- y2EnterSymbol( y2InputTokenText )
- );
-
- return TYPENAME;
-
- case '"':
- case '\'':
- match = c;
- y2InputTokenText[0] = ' ';
- len = 1;
- loop {
-
- c = y1GetChar( y2InputFD );
-
- if (c == '\n' || c == EOF) {
- y1Error( "y2GetToken: Illegal or missing ' or \"" );
- }
- if (c == '\\') {
-
- c = y1GetChar( y2InputFD );
- y2InputTokenText[i] = '\\';
- if( ++len >= NAMEsIZE ) --len;
-
- } else if( c == match ) {
-
- break;
-
- }
- y2InputTokenText[len] = c;
- if (++len >= NAMEsIZE ) --len;
- }
- break;
-
- case '%':
- case '\\':
-
- switch (c = y1GetChar( y2InputFD )) {
-
- case '%':
- case '\\': return MARK ;
- case '0': return TERMINAL;
- case '<': return LEFT ;
- case '2': return BINARY ;
- case '>': return RIGHT ;
- case '=': return PREC ;
- case '{': return LCURLY ;
- default:
- percentCommand = TRUE;
- }
-
- default:
-
- if (isdigit( c )) {
-
- /* Number: */
- y2InputNumberValue = c - '0';
- base = (c == '0') ? 8 : 10;
-
- for (
- c = y1GetChar( y2InputFD );
- isdigit( c );
- c = y1GetChar( y2InputFD )
- ) {
- y2InputNumberValue = y2InputNumberValue * base + (c - '0');
- }
- y1UngetChar( c, y2InputFD );
- return NUMBER;
-
- } else if (
-
- !islower( c )
- &&
- !isupper( c )
- &&
- c != '_'
- &&
- c != '.'
- &&
- c != '$'
-
- ) {
-
- return c;
-
- } else {
-
- len = 0;
-
- while (
- islower( c )
- ||
- isupper( c )
- ||
- isdigit( c )
- ||
- c == '_'
- ||
- c == '.'
- ||
- c == '$'
- ) {
- if (percentCommand && isupper(c)) {
- c += 'a' - 'A';
- }
- y2InputTokenText[ len ] = c;
- if (++len >= NAMEsIZE) --len;
- c = y1GetChar( y2InputFD );
- }
- }
-
- y1UngetChar( c, y2InputFD );
- }
-
- y2InputTokenText[ len ] = '\0';
-
- if (percentCommand) {
- /* Find a reserved word: */
- if (!strcmp(y2InputTokenText,"term" )) return( TERMINAL );
- if (!strcmp(y2InputTokenText,"token" )) return( TERMINAL );
- if (!strcmp(y2InputTokenText,"left" )) return( LEFT );
- if (!strcmp(y2InputTokenText,"nonassoc")) return( BINARY );
- if (!strcmp(y2InputTokenText,"binary" )) return( BINARY );
- if (!strcmp(y2InputTokenText,"right" )) return( RIGHT );
- if (!strcmp(y2InputTokenText,"prec" )) return( PREC );
- if (!strcmp(y2InputTokenText,"start" )) return( START );
- if (!strcmp(y2InputTokenText,"type" )) return( TYPEDEF );
- if (!strcmp(y2InputTokenText,"union" )) return( UNION );
-
- y1Error(
- "y2GetToken: Invalid escape, or illegal reserved word: %s",
- y2InputTokenText
- );
- }
-
- /* Look ahead to distinguish IDENTIFIER from C_IDENTIFIER: */
-
- c = y1GetChar( y2InputFD );
- while (
- c == ' '
- ||
- c == '\t'
- ||
- c == '\n'
- ||
- c == '\f'
- ||
- c == '/'
- ) {
- if( c == '\n' ) {
- ++peekline;
- } else if( c == '/' ) {
- /* Look for comments: */
- peekline += y2SkipComment();
- }
- c = y1GetChar( y2InputFD );
- }
-
- if (c == ':') return C_IDENTIFIER;
-
- y1UngetChar( c, y2InputFD );
-
- return IDENTIFIER;
- }
-
-
- /************************************************************************/
- /* y2Initialize */
- /************************************************************************/
- y2Initialize( argc, argv ) /* Called once from main at startup */
- int argc;
- char *argv[];
- {
- char filename[ FNAMESIZE ];
- char inputFilename[ FNAMESIZE ];
- char *cp;
- int i;
- int makeHFile;
- int makeIFile;
-
- makeHFile = FALSE;
- makeIFile = FALSE;
-
- y2OutputFD = NULL;
- y2DefineFD = NULL;
-
- /* Handle all commandline switches: */
- for (i = 1; --argc && argv[i][0] == '-'; i++) {
-
- while (*++(argv[i])) {
- switch( toupper( *argv[i] )) {
- case 'I': makeIFile++; continue;
- case 'H': makeHFile++; continue;
- default:
- fprintf(stderr, "y2Initialize: Bad option: %c\n", *argv[i]);
- y2Usage();
- }
- }
- }
-
- /* Catch no filename given: */
- if (!argc) y2Usage();
-
- /************************************************************************/
- /* Now open the input file with a default extension of ".Y", */
- /* then replace the period in argv[1] with a null, so argv[1] */
- /* can be used to form the table, defs and info filenames. */
- /************************************************************************/
-
- /* Find the input filename: */
- cp = argv[i];
-
- /* Scan past '.' or to null: */
- while (*cp++ != '.' && *cp);
-
- /* Make our own copy: */
- strcpy( filename, argv[i] );
-
- /* Make sure "filename" copy has ".Y" extention */
- /* and , argv[] copy has no extention: */
- if (!*cp) strcat( filename, ".Y" ); /* Add default ".y" */
- else *(argv[i]-1) = '\0'; /* Null the period: */
-
- /* Open the xxx.y input file: */
- strcpy( inputFilename, filename );
- if ((y2InputFD = fopen( filename, "r" )) == NULL) {
- y1Error( "y2Initialize: Cannot open input file \"%s\"", filename );
- }
-
- /* If -h option specified, create a xxx.h file to #define the tokens: */
- if (makeHFile) {
- strcpy( filename, argv[i] );
- strcat( filename, ".H" );
-
- if ((y2DefineFD = fopen( filename, "w" )) == NULL) {
- y1Error( "y2Initialize: Cannot open defs file\"%s\"", filename);
- }
- }
-
- /* If -i option specified, create a xxx.i file to hold the */
- /* human-readable description of the parser: */
- if (makeIFile) {
- strcpy( filename, argv[i] );
- strcat( filename, ".I" );
-
- if ((y2OutputFD = fopen( filename, "w" )) == NULL) {
- y1Error( "y2Initialize: Cannot open info file\"%s\"", filename);
- }
- }
-
- /* Create the xxx.c file containing the parser proper: */
- strcpy( filename, argv[i] );
- strcat( filename, ".C" );
-
- if ((y2ytabcFD = fopen(filename, "w")) == NULL) {
- y1Error( "y2Initialize: Cannot open table file\"%s\"", filename);
- }
-
- /* Open a temporary(?) file for gotos: */
- if ((y2TempFileFD = fopen( TEMPNAME, "w" )) == NULL) {
- y1Error( "y2Initialize: Cannot open temp file" );
- }
-
- /* Open a file to copy the user-supplied rule-action code into. */
- /* (We add calling machinery as we go along.) */
- if ((y2ActionFD = fopen( ACTNAME, "w" )) == NULL) {
- y1Error( "y2Initialize: Cannot open action file" );
- }
-
- /* Put out a header line at the beginning of the 'table' file: */
- /* CrT: What is "CSD"? Capricious Software Demolition :-) ? */
- fprintf(
- y2ytabcFD,
- "\n/* Created by CSD_YACC (IBM PC) from \"%s\" */\n",
- inputFilename
- );
-
- /* Complete the initialization: */
-
- y2TextFree = y2Text;
-
- /* End token is 0: */
- y2Define( 0,"$end" );
-
- /* Other noncharacter terminal tokens start at 257: */
- y2NextTerminalNumber = 0400;
-
- /* Define remaining special tokens: */
- y2Define( 0, "error" );
- y2Define( 1, "$accept" );
-
- /* y2Pool is empty: */
- y2FreePool = y2Pool;
- }
-
-
- /************************************************************************/
- /* y2SkipComment Skip over comments. */
- /************************************************************************/
- static y2SkipComment() { /* Called only from y2GetToken */
-
- register c;
- register linesSkipped;
-
- linesSkipped =0;
-
- /* y2SkipComment is called after reading a '/': */
-
- if (y1GetChar( y2InputFD ) != '*') {
- y1Error( "y2SkipComment: Illegal comment" );
- }
-
- for (c = y1GetChar( y2InputFD ); c != EOF; c = y1GetChar( y2InputFD )){
-
- while (c == '*') {
-
- if ((c = y1GetChar( y2InputFD )) == '/') return linesSkipped;
- }
- if (c == '\n') ++linesSkipped;
- }
-
- y1Error( "y2SkipComment: EOF inside comment" );
-
- /* NOTREACHED */
- }
-
-
- /************************************************************************/
- /* y2TypeOf Determine the type of a symbol. */
- /************************************************************************/
- static y2TypeOf( t ) /* Called only by y2CpyAction */
- int t;
- {
- register v;
-
- if (t >= FIRSTnONTERMINAL) {
- v = y2NonterminalState[ t - FIRSTnONTERMINAL ].tvalue;
- } else {
- v = TYPE( y2TerminalProperties[ t ] );
- }
-
- if (v <= 0) {
- y1Error(
- "y2TypeOf: Must specify type for %s",
- (
- (t >= FIRSTnONTERMINAL)
- ?
- y2NonterminalState[ t-FIRSTnONTERMINAL ].name
- :
- y2Terminal[ t ].name
- )
- );
- }
- return v;
- }
-
-
- /************************************************************************/
- /* y2Usage */
- /************************************************************************/
- static y2Usage() { /* Called only by y2Initialize */
-
- fprintf( stderr, "\nCDS_YACC:\n" );
- fprintf( stderr, " yacc -hi infile\n\n" );
- fprintf( stderr, "Switches:\n" );
- fprintf( stderr, " -h Create definitions header file\n" );
- fprintf( stderr, " -i Create parser description file\n\n" );
- fprintf( stderr, "Default input file extension is \".Y\"\n" );
- fprintf( stderr, "Defs file same name, \".H\" extension.\n" );
- fprintf( stderr, "Info file same name, \".I\" extension.\n" );
-
- exit(EX_ERR);
- }
-
-
- /************************************************************************/
- /* y2WriteDefines Post declarations: write out the defines */
- /************************************************************************/
- static y2WriteDefines() { /* Called only by y2yyParse */
-
- /********************************************************************/
- /* Write out the defines. We do this at the end of the declaration */
- /* section. If a %{ ... %} section is encountered we write all */
- /* pending declarations out to give the C code access to them. */
- /* Thus, we may not be writing ALL existing declarations this call: */
- /********************************************************************/
-
- register int i, c;
- register char *cp;
-
- /* For all declarations not yet written out: */
- for (i = y2NumberOfDefinedSymbolsWritten; i <= y2NextTerminal; ++i) {
-
- cp = y2Terminal[i].name;
- if (*cp == ' ') ++cp; /* Literals. */
-
- /* Ignore defined strings with special characters in them: */
- for ( ; c = *cp; ++cp) {
- if (!islower(c) && !isupper(c) && !isdigit(c) && c != '_') {
- goto nodef;
- }
- }
-
- /* Write out the #define: */
- fprintf(
- y2ytabcFD,
- "# define %s %d\n",
- y2Terminal[i].name,
- y2Terminal[i].value
- );
-
-
- /* If a .h file was requested, write to it also: */
- if (y2DefineFD != NULL) {
- fprintf(
- y2DefineFD,
- "# define %s %d\n",
- y2Terminal[i].name,
- y2Terminal[i].value
- );
- }
- nodef: ;
- }
- y2NumberOfDefinedSymbolsWritten = y2NextTerminal+1;
- }
-
-
- /************************************************************************/
- /* y2yyParse Kludged YACC input parser. */
- /************************************************************************/
- y2yyParse() { /* Called only from main. */
-
- int token;
- int j;
- int c;
- int *p;
- char actionName[8];
- int typeOfEmpty;
-
- int associativity = 0;
- int type = 0;
- int precedence = 0;
-
- /* "Sorry -- no yacc parser here..... we must bootstrap somehow..." */
-
- /* Handle the declaration section ended by a %% MARKer: */
- for (token = y2GetToken(); token != MARK && token != ENDFILE; ) {
-
- switch (token) {
-
- case LCURLY:
- /* Copy some literal C code across. Give it definitions to date: */
- y2WriteDefines();
- y2CpyCode();
- token = y2GetToken();
- continue;
-
- case UNION:
- /* Copy the union declaration to the output: */
- y2CpyUnion();
- token = y2GetToken();
- continue;
-
- case ';':
- token = y2GetToken();
- break;
-
- case START:
- /* Handle a %start declaration: */
- if ((token = y2GetToken()) != IDENTIFIER) {
- y1Error( "y2yyParse: Bad %%start construction" );
- }
- y2RootNonterminal = (
- y2FindName( TYPEnONTERMINAL, y2InputTokenText )
- );
- token = y2GetToken();
- continue;
-
- case TYPEDEF:
- /* Handle a %token declaration: */
- if ((token = y2GetToken()) != TYPENAME) {
- y1Error( "y2yyParse: Bad syntax in %%type" );
- }
- type = y2InputNumberValue;
-
- /* Handle IDENTIFIER string following the %token: */
- loop {
-
- switch (token = y2GetToken()) {
-
- case ',': continue;
- case ';': token = y2GetToken(); break;
-
- case IDENTIFIER:
-
- /* Look up token, creating new entry if necessary: */
- token = y2FindName( TYPEnONTERMINAL, y2InputTokenText );
-
- /* Handle terminals and nonterminals separately: */
- if (token < FIRSTnONTERMINAL) {
-
- /* Terminal: */
-
- /* See what it is declared as: */
- j = TYPE( y2TerminalProperties[ token ] );
-
- /* OK if no type yet or same type: */
- if (j == 0 || j == type) {
-
- SETtYPEtO( y2TerminalProperties[token], type );
-
- } else {
- y1Error(
- "y2yyParse: Type redeclaration of token %s",
- y2Terminal[token].name
- );
- }
-
- } else {
-
- /* Nonterminal: */
-
- /* See what it is was previously declared as: */
- j = y2NonterminalState[
- token - FIRSTnONTERMINAL
- ].tvalue;
-
- /* No type or matching type ok: */
- if (j == 0 || j == type) {
-
- y2NonterminalState[
- token - FIRSTnONTERMINAL
- ].tvalue = type;
-
- } else {
- y1Error(
- "y2yyParse: Redeclaration of nonterminal %s",
- y2NonterminalState[
- token - FIRSTnONTERMINAL
- ].name
- );
- }
- }
- continue;
-
- default:
- break;
- }
- break;
- }
- continue;
-
- case LEFT:
- case BINARY:
- case RIGHT: ++precedence; /* Fall into TERMINAL: */
-
- case TERMINAL:
- /* Nonzero means new precedence and associativity: */
- associativity = token - TERMINAL;
- type = 0;
-
- /* Get identifiers so defined: */
-
- token = y2GetToken();
-
- if (token == TYPENAME) {
-
- /* There is a type defined: */
- type = y2InputNumberValue;
- token = y2GetToken();
- }
-
- loop {
-
- switch (token) {
-
- case ',': token = y2GetToken(); continue;
- case ';': break;
-
- case IDENTIFIER:
- j = y2FindName( TYPEtERMINAL, y2InputTokenText );
-
- if (associativity) {
-
- if (ASSOCIATIVITY( y2TerminalProperties[j] )) {
- y1Error(
- "y2yyParse: Redeclaration of precedence of %s",
- y2InputTokenText
- );
- }
- SETaSSOCIATIVITYtO( y2TerminalProperties[j], associativity);
- SETpRECEDENCElEVELtO( y2TerminalProperties[j], precedence);
- }
-
- if (type) {
- if (TYPE( y2TerminalProperties[j] )) {
- y1Error(
- "y2yyParse: Redeclaration of type of %s",
- y2InputTokenText
- );
- }
- SETtYPEtO( y2TerminalProperties[j], type );
- }
-
- if ((token = y2GetToken()) == NUMBER) {
- y2Terminal[j].value = y2InputNumberValue;
- if (j < y2NumberOfDefinedSymbolsWritten && j > 2) {
- y1Error(
- "y2yyParse: Must define type # of %s earlier",
- y2Terminal[j].name
- );
- }
- token = y2GetToken();
- }
- continue;
- }
- break;
- }
- continue;
-
- default:
- printf( "y2yyParse: Unrecognized character: %o\n", token);
- y1Error( "y2yyParse: Syntax error" );
- }
- }
-
-
-
- /******************************/
- /* End of declaration section */
- /******************************/
-
- if (token == ENDFILE) y1Error( "y2yyParse: Unexpected EOF before %%" );
-
- /* Token is MARK (%%), wrap up declaration section stuff: */
-
- y2WriteDefines();
-
- fprintf( y2ytabcFD,"#define yyclearin yychar = -1\n" );
- fprintf( y2ytabcFD,"#define yyerrok yyerrflag = 0\n" );
- #ifdef XYZZY
- fprintf( y2ytabcFD,"extern int yychar;\nextern short yyerrflag;\n" );
- #endif
- fprintf(
- y2ytabcFD,
- "#ifndef YYMAXDEPTH\n#define YYMAXDEPTH 150\n#endif\n"
- );
- if (!y2NumberOfTypesDefined) {
- fprintf(
- y2ytabcFD,
- "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n"
- );
- }
-
- #ifdef unix
- fprintf( y2ytabcFD, "YYSTYPE yylval, yyval;\n" );
- #else
- fprintf( y2ytabcFD, "extern YYSTYPE yylval; /*CSD & DECUS LEX */\n");
- fprintf( y2ytabcFD, "YYSTYPE yyval; /*CSD & DECUS LEX */\n");
- #endif
-
- /* Set up to start parsing the rules ("productions"): */
- y2Production[ 0 ] = y2FreePool;
-
- /* If no %start declaration is made, the first nonterminal is used: */
-
- *y2FreePool++ = FIRSTnONTERMINAL;
- *y2FreePool++ = y2RootNonterminal;
- *y2FreePool++ = 1;
- *y2FreePool++ = 0;
-
- y2Production[1] = y2FreePool;
-
- /* Copy any %{...%} code between the %% and the first rule: */
- while ((token = y2GetToken()) == LCURLY) y2CpyCode();
-
- if (token != C_IDENTIFIER) {
- y1Error( "y2yyParse: Bad syntax on first rule" );
- }
- if (!y2RootNonterminal) {
- y2Production[0][1] = y2FindName(TYPEnONTERMINAL,y2InputTokenText);
- }
-
- /* Now read all rules in the grammar: */
- while (token != MARK && token != ENDFILE) {
-
- /* Process a rule: */
-
- if (token == '|' ) {
-
- /* Copy over LHS of previous production: */
- *y2FreePool++ = *y2Production[ y2ThisProduction-1 ];
-
- } else if (token == C_IDENTIFIER) {
-
- /* Copy internal ID# for LHS nonterminal to first slot in rule: */
- *y2FreePool = y2FindName( TYPEnONTERMINAL, y2InputTokenText );
- if (*y2FreePool < FIRSTnONTERMINAL) {
- y1Error( "y2yyParse: Terminal illegal on LHS of grammar rule" );
- }
- ++y2FreePool;
-
- } else {
-
- y1Error( "y2yyParse: Illegal rule: missing semicolon or | ?" );
-
- }
-
- /* Read rule body: */
- token = y2GetToken();
-
- more_rule:
- while (token == IDENTIFIER) {
-
- *y2FreePool = y2FindName( TYPEnONTERMINAL, y2InputTokenText );
-
- /* Grammar rules inherit the associativity and */
- /* precedence of any embedded terminals: */
- if (*y2FreePool < FIRSTnONTERMINAL) {
- y2ProductionProperties[ y2ThisProduction ] = (
- y2TerminalProperties[ *y2FreePool ]
- );
- }
-
- ++y2FreePool;
- token = y2GetToken();
- }
-
- /* Handle "%prec" commands: */
- if (token == PREC) {
- if (y2GetToken() != IDENTIFIER) {
- y1Error( "y2yyParse: Illegal %%prec syntax" );
- }
-
- /* Look up terminal specified in %prec: */
- j = y2FindName( TYPEpREC, y2InputTokenText );
-
- /* Make sure it is not a nonterminal: */
- if (j >= FIRSTnONTERMINAL) {
- y1Error(
- "y2yyParse: Nonterminal %s illegal after %%prec",
- y2NonterminalState[ j-FIRSTnONTERMINAL ].name
- );
- }
-
- /* Let current rule inherit specified precedence: */
- y2ProductionProperties[ y2ThisProduction ] = (
- y2TerminalProperties[ j ]
- );
- token = y2GetToken();
- }
-
- /* Handle actions: */
- if (token == '=') {
- int RHSItems;
-
- /* Remember that this rule has an action: */
- y2ProductionProperties[ y2ThisProduction ] |= RULEhASaCTION;
-
- /* Figure number of items seen so far on right-hand side */
- /* of grammar rule (for check $n args in actions): */
- RHSItems = y2FreePool - y2Production[ y2ThisProduction ] -1;
-
- /* Copy action code to output, handling $ variables: */
- y2CpyAction( RHSItems );
-
- /* Check for more rule after the action: */
- if ((token = y2GetToken()) == IDENTIFIER) {
-
- /* Action within rule. Split it into two rules: */
- sprintf( actionName, "$$%d", y2ThisProduction );
-
- /* Create a nonterminal: */
- j = y2FindName(TYPEnONTERMINAL,actionName);
-
-
- /*******************************************************/
- /* The current rule will become rule number */
- /* y2ThisProduction+1. Move the contents down, and */
- /* make room for the null: */
- /*******************************************************/
-
- for (
- p = y2FreePool;
- p >= y2Production[ y2ThisProduction ];
- p--
- ) {
- p[2] = *p;
- }
- y2FreePool += 2;
-
- /* Enter null production for action: */
- p = y2Production[ y2ThisProduction ];
- *p++ = j;
- *p++ = -y2ThisProduction;
-
- /* Update the production information: */
-
- /* Current rule does NOT have an action after all: */
- y2ProductionProperties[ y2ThisProduction+1 ] = (
- y2ProductionProperties[ y2ThisProduction ] & ~RULEhASaCTION
- );
-
- /* But added null production DOES have an action: */
- y2ProductionProperties[ y2ThisProduction ] = RULEhASaCTION;
-
- /* Check for too productions: */
- if (++y2ThisProduction >= MAXpRODUCTIONS) {
- y1Error( "y2yyParse: More than %d rules", MAXpRODUCTIONS );
- }
- y2Production[ y2ThisProduction ] = p;
-
- /* Make the action appear in the original rule: */
- *y2FreePool++ = j;
-
- /* Get some more of the rule: */
- goto more_rule;
- }
- }
-
- /* Handle end of rule: */
- while (token == ';') token = y2GetToken();
-
- *y2FreePool++ = -y2ThisProduction;
-
- /* Check that default action is reasonable: */
-
- if (
- y2NumberOfTypesDefined
- &&
- !(y2ProductionProperties[ y2ThisProduction ] & RULEhASaCTION)
- &&
- y2NonterminalState[ * /* DeSmet C bug pins the '*' to this line */
- y2Production[ y2ThisProduction ]
- -
- FIRSTnONTERMINAL
- ].tvalue
- ) {
- /* No explicit action, LHS has value: */
- typeOfEmpty = y2Production[ y2ThisProduction ][ 1 ];
-
- if (typeOfEmpty < 0) {
-
- y1Error("y2yyParse: Must return value, since LHS has a type");
-
- } else if (typeOfEmpty >= FIRSTnONTERMINAL ) {
-
- typeOfEmpty = (
- y2NonterminalState[ typeOfEmpty-FIRSTnONTERMINAL ].tvalue
- );
- } else {
-
- typeOfEmpty = TYPE( y2TerminalProperties[typeOfEmpty] );
- }
-
- if (
- typeOfEmpty
- !=
- y2NonterminalState[ * /* DeSmet C bug keeps '*' from moving */
- y2Production[ y2ThisProduction ]
- -
- FIRSTnONTERMINAL
- ].tvalue
- ) {
- y1Error("y2yyParse: Default action has potential type clash");
- }
- }
-
- /* Check for too many productions: */
- if (++y2ThisProduction >= MAXpRODUCTIONS) {
- y1Error( "y2yyParse: more than %d rules", MAXpRODUCTIONS );
- }
-
- y2Production[ y2ThisProduction ] = y2FreePool;
- y2ProductionProperties[ y2ThisProduction ] = 0;
- }
-
-
- /*********************/
- /* End of all rules: */
- /*********************/
-
- /* Properly terminate the last line: */
- fprintf(y2ActionFD, "/* End of actions. */");
- fclose( y2ActionFD );
- fprintf( y2ytabcFD, "# define YYERRCODE %d\n", y2Terminal[2].value );
-
- /* Copy anything remaining to the output code file: */
- if (token == MARK) {
- fprintf( y2ytabcFD, "\n#line %d\n", y1LineNumber );
-
- while ((c = y1GetChar( y2InputFD )) != EOF) putc( c, y2ytabcFD );
- }
- fclose( y2InputFD );
-
- /* All finished with input! Now return and start analysing grammar: */
- }
-
-
-