parse.c

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

C
1,148
字号
/****************************************************************************
*
*                            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 <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "alloc.h"
#include "yacc.h"
#if defined( UNIX )
#include "clibext.h"
#endif

static void copycurl( void );
static void copyUniqueActions( void );
static void copyact( int pnum, a_sym *lhs, a_sym **rhs, unsigned base, unsigned n );
static void lineinfo( void );
static int scan( unsigned used );
static void need( char *pat );
static int eatcrud( void );
static int nextc( void );
static int lastc( void );
static void addbuf( int ch );
static char *dupbuf( void );

int lineno = { 1 };

#define BUF_INCR 500
static unsigned bufused, bufmax;
static char *buf = { NULL };

typedef enum {
    IDENTIFIER = 256,   /* includes identifiers and literals */
    C_IDENTIFIER,       /* identifier (but not literal) followed by colon */
    NUMBER,             /* -?[0-9]+ */
    MARK,               /* %% */
    LCURL,              /* %{ */
    RCURL,              /* }% */
    AMBIG,              /* %keywords */
    KEYWORD_ID,
    LEFT,
    RIGHT,
    NONASSOC,
    TOKEN,
    PREC,
    TYPE,
    START,
    UNION,
} a_token;

static int ch = { ' ' };
static int token;
static int value;

typedef struct uniq_case uniq_case;
typedef struct rule_case rule_case;
struct rule_case {
    rule_case           *next;
    int                 pnum;
    a_sym               *lhs;
};
struct uniq_case {
    uniq_case           *next;
    char                *action;
    rule_case           *rules;
};

static unsigned long actionsCombined;
static uniq_case *caseActions;

a_SR_conflict *ambiguousstates;

static a_sym *make_sym( char *name, token_t value )
{
    a_sym *p;

    p = addsym( name );
    p->token = value;
    return( p );
}

static a_SR_conflict *make_unique_ambiguity( a_sym *sym, unsigned index )
{
    a_SR_conflict *am;

    for( am = ambiguousstates; am != NULL; am = am->next ) {
        if( am->id == index ) {
            if( am->sym != sym ) {
                msg( "ambiguity %u deals with %s, not %s.\n",
                     index, am->sym->name, sym->name );
                break;
            }
            return( am );
        }
    }
    am = MALLOC(1,a_SR_conflict);
    am->next = ambiguousstates;
    am->sym = sym;
    am->id = index;
    am->state = NULL;
    am->shift = NULL;
    am->thread = NULL;
    am->reduce = 0;
    ambiguousstates = am;
    return( am );
}

void defs( void )
{
    token_t gentoken;
    a_sym *sym;
    int ctype;
    char *dupbuf(), *type;
    a_prec prec;

    eofsym = make_sym( "$eof", TOKEN_EOF );
    nosym = make_sym( "$impossible", TOKEN_IMPOSSIBLE );
    errsym = make_sym( "error", TOKEN_ERROR );
    if( denseflag ) {
        gentoken = TOKEN_DENSE_BASE;
    } else {
        gentoken = TOKEN_SPARSE_BASE;
    }
    scan( 0 );
    prec.prec = 0;
    for(;;) {
        switch( token ) {
        case MARK:
            scan( 0 );
            return;
        case START:
            if( scan( 0 ) != IDENTIFIER )
                msg( "Identifier needed after %%start.\n" );
            startsym = addsym( buf );
            scan( 0 );
            break;
        case UNION:
            if( scan( 0 ) != '{' ) {
                msg( "Need '{' after %%union.\n" );
            }
            fprintf( actout, "#ifndef __YYSTYPE_DEFINED\n" );
            fprintf( actout, "#define __YYSTYPE_DEFINED\n" );
            fprintf( actout, "typedef union " );
            lineinfo();
            fprintf( actout, "%s YYSTYPE;\n", buf );
            fprintf( actout, "#endif\n" );
            fprintf( tokout, "#ifndef __YYSTYPE_DEFINED\n" );
            fprintf( tokout, "#define __YYSTYPE_DEFINED\n" );
            fprintf( tokout, "typedef union %s YYSTYPE;\n", buf );
            fprintf( tokout, "#endif\n" );
            scan( 0 );
            break;
        case LCURL:
            lineinfo();
            copycurl();
            scan( 0 );
            break;
        case KEYWORD_ID:
            switch( scan( 0 ) ) {
            case IDENTIFIER:
                sym = addsym( buf );
                if( ! sym->token ) {
                    msg( "Token must be assigned number before %keyword_id\n" );
                }
                value = sym->token;
                break;
            case NUMBER:
                break;
            default:
                msg( "Expecting identifier or number.\n" );
            }
            keyword_id_low = value;
            switch( scan( 0 ) ) {
            case IDENTIFIER:
                sym = addsym( buf );
                if( ! sym->token ) {
                    msg( "Token must be assigned number before %keyword_id\n" );
                }
                value = sym->token;
                break;
            case NUMBER:
                break;
            default:
                msg( "Expecting identifier or number.\n" );
            }
            keyword_id_high = value;
            scan( 0 );
            break;
        case LEFT:
        case RIGHT:
        case NONASSOC:
            ++prec.prec;
            prec.assoc = value;
        case TOKEN:
        case TYPE:
            ctype = token;
            if( scan( 0 ) == '<' ) {
                if( scan( 0 ) != IDENTIFIER ) {
                    msg( "Expecting identifier.\n" );
                }
                type = dupbuf();
                if( scan( 0 ) != '>' ) {
                    msg( "Expecting '>'.\n" );
                }
                scan( 0 );
            } else {
                type = NULL;
            }
            while( token == IDENTIFIER ) {
                sym = addsym( buf );
                if( type != NULL && sym->type != NULL ) {
                    if( strcmp( sym->type, type ) != 0 ) {
                        msg( "'%s' type redeclared from '%s' to '%s'\n",
                            buf, sym->type, type );
                    }
                }
                sym->type = type;
                if( ctype == TYPE ) {
                    scan( 0 );
                } else {
                    if( !sym->token ) {
                        sym->token = value;
                    }
                    if( ctype != TOKEN ) {
                        sym->prec = prec;
                    }
                    if( scan( 0 ) == NUMBER ) {
                        if( sym->token ) {
                            if( sym->name[0] != '\'' ) {
                                fprintf( tokout, "#undef\t%-20s\n", sym->name );
                            }
                        }
                        sym->token = value;
                        scan( 0 );
                    }
                    if( !sym->token ) {
                        sym->token = gentoken++;
                    }
                    if( sym->name[0] != '\'' ) {
                        fprintf( tokout, "#define\t%-20s\t0x%02x\n",
                            sym->name, sym->token );
                    }
                }
                if( token == ',' ) {
                    scan( 0 );
                }
            }
            break;
        default:
            msg( "Incorrect syntax.\n" );
        }
    }
}

