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