genc.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 487 行 · 第 1/2 页

C
487
字号
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
#include "yacc.h"
#include "alloc.h"

extern FILE *actout;

extern char *loadpath;

extern a_sym **symtab, *symlist, *startsym, *eofsym, *errsym, *goalsym, *nosym;
extern a_pro **protab;

extern a_state **statetab, *statelist, **statetail, *startstate, *errstate;

extern unsigned wperset;
extern short *setmembers;

static void putnum( char *name, int i )
{
    fprintf( actout, "#define\t%-20s\t%d\n", name, i );
}

static void preamble()
{
    int         i;

    putnum( "SHIFT", -1 );
    putnum( "ERROR", -2 );
    fprintf( actout, "\n"
                     "#ifndef YYSTYPE\n"
                     "    #define YYSTYPE int\n"
                     "#endif\n"
                     "\n"
                     "typedef struct parse_stack {\n"
                     "    int (YYNEAR *state) (struct parse_stack *, unsigned );\n"
                     "    YYSTYPE v;\n"
                     "} parse_stack;\n\n"
                     "\n"
                     );

    for( i = 0; i < nstate; ++ i ) {
        fprintf( actout,
                 "static int YYNEAR state%d( struct parse_stack *, unsigned );\n", i );
    }
}

static void prolog( int i )
{
    a_name              name;
    a_state *           x;

    fprintf( actout, "\nint YYNEAR state%d( parse_stack * yysp, unsigned token )\n/*\n", i );
    x = statetab[i];
    for( name.item = x->name.item; *name.item; ++name.item ) {
        showitem( actout, *name.item, " ." );
    }
    fprintf( actout, "*/\n{\n" );
}

static void copyact( a_pro * pro, char * indent )
{
    char        *s;
    char        *type;
    int         i;
    a_sym *     lhs;
    an_item *   rhs;
    unsigned    n;
    int         only_default_type;

    if( pro->action == NULL ) return;   // Default action is noop
    lhs = pro->sym;
    rhs = pro->item;
    fprintf( actout, "%s/* %s <-", indent, lhs->name );
    for( n = 0; rhs[n].p.sym != NULL; ++ n ) {
        fprintf( actout, " %s", rhs[n].p.sym->name );
    }
    fprintf( actout, " */\n%s{ YYSTYPE yyval;\n%s\t", indent, indent );
    only_default_type = TRUE;
    for( s = pro->action; *s != '\0'; ){
        if( *s == '$' ){
            if( *++s == '<' ){
                for( type = ++s; *s != '>'; ++s ) {
                    if( *s == '\0' ) {
                        msg( "Bad type specifier.\n" );
                    }
                }
                *s++ = '\0';
                only_default_type = FALSE;
            } else {
                type = NULL;
            }
            if( *s == '$' ){
                fprintf( actout, "yyval", *s );
                if( !type ) {
                    type = lhs->type;
                }
                ++s;
            } else {
                if( *s == '-' || isdigit( *s ) ) {
                    i = strtol( s, &s, 10 );
                }
                if( i >= 0 && i > n ) {
                    msg( "Invalid $ parameter.\n" );
                }
                fprintf( actout, "yysp[%d].v", i - 1 ); // Adjust yysp first
                if( !type && i >= 1 ) {
                    type = rhs[i - 1].p.sym->type;
                }
            }
            if( type ) {
                fprintf( actout, ".%s", type );
            }
        } else if( *s == '\n' ) {
            fprintf( actout, "\n\t%s", indent );
            ++s;
        } else {
            fputc( *s++, actout );
        }
    }
    type = lhs->type;
    if( only_default_type && (type = lhs->type) != NULL ) {
        fprintf( actout, "\n\t%syysp[0].v.%s = yyval.%s;", indent, type, type );
    } else {
        fprintf( actout, "\n\t%syysp[0].v = yyval;", indent );
    }
    fprintf( actout, "\n%s};\n", indent );
}

static a_state * unique_shift( a_pro * reduced )
{
    // See if there is a unique shift when this state is reduced

    a_state *           shift_to;
    a_state *           test;
    a_shift_action *    tx;
    int                 i;

    shift_to = NULL;
    for( i = 0; i < nstate; ++ i ) {
        test = statetab[i];
        for( tx = test->trans; tx->sym; ++tx ) {
            if( tx->sym == reduced->sym ) {
                // Found something that uses this lhs
                if( shift_to == NULL || shift_to == tx->state ) {
                    // This is the first one or it matches the first one
                    shift_to = tx->state;
                } else {
                    return( NULL );     // Not unique
                }
            }
        }
    }
    return( shift_to );
}

static void reduce( int production, int error )
{
    int                 plen;
    an_item *           item;
    a_pro *             pro;
    a_state *           shift_to;

    if( production == error ) {
        fprintf( actout, "\treturn( ERROR );\n" );
    } else {
        production -= nstate;           // Convert to 0 base
        pro = protab[ production ];
        for( item = pro->item, plen = 0; item->p.sym; ++item ) {
            ++plen;
        }
        if( plen != 0 ) {
            fprintf( actout, "\tyysp -= %d;\n", plen );
        }
        copyact( pro, "\t" );
        // fprintf( actout, "\tactions( %d, yysp );\n", production );
        if( (shift_to = unique_shift( pro )) != NULL ) {
            fprintf( actout, "\tyysp[0].state = state%d;\n", shift_to->sidx );
        } else {
            fprintf( actout, "\t(*yysp[-1].state) ( yysp, %d );\n",
                                    pro->sym->token );
        }
        fprintf( actout, "\treturn( %d );\n", plen );
    }
}

static void gencode( int statenum, short *toklist, short *s, short *action,
                        short default_token, short parent_token, short error )
{
    short               default_action;
    short               todo;
    short               token;
    int                 symnum;
    int                 switched;

    prolog( statenum );
    default_action = 0;
    switched = FALSE;
    for( ; toklist < s; ++ toklist ) {
        token = *toklist;
        todo = action[ token ] ;
        if( token == default_token ) {
            default_action = todo;
        } else if( token != parent_token ) {
            if( ! switched ) {
                fprintf( actout, "    switch( token ) {\n" );
                switched = TRUE;
            }

            for( symnum = 0; symnum < nsym; ++ symnum ) {
                if( symtab[symnum]->token == token ) break;

⌨️ 快捷键说明

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