static int scanambig( unsigned used, a_SR_conflict_list **list )
{
    int absorbed_something;
    unsigned index;
    a_sym *sym;
    a_SR_conflict *am;
    a_SR_conflict_list *en;

    absorbed_something = 0;
    for(;;) {
        /* syntax is "%ambig <number> <token>" */
        /* token has already been scanned by scanprec() */
        if( token != AMBIG ) {
            break;
        }
        if( scan( used ) != NUMBER || value < 0 ) {
            msg( "Expecting a non-negative number after %ambig.\n" );
            break;
        }
        index = value;
        if( scan( used ) != IDENTIFIER ) {
            msg( "Expecting a token name after %ambig <number>.\n" );
            break;
        }
        sym = findsym( buf );
        if( sym == NULL ) {
            msg( "Unknown token specified in %ambig directive.\n" );
            break;
        }
        if( sym->token == 0 ) {
            msg( "Non-terminal specified in %ambig directive.\n" );
            break;
        }
        scan( used );
        absorbed_something = 1;
        am = make_unique_ambiguity( sym, index );
        en = MALLOC(1,a_SR_conflict_list);
        en->next = *list;
        en->thread = am->thread;
        en->pro = NULL;
        en->conflict = am;
        am->thread = en;
        *list = en;
    }
    return( absorbed_something );
}

static int scanprec( unsigned used, a_sym **precsym )
{
    if( token != PREC ) return( 0 );
    if( scan( used ) != IDENTIFIER || !(*precsym = findsym( buf )) || !(*precsym)->token ) {
        msg( "Expecting a token after %prec.\n" );
    }
    scan( used );
    return( 1 );
}

static void scanextra( unsigned used, a_sym **psym, a_SR_conflict_list **pSR )
{
    scan( used );
    for(;;) {
        if( ! scanprec( used, psym ) && ! scanambig( used, pSR ) ) break;
    }
}

static char *type_name( char *type )
{
    if( type == NULL ) {
        return( "** no type **" );
    }
    return( type );
}

void rules( void )
{
    a_sym               *lhs, **rhs, *sym, *precsym;
    unsigned            nrhs, maxrhs = { 16 };
    a_pro               *pro;
    char                buffer[20];
    unsigned            i;
    int                 numacts;
    bool                action_defined;
    bool                unit_production;
    bool                not_token;
    a_SR_conflict_list  *list_of_ambiguities;
    a_SR_conflict_list  *am;

    rhs = CALLOC( maxrhs, a_sym * );
    while( token == C_IDENTIFIER ) {
        int sym_lineno = lineno;
        lhs = addsym( buf );
        if( lhs->token )
            msg( "%s used on lhs.\n", lhs->name );
        if( !startsym )
            startsym = lhs;
        numacts = 0;
        do {
            action_defined = FALSE;
            precsym = NULL;
            list_of_ambiguities = NULL;

⌨️ 快捷键说明

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