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 + -
显示快捷键?