yacc.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 287 行

C
287
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Watcom's implementation of the classic YACC tool.
*
****************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "yacc.h"
#include "walloca.h"

FILE *yaccin, *actout, *tokout;
char *loadpath, *srcname;

char lineflag;
char bigflag;
char fastflag;
char denseflag;
char default_shiftflag;
char compactflag;
char eliminateunitflag;
char showflag;
char translateflag;
char defaultwarnflag = 1;

index_t RR_conflicts;
index_t SR_conflicts;
index_t nstate_1_reduce;

static FILE *openr(), *openw();
static void setoptions( char *p );

static int warnings;
static int proflag;

int main( int argc, char **argv )
{
    unsigned i;
    FILE *skeleton, *temp, *save;
    int ch;

    for( i = 1; i < argc; ++i ) {
        if( argv[i][0] != '-' ) break;
        setoptions( &argv[i][1] );
    }
    if( i != argc - 1 && i != argc - 2 ) {
        puts( "usage: yacc [-bcdflpsuw] <grammar> [<driver>]\n" );
        puts( "options:" );
        puts( "    -b    output bigger (less optimal) tables" );
        puts( "    -c    output compact tables (slower to execute)" );
        puts( "    -d    use dense tokens (no '+' style tokens allowed)" );
        puts( "    -ds   use 'default shift' optimization" );
        puts( "    -f    output fast tables (larger size)" );
        puts( "    -l    output #line directives" );
        puts( "    -p    dump all productions" );
        puts( "    -s    dump full state tables" );
        puts( "    -t    translate 'keyword' to Y_KEYWORD, '++' to Y_PLUS_PLUS, etc." );
        puts( "    -u    eliminate useless unit production reduction" );
        puts( "    -w    disable default action type checking" );
        exit( 1 );
    }
    skeleton = NULL;
    if( i == argc - 2 ) {
        skeleton = openr( argv[ argc - 1 ] );
        if( !skeleton ) {
            msg( "could not open driver source code '%s'\n", argv[ argc - 1 ] );
        }
    }
    loadpath = argv[0];
    *getname( loadpath ) = '\0';
    srcname = argv[i];
    if( !strrchr( srcname, '.' ) ) {
        srcname = alloca( strlen( argv[i] )+3 );
        srcname = strcat( strcpy( srcname, argv[i] ), ".y" );
    }
    yaccin = openr( srcname );
    actout = openw( "ytab.c" );
    tokout = openw( "ytab.h" );

    defs();
    if( !(temp = tmpfile()) ) {
        msg( "Cannot create temporary file\n" );
    }
    save = actout;
    actout = temp;
    rules();
    actout = save;
    buildpro();
    CalcMinSentence();
    if( proflag || showflag ) {
        showpro();
    }
    lr0();
    lalr1();
    SetupStateTable();
    /* apply state filters */
    FindUnused();
    if( eliminateunitflag ) {
        EliminateUnitReductions();
    }
    if( default_shiftflag ) {
        if( ! keyword_id_low ) {
            msg( "No %%keyword_id <low> <high> specified." );
        } else {
            MarkDefaultShifts();
        }
    }
    MarkNoUnitRuleOptimizationStates();
    RemoveDeadStates();
    MarkDefaultReductions();
    if( showflag ) {
        showstates();
    }
    if( warnings ) {
        if( warnings == 1 ) {
            printf( "%s: 1 warning\n", srcname );
        } else {
            printf( "%s: %d warnings\n", srcname, warnings );
        }
        exit( 1 );
    }
    parsestats();
    dumpstatistic( "parser states", nstate );
    dumpstatistic( "# states (1 reduce only)", nstate_1_reduce );
    dumpstatistic( "reduce/reduce conflicts", RR_conflicts );
    dumpstatistic( "shift/reduce conflicts", SR_conflicts );
    show_unused();
    rewind( tokout );
    while( (ch = fgetc( tokout )) != EOF ) {
        fputc( ch, actout );
    }
    if( !skeleton ) {
        if( !(skeleton = fpopen( loadpath, "yydriver.c" )) ) {
            msg( "Can't find yacc skeleton yydriver.c\n" );
        }
    }
    while( (ch = fgetc( skeleton )) != '\f' && ch != EOF ) {
        fputc( ch, actout );
    }
    genobj();
    while( (ch = fgetc( skeleton )) != '\f' && ch != EOF ) {
        fputc( ch, actout );
    }
    rewind( temp );
    while( (ch = fgetc( temp )) != EOF ) {
        fputc( ch, actout );
    }
    while( (ch = fgetc( skeleton )) != EOF ) {
        fputc( ch, actout );
    }
    tail();
    return( 0 );
}

static FILE *openr( char *filename )
{
    FILE *file;

    if( !(file = fopen( filename, "r" )) ) {
        msg( "Can't open %s.\n", filename );
    }
    return( file );
}

static FILE *openw( char *filename )
{
    FILE *file;

    if( !(file = fopen( filename, "w" )) ) {
        msg( "Can't open %s for output.\n", filename );
    }
    return( file );
}

static void setoptions( char *p )
{
    for( ; *p; ++p ) {
        switch( *p ) {
        case 'b':
            bigflag = 1;
            break;
        case 'c':
            compactflag = 1;
            break;
        case 'd':
            if( p[1] == 's' ) {
                ++p;
                default_shiftflag = 1;
            } else {
                denseflag = 1;
            }
            break;
        case 'f':
            fastflag = 1;
            break;
        case 's':
            showflag = 1;
            break;
        case 'l':
            lineflag = 1;
            break;
        case 'p':
            proflag = 1;
            break;
        case 't':
            translateflag = 1;
            break;
        case 'u':
            eliminateunitflag = 1;
            break;
        case 'w':
            defaultwarnflag = 0;
            break;
        default:
            msg( "Unknown option '%c'\n", *p );
        }
    }
}

void warn( char *fmt, ... )
{
    va_list arg_ptr;

    if( srcname != NULL ) {
        printf( "%s(%d): ", srcname, lineno );
    }
    printf( "Warning! " );
    va_start( arg_ptr, fmt );
    vprintf( fmt, arg_ptr );
    va_end( arg_ptr );
    ++warnings;
}

void msg( char *fmt, ... )
{
    va_list arg_ptr;

    if( srcname != NULL ) {
        printf( "%s(%d): ", srcname, lineno );
    }
    printf( "Error! " );
    va_start( arg_ptr, fmt );
    vprintf( fmt, arg_ptr );
    va_end( arg_ptr );
    exit( 1 );
}

void dumpstatistic( char *name, unsigned stat )
{
    size_t len;

    len = strlen( name );
    printf( "%s:", name );
    while( len < 39 ) {
        putchar( ' ' );
        ++len;
    }
    printf( "%6u\n", stat );
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?