1
0

Source code upload

This commit is contained in:
calmsacibis995
2022-09-29 17:59:04 +03:00
parent 72fa9da3d7
commit 8fc8fa8089
33399 changed files with 11964078 additions and 0 deletions
+702
View File
@@ -0,0 +1,702 @@
/* Generate the nondeterministic finite state machine for bison,
Copyright (C) 1984, 1986, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* See comments in state.h for the data structures that represent it.
The entry point is generate_states. */
#include <stdio.h>
#include "system.h"
#include "machine.h"
#include "new.h"
#include "gram.h"
#include "state.h"
extern char *nullable;
extern short *itemset;
extern short *itemsetend;
int nstates;
int final_state;
core *first_state;
shifts *first_shift;
reductions *first_reduction;
int get_state();
core *new_state();
void new_itemsets();
void append_states();
void initialize_states();
void save_shifts();
void save_reductions();
void augment_automaton();
void insert_start_shift();
extern void initialize_closure();
extern void closure();
extern void finalize_closure();
extern void toomany();
static core *this_state;
static core *last_state;
static shifts *last_shift;
static reductions *last_reduction;
static int nshifts;
static short *shift_symbol;
static short *redset;
static short *shiftset;
static short **kernel_base;
static short **kernel_end;
static short *kernel_items;
/* hash table for states, to recognize equivalent ones. */
#define STATE_TABLE_SIZE 1009
static core **state_table;
void
allocate_itemsets()
{
register short *itemp;
register int symbol;
register int i;
register int count;
register short *symbol_count;
count = 0;
symbol_count = NEW2(nsyms, short);
itemp = ritem;
symbol = *itemp++;
while (symbol)
{
if (symbol > 0)
{
count++;
symbol_count[symbol]++;
}
symbol = *itemp++;
}
/* see comments before new_itemsets. All the vectors of items
live inside kernel_items. The number of active items after
some symbol cannot be more than the number of times that symbol
appears as an item, which is symbol_count[symbol].
We allocate that much space for each symbol. */
kernel_base = NEW2(nsyms, short *);
kernel_items = NEW2(count, short);
count = 0;
for (i = 0; i < nsyms; i++)
{
kernel_base[i] = kernel_items + count;
count += symbol_count[i];
}
shift_symbol = symbol_count;
kernel_end = NEW2(nsyms, short *);
}
void
allocate_storage()
{
allocate_itemsets();
shiftset = NEW2(nsyms, short);
redset = NEW2(nrules + 1, short);
state_table = NEW2(STATE_TABLE_SIZE, core *);
}
void
free_storage()
{
FREE(shift_symbol);
FREE(redset);
FREE(shiftset);
FREE(kernel_base);
FREE(kernel_end);
FREE(kernel_items);
FREE(state_table);
}
/* compute the nondeterministic finite state machine (see state.h for details)
from the grammar. */
void
generate_states()
{
allocate_storage();
initialize_closure(nitems);
initialize_states();
while (this_state)
{
/* Set up ruleset and itemset for the transitions out of this state.
ruleset gets a 1 bit for each rule that could reduce now.
itemset gets a vector of all the items that could be accepted next. */
closure(this_state->items, this_state->nitems);
/* record the reductions allowed out of this state */
save_reductions();
/* find the itemsets of the states that shifts can reach */
new_itemsets();
/* find or create the core structures for those states */
append_states();
/* create the shifts structures for the shifts to those states,
now that the state numbers transitioning to are known */
if (nshifts > 0)
save_shifts();
/* states are queued when they are created; process them all */
this_state = this_state->next;
}
/* discard various storage */
finalize_closure();
free_storage();
/* set up initial and final states as parser wants them */
augment_automaton();
}
/* Find which symbols can be shifted in the current state,
and for each one record which items would be active after that shift.
Uses the contents of itemset.
shift_symbol is set to a vector of the symbols that can be shifted.
For each symbol in the grammar, kernel_base[symbol] points to
a vector of item numbers activated if that symbol is shifted,
and kernel_end[symbol] points after the end of that vector. */
void
new_itemsets()
{
register int i;
register int shiftcount;
register short *isp;
register short *ksp;
register int symbol;
#ifdef TRACE
fprintf(stderr, "Entering new_itemsets\n");
#endif
for (i = 0; i < nsyms; i++)
kernel_end[i] = NULL;
shiftcount = 0;
isp = itemset;
while (isp < itemsetend)
{
i = *isp++;
symbol = ritem[i];
if (symbol > 0)
{
ksp = kernel_end[symbol];
if (!ksp)
{
shift_symbol[shiftcount++] = symbol;
ksp = kernel_base[symbol];
}
*ksp++ = i + 1;
kernel_end[symbol] = ksp;
}
}
nshifts = shiftcount;
}
/* Use the information computed by new_itemsets to find the state numbers
reached by each shift transition from the current state.
shiftset is set up as a vector of state numbers of those states. */
void
append_states()
{
register int i;
register int j;
register int symbol;
#ifdef TRACE
fprintf(stderr, "Entering append_states\n");
#endif
/* first sort shift_symbol into increasing order */
for (i = 1; i < nshifts; i++)
{
symbol = shift_symbol[i];
j = i;
while (j > 0 && shift_symbol[j - 1] > symbol)
{
shift_symbol[j] = shift_symbol[j - 1];
j--;
}
shift_symbol[j] = symbol;
}
for (i = 0; i < nshifts; i++)
{
symbol = shift_symbol[i];
shiftset[i] = get_state(symbol);
}
}
/* find the state number for the state we would get to
(from the current state) by shifting symbol.
Create a new state if no equivalent one exists already.
Used by append_states */
int
get_state(symbol)
int symbol;
{
register int key;
register short *isp1;
register short *isp2;
register short *iend;
register core *sp;
register int found;
int n;
#ifdef TRACE
fprintf(stderr, "Entering get_state, symbol = %d\n", symbol);
#endif
isp1 = kernel_base[symbol];
iend = kernel_end[symbol];
n = iend - isp1;
/* add up the target state's active item numbers to get a hash key */
key = 0;
while (isp1 < iend)
key += *isp1++;
key = key % STATE_TABLE_SIZE;
sp = state_table[key];
if (sp)
{
found = 0;
while (!found)
{
if (sp->nitems == n)
{
found = 1;
isp1 = kernel_base[symbol];
isp2 = sp->items;
while (found && isp1 < iend)
{
if (*isp1++ != *isp2++)
found = 0;
}
}
if (!found)
{
if (sp->link)
{
sp = sp->link;
}
else /* bucket exhausted and no match */
{
sp = sp->link = new_state(symbol);
found = 1;
}
}
}
}
else /* bucket is empty */
{
state_table[key] = sp = new_state(symbol);
}
return (sp->number);
}
/* subroutine of get_state. create a new state for those items, if necessary. */
core *
new_state(symbol)
int symbol;
{
register int n;
register core *p;
register short *isp1;
register short *isp2;
register short *iend;
#ifdef TRACE
fprintf(stderr, "Entering new_state, symbol = %d\n", symbol);
#endif
if (nstates >= MAXSHORT)
toomany("states");
isp1 = kernel_base[symbol];
iend = kernel_end[symbol];
n = iend - isp1;
p = (core *) mallocate((unsigned) (sizeof(core) + (n - 1) * sizeof(short)));
p->accessing_symbol = symbol;
p->number = nstates;
p->nitems = n;
isp2 = p->items;
while (isp1 < iend)
*isp2++ = *isp1++;
last_state->next = p;
last_state = p;
nstates++;
return (p);
}
void
initialize_states()
{
register core *p;
/* register unsigned *rp1; JF unused */
/* register unsigned *rp2; JF unused */
/* register unsigned *rend; JF unused */
p = (core *) mallocate((unsigned) (sizeof(core) - sizeof(short)));
first_state = last_state = this_state = p;
nstates = 1;
}
void
save_shifts()
{
register shifts *p;
register short *sp1;
register short *sp2;
register short *send;
p = (shifts *) mallocate((unsigned) (sizeof(shifts) +
(nshifts - 1) * sizeof(short)));
p->number = this_state->number;
p->nshifts = nshifts;
sp1 = shiftset;
sp2 = p->shifts;
send = shiftset + nshifts;
while (sp1 < send)
*sp2++ = *sp1++;
if (last_shift)
{
last_shift->next = p;
last_shift = p;
}
else
{
first_shift = p;
last_shift = p;
}
}
/* find which rules can be used for reduction transitions from the current state
and make a reductions structure for the state to record their rule numbers. */
void
save_reductions()
{
register short *isp;
register short *rp1;
register short *rp2;
register int item;
register int count;
register reductions *p;
short *rend;
/* find and count the active items that represent ends of rules */
count = 0;
for (isp = itemset; isp < itemsetend; isp++)
{
item = ritem[*isp];
if (item < 0)
{
redset[count++] = -item;
}
}
/* make a reductions structure and copy the data into it. */
if (count)
{
p = (reductions *) mallocate((unsigned) (sizeof(reductions) +
(count - 1) * sizeof(short)));
p->number = this_state->number;
p->nreds = count;
rp1 = redset;
rp2 = p->rules;
rend = rp1 + count;
while (rp1 < rend)
*rp2++ = *rp1++;
if (last_reduction)
{
last_reduction->next = p;
last_reduction = p;
}
else
{
first_reduction = p;
last_reduction = p;
}
}
}
/* Make sure that the initial state has a shift that accepts the
grammar's start symbol and goes to the next-to-final state,
which has a shift going to the final state, which has a shift
to the termination state.
Create such states and shifts if they don't happen to exist already. */
void
augment_automaton()
{
register int i;
register int k;
/* register int found; JF unused */
register core *statep;
register shifts *sp;
register shifts *sp2;
register shifts *sp1;
sp = first_shift;
if (sp)
{
if (sp->number == 0)
{
k = sp->nshifts;
statep = first_state->next;
/* The states reached by shifts from first_state are numbered 1...K.
Look for one reached by start_symbol. */
while (statep->accessing_symbol < start_symbol
&& statep->number < k)
statep = statep->next;
if (statep->accessing_symbol == start_symbol)
{
/* We already have a next-to-final state.
Make sure it has a shift to what will be the final state. */
k = statep->number;
while (sp && sp->number < k)
{
sp1 = sp;
sp = sp->next;
}
if (sp && sp->number == k)
{
sp2 = (shifts *) mallocate((unsigned) (sizeof(shifts)
+ sp->nshifts * sizeof(short)));
sp2->number = k;
sp2->nshifts = sp->nshifts + 1;
sp2->shifts[0] = nstates;
for (i = sp->nshifts; i > 0; i--)
sp2->shifts[i] = sp->shifts[i - 1];
/* Patch sp2 into the chain of shifts in place of sp,
following sp1. */
sp2->next = sp->next;
sp1->next = sp2;
if (sp == last_shift)
last_shift = sp2;
FREE(sp);
}
else
{
sp2 = NEW(shifts);
sp2->number = k;
sp2->nshifts = 1;
sp2->shifts[0] = nstates;
/* Patch sp2 into the chain of shifts between sp1 and sp. */
sp2->next = sp;
sp1->next = sp2;
if (sp == 0)
last_shift = sp2;
}
}
else
{
/* There is no next-to-final state as yet. */
/* Add one more shift in first_shift,
going to the next-to-final state (yet to be made). */
sp = first_shift;
sp2 = (shifts *) mallocate(sizeof(shifts)
+ sp->nshifts * sizeof(short));
sp2->nshifts = sp->nshifts + 1;
/* Stick this shift into the vector at the proper place. */
statep = first_state->next;
for (k = 0, i = 0; i < sp->nshifts; k++, i++)
{
if (statep->accessing_symbol > start_symbol && i == k)
sp2->shifts[k++] = nstates;
sp2->shifts[k] = sp->shifts[i];
statep = statep->next;
}
/* Patch sp2 into the chain of shifts
in place of sp, at the beginning. */
sp2->next = sp->next;
first_shift = sp2;
if (last_shift == sp)
last_shift = sp2;
FREE(sp);
/* Create the next-to-final state, with shift to
what will be the final state. */
insert_start_shift();
}
}
else
{
/* The initial state didn't even have any shifts.
Give it one shift, to the next-to-final state. */
sp = NEW(shifts);
sp->nshifts = 1;
sp->shifts[0] = nstates;
/* Patch sp into the chain of shifts at the beginning. */
sp->next = first_shift;
first_shift = sp;
/* Create the next-to-final state, with shift to
what will be the final state. */
insert_start_shift();
}
}
else
{
/* There are no shifts for any state.
Make one shift, from the initial state to the next-to-final state. */
sp = NEW(shifts);
sp->nshifts = 1;
sp->shifts[0] = nstates;
/* Initialize the chain of shifts with sp. */
first_shift = sp;
last_shift = sp;
/* Create the next-to-final state, with shift to
what will be the final state. */
insert_start_shift();
}
/* Make the final state--the one that follows a shift from the
next-to-final state.
The symbol for that shift is 0 (end-of-file). */
statep = (core *) mallocate((unsigned) (sizeof(core) - sizeof(short)));
statep->number = nstates;
last_state->next = statep;
last_state = statep;
/* Make the shift from the final state to the termination state. */
sp = NEW(shifts);
sp->number = nstates++;
sp->nshifts = 1;
sp->shifts[0] = nstates;
last_shift->next = sp;
last_shift = sp;
/* Note that the variable `final_state' refers to what we sometimes call
the termination state. */
final_state = nstates;
/* Make the termination state. */
statep = (core *) mallocate((unsigned) (sizeof(core) - sizeof(short)));
statep->number = nstates++;
last_state->next = statep;
last_state = statep;
}
/* subroutine of augment_automaton.
Create the next-to-final state, to which a shift has already been made in
the initial state. */
void
insert_start_shift()
{
register core *statep;
register shifts *sp;
statep = (core *) mallocate((unsigned) (sizeof(core) - sizeof(short)));
statep->number = nstates;
statep->accessing_symbol = start_symbol;
last_state->next = statep;
last_state = statep;
/* Make a shift from this state to (what will be) the final state. */
sp = NEW(shifts);
sp->number = nstates++;
sp->nshifts = 1;
sp->shifts[0] = nstates;
last_shift->next = sp;
last_shift = sp;
}
+25
View File
@@ -0,0 +1,25 @@
#
include $(ROOT)/usr/include/make/commondefs
CFILES= LR0.c allocate.c closure.c conflicts.c derives.c files.c \
getargs.c getopt.c getopt1.c gram.c lalr.c lex.c main.c nullable.c \
output.c print.c reader.c reduce.c symtab.c version.c warshall.c alloca.c
SIMPLE=bison.simple
HAIRY=bison.hairy
TARGETS=bison
LLDLIBS=-lw
LCOPTS=-DXPFILE=\"$(ROOT)/usr/lib/$(SIMPLE)\" \
-DXPFILE1=\"$(ROOT)/usr/lib/$(HAIRY)\"
default: $(TARGETS)
include $(COMMONRULES)
bison: $(OBJECTS)
$(CCF) $(OBJECTS) $(LDFLAGS) -o $@
install: default
$(INSTALL) -F /usr/sbin $(TARGETS)
$(INSTALL) -F /usr/lib $(SIMPLE)
$(INSTALL) -F /usr/lib $(HAIRY)
+191
View File
@@ -0,0 +1,191 @@
/*
alloca -- (mostly) portable public-domain implementation -- D A Gwyn
last edit: 86/05/30 rms
include config.h, since on VMS it renames some symbols.
Use xmalloc instead of malloc.
This implementation of the PWB library alloca() function,
which is used to allocate space off the run-time stack so
that it is automatically reclaimed upon procedure exit,
was inspired by discussions with J. Q. Johnson of Cornell.
It should work under any C implementation that uses an
actual procedure stack (as opposed to a linked list of
frames). There are some preprocessor constants that can
be defined when compiling for your specific system, for
improved efficiency; however, the defaults should be okay.
The general concept of this implementation is to keep
track of all alloca()-allocated blocks, and reclaim any
that are found to be deeper in the stack than the current
invocation. This heuristic does not reclaim storage as
soon as it becomes invalid, but it will do so eventually.
As a special case, alloca(0) reclaims storage without
allocating any. It is a good idea to use alloca(0) in
your main control loop, etc. to force garbage collection.
*/
#ifndef lint
static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */
#endif
#ifdef emacs
#include "config.h"
#ifdef static
/* actually, only want this if static is defined as ""
-- this is for usg, in which emacs must undefine static
in order to make unexec workable
*/
#ifndef STACK_DIRECTION
you
lose
-- must know STACK_DIRECTION at compile-time
#endif /* STACK_DIRECTION undefined */
#endif /* static */
#endif /* emacs */
#ifdef __STDC__
typedef void *pointer; /* generic pointer type */
#else
typedef char *pointer; /* generic pointer type */
#endif
#define NULL 0 /* null pointer constant */
extern void free();
extern pointer xmalloc();
/*
Define STACK_DIRECTION if you know the direction of stack
growth for your system; otherwise it will be automatically
deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
#ifndef STACK_DIRECTION
#define STACK_DIRECTION 0 /* direction unknown */
#endif
#if STACK_DIRECTION != 0
#define STACK_DIR STACK_DIRECTION /* known at compile-time */
#else /* STACK_DIRECTION == 0; need run-time code */
static int stack_dir; /* 1 or -1 once known */
#define STACK_DIR stack_dir
static void
find_stack_direction (/* void */)
{
static char *addr = NULL; /* address of first
`dummy', once known */
auto char dummy; /* to get stack address */
if (addr == NULL)
{ /* initial entry */
addr = &dummy;
find_stack_direction (); /* recurse once */
}
else /* second entry */
if (&dummy > addr)
stack_dir = 1; /* stack grew upward */
else
stack_dir = -1; /* stack grew downward */
}
#endif /* STACK_DIRECTION == 0 */
/*
An "alloca header" is used to:
(a) chain together all alloca()ed blocks;
(b) keep track of stack depth.
It is very important that sizeof(header) agree with malloc()
alignment chunk size. The following default should work okay.
*/
#ifndef ALIGN_SIZE
#define ALIGN_SIZE sizeof(double)
#endif
typedef union hdr
{
char align[ALIGN_SIZE]; /* to force sizeof(header) */
struct
{
union hdr *next; /* for chaining headers */
char *deep; /* for stack depth measure */
} h;
} header;
/*
alloca( size ) returns a pointer to at least `size' bytes of
storage which will be automatically reclaimed upon exit from
the procedure that called alloca(). Originally, this space
was supposed to be taken from the current stack frame of the
caller, but that method cannot be made to work for some
implementations of C, for example under Gould's UTX/32.
*/
static header *last_alloca_header = NULL; /* -> last alloca header */
pointer
alloca (size) /* returns pointer to storage */
unsigned size; /* # bytes to allocate */
{
auto char probe; /* probes stack depth: */
register char *depth = &probe;
#if STACK_DIRECTION == 0
if (STACK_DIR == 0) /* unknown growth direction */
find_stack_direction ();
#endif
/* Reclaim garbage, defined as all alloca()ed storage that
was allocated from deeper in the stack than currently. */
{
register header *hp; /* traverses linked list */
for (hp = last_alloca_header; hp != NULL;)
if ((STACK_DIR > 0 && hp->h.deep > depth)
|| (STACK_DIR < 0 && hp->h.deep < depth))
{
register header *np = hp->h.next;
free ((pointer) hp); /* collect garbage */
hp = np; /* -> next header */
}
else
break; /* rest are not deeper */
last_alloca_header = hp; /* -> last valid storage */
}
if (size == 0)
return NULL; /* no allocation required */
/* Allocate combined header + user data storage. */
{
register pointer new = xmalloc (sizeof (header) + size);
/* address of header */
((header *)new)->h.next = last_alloca_header;
((header *)new)->h.deep = depth;
last_alloca_header = (header *)new;
/* User storage begins just after header. */
return (pointer)((char *)new + sizeof(header));
}
}
+54
View File
@@ -0,0 +1,54 @@
/* Allocate and clear storage for bison,
Copyright (C) 1984, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
extern char *calloc();
extern void done();
extern char *program_name;
char *
mallocate(n)
register unsigned n;
{
register char *block;
/* Avoid uncertainty about what an arg of 0 will do. */
if (n == 0)
n = 1;
block = calloc(n,1);
if (block == NULL)
{
fprintf(stderr, "%s: memory exhausted\n", program_name);
done(1);
}
return (block);
}
/* This name is used by alloca.c. */
char *
xmalloc (n)
unsigned int n;
{
return mallocate (n);
}
+334
View File
@@ -0,0 +1,334 @@
extern int timeclock;
int yyerror; /* Yyerror and yycost are set by guards. */
int yycost; /* If yyerror is set to a nonzero value by a */
/* guard, the reduction with which the guard */
/* is associated is not performed, and the */
/* error recovery mechanism is invoked. */
/* Yycost indicates the cost of performing */
/* the reduction given the attributes of the */
/* symbols. */
/* YYMAXDEPTH indicates the size of the parser's state and value */
/* stacks. */
#ifndef YYMAXDEPTH
#define YYMAXDEPTH 500
#endif
/* YYMAXRULES must be at least as large as the number of rules that */
/* could be placed in the rule queue. That number could be determined */
/* from the grammar and the size of the stack, but, as yet, it is not. */
#ifndef YYMAXRULES
#define YYMAXRULES 100
#endif
#ifndef YYMAXBACKUP
#define YYMAXBACKUP 100
#endif
short yyss[YYMAXDEPTH]; /* the state stack */
YYSTYPE yyvs[YYMAXDEPTH]; /* the semantic value stack */
YYLTYPE yyls[YYMAXDEPTH]; /* the location stack */
short yyrq[YYMAXRULES]; /* the rule queue */
int yychar; /* the lookahead symbol */
YYSTYPE yylval; /* the semantic value of the */
/* lookahead symbol */
YYSTYPE yytval; /* the semantic value for the state */
/* at the top of the state stack. */
YYSTYPE yyval; /* the variable used to return */
/* semantic values from the action */
/* routines */
YYLTYPE yylloc; /* location data for the lookahead */
/* symbol */
YYLTYPE yytloc; /* location data for the state at the */
/* top of the state stack */
int yynunlexed;
short yyunchar[YYMAXBACKUP];
YYSTYPE yyunval[YYMAXBACKUP];
YYLTYPE yyunloc[YYMAXBACKUP];
short *yygssp; /* a pointer to the top of the state */
/* stack; only set during error */
/* recovery. */
YYSTYPE *yygvsp; /* a pointer to the top of the value */
/* stack; only set during error */
/* recovery. */
YYLTYPE *yyglsp; /* a pointer to the top of the */
/* location stack; only set during */
/* error recovery. */
/* Yyget is an interface between the parser and the lexical analyzer. */
/* It is costly to provide such an interface, but it avoids requiring */
/* the lexical analyzer to be able to back up the scan. */
yyget()
{
if (yynunlexed > 0)
{
yynunlexed--;
yychar = yyunchar[yynunlexed];
yylval = yyunval[yynunlexed];
yylloc = yyunloc[yynunlexed];
}
else if (yychar <= 0)
yychar = 0;
else
{
yychar = yylex();
if (yychar < 0)
yychar = 0;
else yychar = YYTRANSLATE(yychar);
}
}
yyunlex(chr, val, loc)
int chr;
YYSTYPE val;
YYLTYPE loc;
{
yyunchar[yynunlexed] = chr;
yyunval[yynunlexed] = val;
yyunloc[yynunlexed] = loc;
yynunlexed++;
}
yyrestore(first, last)
register short *first;
register short *last;
{
register short *ssp;
register short *rp;
register int symbol;
register int state;
register int tvalsaved;
ssp = yygssp;
yyunlex(yychar, yylval, yylloc);
tvalsaved = 0;
while (first != last)
{
symbol = yystos[*ssp];
if (symbol < YYNTBASE)
{
yyunlex(symbol, yytval, yytloc);
tvalsaved = 1;
ssp--;
}
ssp--;
if (first == yyrq)
first = yyrq + YYMAXRULES;
first--;
for (rp = yyrhs + yyprhs[*first]; symbol = *rp; rp++)
{
if (symbol < YYNTBASE)
state = yytable[yypact[*ssp] + symbol];
else
{
state = yypgoto[symbol - YYNTBASE] + *ssp;
if (state >= 0 && state <= YYLAST && yycheck[state] == *ssp)
state = yytable[state];
else
state = yydefgoto[symbol - YYNTBASE];
}
*++ssp = state;
}
}
if ( ! tvalsaved && ssp > yyss)
{
yyunlex(yystos[*ssp], yytval, yytloc);
ssp--;
}
yygssp = ssp;
}
int
yyparse()
{
register int yystate;
register int yyn;
register short *yyssp;
register short *yyrq0;
register short *yyptr;
register YYSTYPE *yyvsp;
int yylen;
YYLTYPE *yylsp;
short *yyrq1;
short *yyrq2;
yystate = 0;
yyssp = yyss - 1;
yyvsp = yyvs - 1;
yylsp = yyls - 1;
yyrq0 = yyrq;
yyrq1 = yyrq0;
yyrq2 = yyrq0;
yychar = yylex();
if (yychar < 0)
yychar = 0;
else yychar = YYTRANSLATE(yychar);
yynewstate:
if (yyssp >= yyss + YYMAXDEPTH - 1)
{
yyabort("Parser Stack Overflow");
YYABORT;
}
*++yyssp = yystate;
yyresume:
yyn = yypact[yystate];
if (yyn == YYFLAG)
goto yydefault;
yyn += yychar;
if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar)
goto yydefault;
yyn = yytable[yyn];
if (yyn < 0)
{
yyn = -yyn;
goto yyreduce;
}
else if (yyn == 0)
goto yyerrlab;
yystate = yyn;
yyptr = yyrq2;
while (yyptr != yyrq1)
{
yyn = *yyptr++;
yylen = yyr2[yyn];
yyvsp -= yylen;
yylsp -= yylen;
yyguard(yyn, yyvsp, yylsp);
if (yyerror)
goto yysemerr;
yyaction(yyn, yyvsp, yylsp);
*++yyvsp = yyval;
yylsp++;
if (yylen == 0)
{
yylsp->timestamp = timeclock;
yylsp->first_line = yytloc.first_line;
yylsp->first_column = yytloc.first_column;
yylsp->last_line = (yylsp-1)->last_line;
yylsp->last_column = (yylsp-1)->last_column;
yylsp->text = 0;
}
else
{
yylsp->last_line = (yylsp+yylen-1)->last_line;
yylsp->last_column = (yylsp+yylen-1)->last_column;
}
if (yyptr == yyrq + YYMAXRULES)
yyptr = yyrq;
}
if (yystate == YYFINAL)
YYACCEPT;
yyrq2 = yyptr;
yyrq1 = yyrq0;
*++yyvsp = yytval;
*++yylsp = yytloc;
yytval = yylval;
yytloc = yylloc;
yyget();
goto yynewstate;
yydefault:
yyn = yydefact[yystate];
if (yyn == 0)
goto yyerrlab;
yyreduce:
*yyrq0++ = yyn;
if (yyrq0 == yyrq + YYMAXRULES)
yyrq0 = yyrq;
if (yyrq0 == yyrq2)
{
yyabort("Parser Rule Queue Overflow");
YYABORT;
}
yyssp -= yyr2[yyn];
yyn = yyr1[yyn];
yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
yystate = yytable[yystate];
else
yystate = yydefgoto[yyn - YYNTBASE];
goto yynewstate;
yysemerr:
*--yyptr = yyn;
yyrq2 = yyptr;
yyvsp += yyr2[yyn];
yyerrlab:
yygssp = yyssp;
yygvsp = yyvsp;
yyglsp = yylsp;
yyrestore(yyrq0, yyrq2);
yyrecover();
yystate = *yygssp;
yyssp = yygssp;
yyvsp = yygvsp;
yyrq0 = yyrq;
yyrq1 = yyrq0;
yyrq2 = yyrq0;
goto yyresume;
}
$
+625
View File
@@ -0,0 +1,625 @@
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
#line 3 "bison.simple"
/* Skeleton output parser for bison,
Copyright (C) 1984, 1989, 1990 Bob Corbett and Richard Stallman
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef alloca
#ifdef __GNUC__
#define alloca __builtin_alloca
#else /* not GNU C. */
#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__)
#include <alloca.h>
#else /* not sparc */
#if defined (MSDOS) && !defined (__TURBOC__)
#include <malloc.h>
#else /* not MSDOS, or __TURBOC__ */
#if defined(_AIX)
#include <malloc.h>
#pragma alloca
#endif /* not _AIX */
#endif /* not MSDOS, or __TURBOC__ */
#endif /* not sparc. */
#endif /* not GNU C. */
#endif /* alloca not defined. */
/* This is the parser code that is written into each bison parser
when the %semantic_parser declaration is not specified in the grammar.
It was written by Richard Stallman by simplifying the hairy parser
used when %semantic_parser is specified. */
/* Note: there must be only one dollar sign in this file.
It is replaced by the list of actions, each action
as one case of the switch. */
#define yyerrok (yyerrstatus = 0)
#define yyclearin (yychar = YYEMPTY)
#define YYEMPTY -2
#define YYEOF 0
#define YYACCEPT return(0)
#define YYABORT return(1)
#define YYERROR goto yyerrlab1
/* Like YYERROR except do call yyerror.
This remains here temporarily to ease the
transition to the new meaning of YYERROR, for GCC.
Once GCC version 2 has supplanted version 1, this can go. */
#define YYFAIL goto yyerrlab
#define YYRECOVERING() (!!yyerrstatus)
#define YYBACKUP(token, value) \
do \
if (yychar == YYEMPTY && yylen == 1) \
{ yychar = (token), yylval = (value); \
yychar1 = YYTRANSLATE (yychar); \
YYPOPSTACK; \
goto yybackup; \
} \
else \
{ yyerror ("syntax error: cannot back up"); YYERROR; } \
while (0)
#define YYTERROR 1
#define YYERRCODE 256
#ifndef YYPURE
#define YYLEX yylex()
#endif
#ifdef YYPURE
#ifdef YYLSP_NEEDED
#define YYLEX yylex(&yylval, &yylloc)
#else
#define YYLEX yylex(&yylval)
#endif
#endif
/* If nonreentrant, generate the variables here */
#ifndef YYPURE
int yychar; /* the lookahead symbol */
YYSTYPE yylval; /* the semantic value of the */
/* lookahead symbol */
#ifdef YYLSP_NEEDED
YYLTYPE yylloc; /* location data for the lookahead */
/* symbol */
#endif
int yynerrs; /* number of parse errors so far */
#endif /* not YYPURE */
#if YYDEBUG != 0
int yydebug; /* nonzero means print parse trace */
/* Since this is uninitialized, it does not stop multiple parsers
from coexisting. */
#endif
/* YYINITDEPTH indicates the initial size of the parser's stacks */
#ifndef YYINITDEPTH
#define YYINITDEPTH 200
#endif
/* YYMAXDEPTH is the maximum size the stacks can grow to
(effective only if the built-in stack extension method is used). */
#if YYMAXDEPTH == 0
#undef YYMAXDEPTH
#endif
#ifndef YYMAXDEPTH
#define YYMAXDEPTH 10000
#endif
#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
#define __yy_bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)
#else /* not GNU C or C++ */
#ifndef __cplusplus
/* This is the most reliable way to avoid incompatibilities
in available built-in functions on various systems. */
static void
__yy_bcopy (from, to, count)
char *from;
char *to;
int count;
{
register char *f = from;
register char *t = to;
register int i = count;
while (i-- > 0)
*t++ = *f++;
}
#else /* __cplusplus */
/* This is the most reliable way to avoid incompatibilities
in available built-in functions on various systems. */
static void
__yy_bcopy (char *from, char *to, int count)
{
register char *f = from;
register char *t = to;
register int i = count;
while (i-- > 0)
*t++ = *f++;
}
#endif
#endif
#line 169 "bison.simple"
int
yyparse()
{
register int yystate;
register int yyn;
register short *yyssp;
register YYSTYPE *yyvsp;
int yyerrstatus; /* number of tokens to shift before error messages enabled */
int yychar1; /* lookahead token as an internal (translated) token number */
short yyssa[YYINITDEPTH]; /* the state stack */
YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
short *yyss = yyssa; /* refer to the stacks thru separate pointers */
YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
#ifdef YYLSP_NEEDED
YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
YYLTYPE *yyls = yylsa;
YYLTYPE *yylsp;
#define YYPOPSTACK (yyvsp--, yysp--, yylsp--)
#else
#define YYPOPSTACK (yyvsp--, yysp--)
#endif
int yystacksize = YYINITDEPTH;
#ifdef YYPURE
int yychar;
YYSTYPE yylval;
int yynerrs;
#ifdef YYLSP_NEEDED
YYLTYPE yylloc;
#endif
#endif
YYSTYPE yyval; /* the variable used to return */
/* semantic values from the action */
/* routines */
int yylen;
#if YYDEBUG != 0
if (yydebug)
fprintf(stderr, "Starting parse\n");
#endif
yystate = 0;
yyerrstatus = 0;
yynerrs = 0;
yychar = YYEMPTY; /* Cause a token to be read. */
/* Initialize stack pointers.
Waste one element of value and location stack
so that they stay on the same level as the state stack. */
yyssp = yyss - 1;
yyvsp = yyvs;
#ifdef YYLSP_NEEDED
yylsp = yyls;
#endif
/* Push a new state, which is found in yystate . */
/* In all cases, when you get here, the value and location stacks
have just been pushed. so pushing a state here evens the stacks. */
yynewstate:
*++yyssp = yystate;
if (yyssp >= yyss + yystacksize - 1)
{
/* Give user a chance to reallocate the stack */
/* Use copies of these so that the &'s don't force the real ones into memory. */
YYSTYPE *yyvs1 = yyvs;
short *yyss1 = yyss;
#ifdef YYLSP_NEEDED
YYLTYPE *yyls1 = yyls;
#endif
/* Get the current used size of the three stacks, in elements. */
int size = yyssp - yyss + 1;
#ifdef yyoverflow
/* Each stack pointer address is followed by the size of
the data in use in that stack, in bytes. */
yyoverflow("parser stack overflow",
&yyss1, size * sizeof (*yyssp),
&yyvs1, size * sizeof (*yyvsp),
#ifdef YYLSP_NEEDED
&yyls1, size * sizeof (*yylsp),
#endif
&yystacksize);
yyss = yyss1; yyvs = yyvs1;
#ifdef YYLSP_NEEDED
yyls = yyls1;
#endif
#else /* no yyoverflow */
/* Extend the stack our own way. */
if (yystacksize >= YYMAXDEPTH)
{
yyerror("parser stack overflow");
return 2;
}
yystacksize *= 2;
if (yystacksize > YYMAXDEPTH)
yystacksize = YYMAXDEPTH;
yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
__yy_bcopy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp));
yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
__yy_bcopy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp));
#ifdef YYLSP_NEEDED
yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
__yy_bcopy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
#endif
#endif /* no yyoverflow */
yyssp = yyss + size - 1;
yyvsp = yyvs + size - 1;
#ifdef YYLSP_NEEDED
yylsp = yyls + size - 1;
#endif
#if YYDEBUG != 0
if (yydebug)
fprintf(stderr, "Stack size increased to %d\n", yystacksize);
#endif
if (yyssp >= yyss + yystacksize - 1)
YYABORT;
}
#if YYDEBUG != 0
if (yydebug)
fprintf(stderr, "Entering state %d\n", yystate);
#endif
yybackup:
/* Do appropriate processing given the current state. */
/* Read a lookahead token if we need one and don't already have one. */
/* yyresume: */
/* First try to decide what to do without reference to lookahead token. */
yyn = yypact[yystate];
if (yyn == YYFLAG)
goto yydefault;
/* Not known => get a lookahead token if don't already have one. */
/* yychar is either YYEMPTY or YYEOF
or a valid token in external form. */
if (yychar == YYEMPTY)
{
#if YYDEBUG != 0
if (yydebug)
fprintf(stderr, "Reading a token: ");
#endif
yychar = YYLEX;
}
/* Convert token to internal form (in yychar1) for indexing tables with */
if (yychar <= 0) /* This means end of input. */
{
yychar1 = 0;
yychar = YYEOF; /* Don't call YYLEX any more */
#if YYDEBUG != 0
if (yydebug)
fprintf(stderr, "Now at end of input.\n");
#endif
}
else
{
yychar1 = YYTRANSLATE(yychar);
#if YYDEBUG != 0
if (yydebug)
{
fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
/* Give the individual parser a way to print the precise meaning
of a token, for further debugging info. */
#ifdef YYPRINT
YYPRINT (stderr, yychar, yylval);
#endif
fprintf (stderr, ")\n");
}
#endif
}
yyn += yychar1;
if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
goto yydefault;
yyn = yytable[yyn];
/* yyn is what to do for this token type in this state.
Negative => reduce, -yyn is rule number.
Positive => shift, yyn is new state.
New state is final state => don't bother to shift,
just return success.
0, or most negative number => error. */
if (yyn < 0)
{
if (yyn == YYFLAG)
goto yyerrlab;
yyn = -yyn;
goto yyreduce;
}
else if (yyn == 0)
goto yyerrlab;
if (yyn == YYFINAL)
YYACCEPT;
/* Shift the lookahead token. */
#if YYDEBUG != 0
if (yydebug)
fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
#endif
/* Discard the token being shifted unless it is eof. */
if (yychar != YYEOF)
yychar = YYEMPTY;
*++yyvsp = yylval;
#ifdef YYLSP_NEEDED
*++yylsp = yylloc;
#endif
/* count tokens shifted since error; after three, turn off error status. */
if (yyerrstatus) yyerrstatus--;
yystate = yyn;
goto yynewstate;
/* Do the default action for the current state. */
yydefault:
yyn = yydefact[yystate];
if (yyn == 0)
goto yyerrlab;
/* Do a reduction. yyn is the number of a rule to reduce with. */
yyreduce:
yylen = yyr2[yyn];
yyval = yyvsp[1-yylen]; /* implement default value of the action */
#if YYDEBUG != 0
if (yydebug)
{
int i;
fprintf (stderr, "Reducing via rule %d (line %d), ",
yyn, yyrline[yyn]);
/* Print the symboles being reduced, and their result. */
for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
fprintf (stderr, "%s ", yytname[yyrhs[i]]);
fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
}
#endif
$ /* the action file gets copied in in place of this dollarsign */
#line 440 "bison.simple"
yyvsp -= yylen;
yyssp -= yylen;
#ifdef YYLSP_NEEDED
yylsp -= yylen;
#endif
#if YYDEBUG != 0
if (yydebug)
{
short *ssp1 = yyss - 1;
fprintf (stderr, "state stack now");
while (ssp1 != yyssp)
fprintf (stderr, " %d", *++ssp1);
fprintf (stderr, "\n");
}
#endif
*++yyvsp = yyval;
#ifdef YYLSP_NEEDED
yylsp++;
if (yylen == 0)
{
yylsp->first_line = yylloc.first_line;
yylsp->first_column = yylloc.first_column;
yylsp->last_line = (yylsp-1)->last_line;
yylsp->last_column = (yylsp-1)->last_column;
yylsp->text = 0;
}
else
{
yylsp->last_line = (yylsp+yylen-1)->last_line;
yylsp->last_column = (yylsp+yylen-1)->last_column;
}
#endif
/* Now "shift" the result of the reduction.
Determine what state that goes to,
based on the state we popped back to
and the rule number reduced by. */
yyn = yyr1[yyn];
yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
yystate = yytable[yystate];
else
yystate = yydefgoto[yyn - YYNTBASE];
goto yynewstate;
yyerrlab: /* here on detecting error */
if (! yyerrstatus)
/* If not already recovering from an error, report this error. */
{
++yynerrs;
#ifdef YYERROR_VERBOSE
yyn = yypact[yystate];
if (yyn > YYFLAG && yyn < YYLAST)
{
int size = 0;
char *msg;
int x, count;
count = 0;
for (x = 0; x < (sizeof(yytname) / sizeof(char *)); x++)
if (yycheck[x + yyn] == x)
size += strlen(yytname[x]) + 15, count++;
msg = (char *) xmalloc(size + 15);
strcpy(msg, "parse error");
if (count < 5)
{
count = 0;
for (x = 0; x < (sizeof(yytname) / sizeof(char *)); x++)
if (yycheck[x + yyn] == x)
{
strcat(msg, count == 0 ? ", expecting `" : " or `");
strcat(msg, yytname[x]);
strcat(msg, "'");
count++;
}
}
yyerror(msg);
free(msg);
}
else
#endif /* YYERROR_VERBOSE */
yyerror("parse error");
}
yyerrlab1: /* here on error raised explicitly by an action */
if (yyerrstatus == 3)
{
/* if just tried and failed to reuse lookahead token after an error, discard it. */
/* return failure if at end of input */
if (yychar == YYEOF)
YYABORT;
#if YYDEBUG != 0
if (yydebug)
fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
#endif
yychar = YYEMPTY;
}
/* Else will try to reuse lookahead token
after shifting the error token. */
yyerrstatus = 3; /* Each real token shifted decrements this */
goto yyerrhandle;
yyerrdefault: /* current state does not do anything special for the error token. */
#if 0
/* This is wrong; only states that explicitly want error tokens
should shift them. */
yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
if (yyn) goto yydefault;
#endif
yyerrpop: /* pop the current state because it cannot handle the error token */
if (yyssp == yyss) YYABORT;
yyvsp--;
yystate = *--yyssp;
#ifdef YYLSP_NEEDED
yylsp--;
#endif
#if YYDEBUG != 0
if (yydebug)
{
short *ssp1 = yyss - 1;
fprintf (stderr, "Error: state stack now");
while (ssp1 != yyssp)
fprintf (stderr, " %d", *++ssp1);
fprintf (stderr, "\n");
}
#endif
yyerrhandle:
yyn = yypact[yystate];
if (yyn == YYFLAG)
goto yyerrdefault;
yyn += YYTERROR;
if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
goto yyerrdefault;
yyn = yytable[yyn];
if (yyn < 0)
{
if (yyn == YYFLAG)
goto yyerrpop;
yyn = -yyn;
goto yyreduce;
}
else if (yyn == 0)
goto yyerrpop;
if (yyn == YYFINAL)
YYACCEPT;
#if YYDEBUG != 0
if (yydebug)
fprintf(stderr, "Shifting error token, ");
#endif
*++yyvsp = yylval;
#ifdef YYLSP_NEEDED
*++yylsp = yylloc;
#endif
yystate = yyn;
goto yynewstate;
}
+351
View File
@@ -0,0 +1,351 @@
/* Subroutines for bison
Copyright (C) 1984, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* subroutines of file LR0.c.
Entry points:
closure (items, n)
Given a vector of item numbers items, of length n,
set up ruleset and itemset to indicate what rules could be run
and which items could be accepted when those items are the active ones.
ruleset contains a bit for each rule. closure sets the bits
for all rules which could potentially describe the next input to be read.
itemset is a vector of item numbers; itemsetend points to just beyond the end
of the part of it that is significant.
closure places there the indices of all items which represent units of
input that could arrive next.
initialize_closure (n)
Allocates the itemset and ruleset vectors,
and precomputes useful data so that closure can be called.
n is the number of elements to allocate for itemset.
finalize_closure ()
Frees itemset, ruleset and internal data.
*/
#include <stdio.h>
#include "system.h"
#include "machine.h"
#include "new.h"
#include "gram.h"
extern short **derives;
extern char **tags;
void set_fderives();
void set_firsts();
extern void RTC();
short *itemset;
short *itemsetend;
static unsigned *ruleset;
/* internal data. See comments before set_fderives and set_firsts. */
static unsigned *fderives;
static unsigned *firsts;
/* number of words required to hold a bit for each rule */
static int rulesetsize;
/* number of words required to hold a bit for each variable */
static int varsetsize;
void
initialize_closure(n)
int n;
{
itemset = NEW2(n, short);
rulesetsize = WORDSIZE(nrules + 1);
ruleset = NEW2(rulesetsize, unsigned);
set_fderives();
}
/* set fderives to an nvars by nrules matrix of bits
indicating which rules can help derive the beginning of the data
for each nonterminal. For example, if symbol 5 can be derived as
the sequence of symbols 8 3 20, and one of the rules for deriving
symbol 8 is rule 4, then the [5 - ntokens, 4] bit in fderives is set. */
void
set_fderives()
{
register unsigned *rrow;
register unsigned *vrow;
register int j;
register unsigned cword;
register short *rp;
register int b;
int ruleno;
int i;
fderives = NEW2(nvars * rulesetsize, unsigned) - ntokens * rulesetsize;
set_firsts();
rrow = fderives + ntokens * rulesetsize;
for (i = ntokens; i < nsyms; i++)
{
vrow = firsts + ((i - ntokens) * varsetsize);
cword = *vrow++;
b = 0;
for (j = ntokens; j < nsyms; j++)
{
if (cword & (1 << b))
{
rp = derives[j];
while ((ruleno = *rp++) > 0)
{
SETBIT(rrow, ruleno);
}
}
b++;
if (b >= BITS_PER_WORD && j + 1 < nsyms)
{
cword = *vrow++;
b = 0;
}
}
rrow += rulesetsize;
}
#ifdef DEBUG
print_fderives();
#endif
FREE(firsts);
}
/* set firsts to be an nvars by nvars bit matrix indicating which items
can represent the beginning of the input corresponding to which other items.
For example, if some rule expands symbol 5 into the sequence of symbols 8 3 20,
the symbol 8 can be the beginning of the data for symbol 5,
so the bit [8 - ntokens, 5 - ntokens] in firsts is set. */
void
set_firsts()
{
register unsigned *row;
/* register int done; JF unused */
register int symbol;
register short *sp;
register int rowsize;
int i;
varsetsize = rowsize = WORDSIZE(nvars);
firsts = NEW2(nvars * rowsize, unsigned);
row = firsts;
for (i = ntokens; i < nsyms; i++)
{
sp = derives[i];
while (*sp >= 0)
{
symbol = ritem[rrhs[*sp++]];
if (ISVAR(symbol))
{
symbol -= ntokens;
SETBIT(row, symbol);
}
}
row += rowsize;
}
RTC(firsts, nvars);
#ifdef DEBUG
print_firsts();
#endif
}
void
closure(core, n)
short *core;
int n;
{
register int ruleno;
register unsigned word;
register short *csp;
register unsigned *dsp;
register unsigned *rsp;
short *csend;
unsigned *rsend;
int symbol;
int itemno;
rsp = ruleset;
rsend = ruleset + rulesetsize;
csend = core + n;
if (n == 0)
{
dsp = fderives + start_symbol * rulesetsize;
while (rsp < rsend)
*rsp++ = *dsp++;
}
else
{
while (rsp < rsend)
*rsp++ = 0;
csp = core;
while (csp < csend)
{
symbol = ritem[*csp++];
if (ISVAR(symbol))
{
dsp = fderives + symbol * rulesetsize;
rsp = ruleset;
while (rsp < rsend)
*rsp++ |= *dsp++;
}
}
}
ruleno = 0;
itemsetend = itemset;
csp = core;
rsp = ruleset;
while (rsp < rsend)
{
word = *rsp++;
if (word == 0)
{
ruleno += BITS_PER_WORD;
}
else
{
register int b;
for (b = 0; b < BITS_PER_WORD; b++)
{
if (word & (1 << b))
{
itemno = rrhs[ruleno];
while (csp < csend && *csp < itemno)
*itemsetend++ = *csp++;
*itemsetend++ = itemno;
}
ruleno++;
}
}
}
while (csp < csend)
*itemsetend++ = *csp++;
#ifdef DEBUG
print_closure(n);
#endif
}
void
finalize_closure()
{
FREE(itemset);
FREE(ruleset);
FREE(fderives + ntokens * rulesetsize);
}
#ifdef DEBUG
print_closure(n)
int n;
{
register short *isp;
printf("\n\nn = %d\n\n", n);
for (isp = itemset; isp < itemsetend; isp++)
printf(" %d\n", *isp);
}
print_firsts()
{
register int i;
register int j;
register unsigned *rowp;
printf("\n\n\nFIRSTS\n\n");
for (i = ntokens; i < nsyms; i++)
{
printf("\n\n%s firsts\n\n", tags[i]);
rowp = firsts + ((i - ntokens) * varsetsize);
for (j = 0; j < nvars; j++)
if (BITISSET (rowp, j))
printf(" %s\n", tags[j + ntokens]);
}
}
print_fderives()
{
register int i;
register int j;
register unsigned *rp;
printf("\n\n\nFDERIVES\n");
for (i = ntokens; i < nsyms; i++)
{
printf("\n\n%s derives\n\n", tags[i]);
rp = fderives + i * rulesetsize;
for (j = 0; j <= nrules; j++)
if (BITISSET (rp, j))
printf(" %d\n", j);
}
fflush(stdout);
}
#endif
+773
View File
@@ -0,0 +1,773 @@
/* Find and resolve or report look-ahead conflicts for bison,
Copyright (C) 1984, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef _AIX
#pragma alloca
#endif
#include <stdio.h>
#include "system.h"
#include "machine.h"
#include "new.h"
#include "files.h"
#include "gram.h"
#include "state.h"
#if defined(STDC_HEADERS) || defined(__GNU_LIBRARY__)
#define bcopy(s, d, n) memcpy ((d), (s), (n))
#else
#ifdef USG
#include <memory.h>
#define bcopy(src, dst, num) memcpy((dst), (src), (num))
#endif
#endif
#ifdef __GNUC__
#define alloca __builtin_alloca
#else
#ifdef sparc
#include <alloca.h>
#else
#ifndef _AIX
extern char *alloca ();
#endif
#endif
#endif
extern char **tags;
extern int tokensetsize;
extern char *consistent;
extern short *accessing_symbol;
extern shifts **shift_table;
extern unsigned *LA;
extern short *LAruleno;
extern short *lookaheads;
extern int verboseflag;
void set_conflicts();
void resolve_sr_conflict();
void flush_shift();
void log_resolution();
void total_conflicts();
void count_sr_conflicts();
void count_rr_conflicts();
char any_conflicts;
char *conflicts;
errs **err_table;
int expected_conflicts;
static unsigned *shiftset;
static unsigned *lookaheadset;
static int src_total;
static int rrc_total;
static int src_count;
static int rrc_count;
void
initialize_conflicts()
{
register int i;
/* register errs *sp; JF unused */
conflicts = NEW2(nstates, char);
shiftset = NEW2(tokensetsize, unsigned);
lookaheadset = NEW2(tokensetsize, unsigned);
err_table = NEW2(nstates, errs *);
any_conflicts = 0;
for (i = 0; i < nstates; i++)
set_conflicts(i);
}
void
set_conflicts(state)
int state;
{
register int i;
register int k;
register shifts *shiftp;
register unsigned *fp2;
register unsigned *fp3;
register unsigned *fp4;
register unsigned *fp1;
register int symbol;
if (consistent[state]) return;
for (i = 0; i < tokensetsize; i++)
lookaheadset[i] = 0;
shiftp = shift_table[state];
if (shiftp)
{
k = shiftp->nshifts;
for (i = 0; i < k; i++)
{
symbol = accessing_symbol[shiftp->shifts[i]];
if (ISVAR(symbol)) break;
SETBIT(lookaheadset, symbol);
}
}
k = lookaheads[state + 1];
fp4 = lookaheadset + tokensetsize;
/* loop over all rules which require lookahead in this state */
/* first check for shift-reduce conflict, and try to resolve using precedence */
for (i = lookaheads[state]; i < k; i++)
if (rprec[LAruleno[i]])
{
fp1 = LA + i * tokensetsize;
fp2 = fp1;
fp3 = lookaheadset;
while (fp3 < fp4)
{
if (*fp2++ & *fp3++)
{
resolve_sr_conflict(state, i);
break;
}
}
}
/* loop over all rules which require lookahead in this state */
/* Check for conflicts not resolved above. */
for (i = lookaheads[state]; i < k; i++)
{
fp1 = LA + i * tokensetsize;
fp2 = fp1;
fp3 = lookaheadset;
while (fp3 < fp4)
{
if (*fp2++ & *fp3++)
{
conflicts[state] = 1;
any_conflicts = 1;
}
}
fp2 = fp1;
fp3 = lookaheadset;
while (fp3 < fp4)
*fp3++ |= *fp2++;
}
}
/* Attempt to resolve shift-reduce conflict for one rule
by means of precedence declarations.
It has already been checked that the rule has a precedence.
A conflict is resolved by modifying the shift or reduce tables
so that there is no longer a conflict. */
void
resolve_sr_conflict(state, lookaheadnum)
int state;
int lookaheadnum;
{
register int i;
register int mask;
register unsigned *fp1;
register unsigned *fp2;
register int redprec;
errs *errp = (errs *) alloca (sizeof(errs) + ntokens * sizeof(short));
short *errtokens = errp->errs;
/* find the rule to reduce by to get precedence of reduction */
redprec = rprec[LAruleno[lookaheadnum]];
mask = 1;
fp1 = LA + lookaheadnum * tokensetsize;
fp2 = lookaheadset;
for (i = 0; i < ntokens; i++)
{
if ((mask & *fp2 & *fp1) && sprec[i])
/* Shift-reduce conflict occurs for token number i
and it has a precedence.
The precedence of shifting is that of token i. */
{
if (sprec[i] < redprec)
{
if (verboseflag) log_resolution(state, lookaheadnum, i, "reduce");
*fp2 &= ~mask; /* flush the shift for this token */
flush_shift(state, i);
}
else if (sprec[i] > redprec)
{
if (verboseflag) log_resolution(state, lookaheadnum, i, "shift");
*fp1 &= ~mask; /* flush the reduce for this token */
}
else
{
/* Matching precedence levels.
For left association, keep only the reduction.
For right association, keep only the shift.
For nonassociation, keep neither. */
switch (sassoc[i])
{
case RIGHT_ASSOC:
if (verboseflag) log_resolution(state, lookaheadnum, i, "shift");
break;
case LEFT_ASSOC:
if (verboseflag) log_resolution(state, lookaheadnum, i, "reduce");
break;
case NON_ASSOC:
if (verboseflag) log_resolution(state, lookaheadnum, i, "an error");
break;
}
if (sassoc[i] != RIGHT_ASSOC)
{
*fp2 &= ~mask; /* flush the shift for this token */
flush_shift(state, i);
}
if (sassoc[i] != LEFT_ASSOC)
{
*fp1 &= ~mask; /* flush the reduce for this token */
}
if (sassoc[i] == NON_ASSOC)
{
/* Record an explicit error for this token. */
*errtokens++ = i;
}
}
}
mask <<= 1;
if (mask == 0)
{
mask = 1;
fp2++; fp1++;
}
}
errp->nerrs = errtokens - errp->errs;
if (errp->nerrs)
{
/* Some tokens have been explicitly made errors. Allocate
a permanent errs structure for this state, to record them. */
i = (char *) errtokens - (char *) errp;
err_table[state] = (errs *) mallocate ((unsigned int)i);
bcopy (errp, err_table[state], i);
}
else
err_table[state] = 0;
}
/* turn off the shift recorded for the specified token in the specified state.
Used when we resolve a shift-reduce conflict in favor of the reduction. */
void
flush_shift(state, token)
int state;
int token;
{
register shifts *shiftp;
register int k, i;
/* register unsigned symbol; JF unused */
shiftp = shift_table[state];
if (shiftp)
{
k = shiftp->nshifts;
for (i = 0; i < k; i++)
{
if (shiftp->shifts[i] && token == accessing_symbol[shiftp->shifts[i]])
(shiftp->shifts[i]) = 0;
}
}
}
void
log_resolution(state, LAno, token, resolution)
int state, LAno, token;
char *resolution;
{
fprintf(foutput,
"Conflict in state %d between rule %d and token %s resolved as %s.\n",
state, LAruleno[LAno], tags[token], resolution);
}
void
conflict_log()
{
register int i;
src_total = 0;
rrc_total = 0;
for (i = 0; i < nstates; i++)
{
if (conflicts[i])
{
count_sr_conflicts(i);
count_rr_conflicts(i);
src_total += src_count;
rrc_total += rrc_count;
}
}
total_conflicts();
}
void
verbose_conflict_log()
{
register int i;
src_total = 0;
rrc_total = 0;
for (i = 0; i < nstates; i++)
{
if (conflicts[i])
{
count_sr_conflicts(i);
count_rr_conflicts(i);
src_total += src_count;
rrc_total += rrc_count;
fprintf(foutput, "State %d contains", i);
if (src_count == 1)
fprintf(foutput, " 1 shift/reduce conflict");
else if (src_count > 1)
fprintf(foutput, " %d shift/reduce conflicts", src_count);
if (src_count > 0 && rrc_count > 0)
fprintf(foutput, " and");
if (rrc_count == 1)
fprintf(foutput, " 1 reduce/reduce conflict");
else if (rrc_count > 1)
fprintf(foutput, " %d reduce/reduce conflicts", rrc_count);
putc('.', foutput);
putc('\n', foutput);
}
}
total_conflicts();
}
void
total_conflicts()
{
extern int fixed_outfiles;
if (src_total == expected_conflicts && rrc_total == 0)
return;
if (fixed_outfiles)
{
/* If invoked under the name `yacc', use the output format
specified by POSIX. */
fprintf(stderr, "conflicts: ", infile);
if (src_total > 0)
fprintf(stderr, " %d shift/reduce", src_total);
if (src_total > 0 && rrc_total > 0)
fprintf(stderr, ",");
if (rrc_total > 0)
fprintf(stderr, " %d reduce/reduce", rrc_total);
putc('\n', stderr);
}
else
{
fprintf(stderr, "%s contains", infile);
if (src_total == 1)
fprintf(stderr, " 1 shift/reduce conflict");
else if (src_total > 1)
fprintf(stderr, " %d shift/reduce conflicts", src_total);
if (src_total > 0 && rrc_total > 0)
fprintf(stderr, " and");
if (rrc_total == 1)
fprintf(stderr, " 1 reduce/reduce conflict");
else if (rrc_total > 1)
fprintf(stderr, " %d reduce/reduce conflicts", rrc_total);
putc('.', stderr);
putc('\n', stderr);
}
}
void
count_sr_conflicts(state)
int state;
{
register int i;
register int k;
register int mask;
register shifts *shiftp;
register unsigned *fp1;
register unsigned *fp2;
register unsigned *fp3;
register int symbol;
src_count = 0;
shiftp = shift_table[state];
if (!shiftp) return;
for (i = 0; i < tokensetsize; i++)
{
shiftset[i] = 0;
lookaheadset[i] = 0;
}
k = shiftp->nshifts;
for (i = 0; i < k; i++)
{
if (! shiftp->shifts[i]) continue;
symbol = accessing_symbol[shiftp->shifts[i]];
if (ISVAR(symbol)) break;
SETBIT(shiftset, symbol);
}
k = lookaheads[state + 1];
fp3 = lookaheadset + tokensetsize;
for (i = lookaheads[state]; i < k; i++)
{
fp1 = LA + i * tokensetsize;
fp2 = lookaheadset;
while (fp2 < fp3)
*fp2++ |= *fp1++;
}
fp1 = shiftset;
fp2 = lookaheadset;
while (fp2 < fp3)
*fp2++ &= *fp1++;
mask = 1;
fp2 = lookaheadset;
for (i = 0; i < ntokens; i++)
{
if (mask & *fp2)
src_count++;
mask <<= 1;
if (mask == 0)
{
mask = 1;
fp2++;
}
}
}
void
count_rr_conflicts(state)
int state;
{
register int i;
register int j;
register int count;
register unsigned mask;
register unsigned *baseword;
register unsigned *wordp;
register int m;
register int n;
rrc_count = 0;
m = lookaheads[state];
n = lookaheads[state + 1];
if (n - m < 2) return;
mask = 1;
baseword = LA + m * tokensetsize;
for (i = 0; i < ntokens; i++)
{
wordp = baseword;
count = 0;
for (j = m; j < n; j++)
{
if (mask & *wordp)
count++;
wordp += tokensetsize;
}
if (count >= 2) rrc_count++;
mask <<= 1;
if (mask == 0)
{
mask = 1;
baseword++;
}
}
}
void
print_reductions(state)
int state;
{
register int i;
register int j;
register int k;
register unsigned *fp1;
register unsigned *fp2;
register unsigned *fp3;
register unsigned *fp4;
register int rule;
register int symbol;
register unsigned mask;
register int m;
register int n;
register int default_LA;
register int default_rule;
register int cmax;
register int count;
register shifts *shiftp;
register errs *errp;
int nodefault = 0;
for (i = 0; i < tokensetsize; i++)
shiftset[i] = 0;
shiftp = shift_table[state];
if (shiftp)
{
k = shiftp->nshifts;
for (i = 0; i < k; i++)
{
if (! shiftp->shifts[i]) continue;
symbol = accessing_symbol[shiftp->shifts[i]];
if (ISVAR(symbol)) break;
/* if this state has a shift for the error token,
don't use a default rule. */
if (symbol == error_token_number) nodefault = 1;
SETBIT(shiftset, symbol);
}
}
errp = err_table[state];
if (errp)
{
k = errp->nerrs;
for (i = 0; i < k; i++)
{
if (! errp->errs[i]) continue;
symbol = errp->errs[i];
SETBIT(shiftset, symbol);
}
}
m = lookaheads[state];
n = lookaheads[state + 1];
if (n - m == 1 && ! nodefault)
{
default_rule = LAruleno[m];
fp1 = LA + m * tokensetsize;
fp2 = shiftset;
fp3 = lookaheadset;
fp4 = lookaheadset + tokensetsize;
while (fp3 < fp4)
*fp3++ = *fp1++ & *fp2++;
mask = 1;
fp3 = lookaheadset;
for (i = 0; i < ntokens; i++)
{
if (mask & *fp3)
fprintf(foutput, " %-4s\t[reduce using rule %d (%s)]\n",
tags[i], default_rule, tags[rlhs[default_rule]]);
mask <<= 1;
if (mask == 0)
{
mask = 1;
fp3++;
}
}
fprintf(foutput, " $default\treduce using rule %d (%s)\n\n",
default_rule, tags[rlhs[default_rule]]);
}
else if (n - m >= 1)
{
cmax = 0;
default_LA = -1;
fp4 = lookaheadset + tokensetsize;
if (! nodefault)
for (i = m; i < n; i++)
{
fp1 = LA + i * tokensetsize;
fp2 = shiftset;
fp3 = lookaheadset;
while (fp3 < fp4)
*fp3++ = *fp1++ & ( ~ (*fp2++));
count = 0;
mask = 1;
fp3 = lookaheadset;
for (j = 0; j < ntokens; j++)
{
if (mask & *fp3)
count++;
mask <<= 1;
if (mask == 0)
{
mask = 1;
fp3++;
}
}
if (count > cmax)
{
cmax = count;
default_LA = i;
default_rule = LAruleno[i];
}
fp2 = shiftset;
fp3 = lookaheadset;
while (fp3 < fp4)
*fp2++ |= *fp3++;
}
for (i = 0; i < tokensetsize; i++)
shiftset[i] = 0;
if (shiftp)
{
k = shiftp->nshifts;
for (i = 0; i < k; i++)
{
if (! shiftp->shifts[i]) continue;
symbol = accessing_symbol[shiftp->shifts[i]];
if (ISVAR(symbol)) break;
SETBIT(shiftset, symbol);
}
}
mask = 1;
fp1 = LA + m * tokensetsize;
fp2 = shiftset;
for (i = 0; i < ntokens; i++)
{
int defaulted = 0;
if (mask & *fp2)
count = 1;
else
count = 0;
fp3 = fp1;
for (j = m; j < n; j++)
{
if (mask & *fp3)
{
if (count == 0)
{
if (j != default_LA)
{
rule = LAruleno[j];
fprintf(foutput, " %-4s\treduce using rule %d (%s)\n",
tags[i], rule, tags[rlhs[rule]]);
}
else defaulted = 1;
count++;
}
else
{
if (defaulted)
{
rule = LAruleno[default_LA];
fprintf(foutput, " %-4s\treduce using rule %d (%s)\n",
tags[i], rule, tags[rlhs[rule]]);
defaulted = 0;
}
rule = LAruleno[j];
fprintf(foutput, " %-4s\t[reduce using rule %d (%s)]\n",
tags[i], rule, tags[rlhs[rule]]);
}
}
fp3 += tokensetsize;
}
mask <<= 1;
if (mask == 0)
{
mask = 1;
fp1++;
}
}
if (default_LA >= 0)
{
fprintf(foutput, " $default\treduce using rule %d (%s)\n",
default_rule, tags[rlhs[default_rule]]);
}
putc('\n', foutput);
}
}
void
finalize_conflicts()
{
FREE(conflicts);
FREE(shiftset);
FREE(lookaheadset);
}
+118
View File
@@ -0,0 +1,118 @@
/* Match rules with nonterminals for bison,
Copyright (C) 1984, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* set_derives finds, for each variable (nonterminal), which rules can derive it.
It sets up the value of derives so that
derives[i - ntokens] points to a vector of rule numbers,
terminated with -1. */
#include <stdio.h>
#include "system.h"
#include "new.h"
#include "types.h"
#include "gram.h"
short **derives;
void
set_derives()
{
register int i;
register int lhs;
register shorts *p;
register short *q;
register shorts **dset;
register shorts *delts;
dset = NEW2(nvars, shorts *) - ntokens;
delts = NEW2(nrules + 1, shorts);
p = delts;
for (i = nrules; i > 0; i--)
{
lhs = rlhs[i];
if (lhs >= 0)
{
p->next = dset[lhs];
p->value = i;
dset[lhs] = p;
p++;
}
}
derives = NEW2(nvars, short *) - ntokens;
q = NEW2(nvars + nrules, short);
for (i = ntokens; i < nsyms; i++)
{
derives[i] = q;
p = dset[i];
while (p)
{
*q++ = p->value;
p = p->next;
}
*q++ = -1;
}
#ifdef DEBUG
print_derives();
#endif
FREE(dset + ntokens);
FREE(delts);
}
void
free_derives()
{
FREE(derives[ntokens]);
FREE(derives + ntokens);
}
#ifdef DEBUG
print_derives()
{
register int i;
register short *sp;
extern char **tags;
printf("\n\n\nDERIVES\n\n");
for (i = ntokens; i < nsyms; i++)
{
printf("%s derives", tags[i]);
for (sp = derives[i]; *sp > 0; sp++)
{
printf(" %d", *sp);
}
putchar('\n');
}
putchar('\n');
}
#endif
+376
View File
@@ -0,0 +1,376 @@
/* Open and close files for bison,
Copyright (C) 1984, 1986, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef VMS
#include <ssdef.h>
#define unlink delete
#ifndef XPFILE
#define XPFILE "GNU_BISON:[000000]BISON.SIMPLE"
#endif
#ifndef XPFILE1
#define XPFILE1 "GNU_BISON:[000000]BISON.HAIRY"
#endif
#endif
#include <stdio.h>
#include "system.h"
#include "files.h"
#include "new.h"
#include "gram.h"
FILE *finput = NULL;
FILE *foutput = NULL;
FILE *fdefines = NULL;
FILE *ftable = NULL;
FILE *fattrs = NULL;
FILE *fguard = NULL;
FILE *faction = NULL;
FILE *fparser = NULL;
/* File name specified with -o for the output file, or 0 if no -o. */
char *spec_outfile;
char *infile;
char *outfile;
char *defsfile;
char *tabfile;
char *attrsfile;
char *guardfile;
char *actfile;
char *tmpattrsfile;
char *tmptabfile;
extern char *mktemp(); /* So the compiler won't complain */
extern char *getenv();
extern void perror();
extern void exit();
FILE *tryopen(); /* This might be a good idea */
void done();
extern char *program_name;
extern int verboseflag;
extern int definesflag;
int fixed_outfiles = 0;
char*
stringappend(string1, end1, string2)
char *string1;
int end1;
char *string2;
{
register char *ostring;
register char *cp, *cp1;
register int i;
cp = string2; i = 0;
while (*cp++) i++;
ostring = NEW2(i+end1+1, char);
cp = ostring;
cp1 = string1;
for (i = 0; i < end1; i++)
*cp++ = *cp1++;
cp1 = string2;
while (*cp++ = *cp1++) ;
return ostring;
}
/* JF this has been hacked to death. Nowaday it sets up the file names for
the output files, and opens the tmp files and the parser */
void
openfiles()
{
char *name_base;
register char *cp;
char *filename;
int base_length;
int short_base_length;
#ifdef VMS
char *tmp_base = "sys$scratch:b_";
#else
char *tmp_base = "/tmp/b.";
#endif
int tmp_len;
#ifdef MSDOS
tmp_base = getenv ("TMP");
if (tmp_base == 0)
tmp_base = "";
strlwr (infile);
#endif /* MSDOS */
tmp_len = strlen (tmp_base);
if (spec_outfile)
{
/* -o was specified. The precise -o name will be used for ftable.
For other output files, remove the ".c" or ".tab.c" suffix. */
name_base = spec_outfile;
#ifdef MSDOS
strlwr (name_base);
#endif /* MSDOS */
/* BASE_LENGTH includes ".tab" but not ".c". */
base_length = strlen (name_base);
if (!strcmp (name_base + base_length - 2, ".c"))
base_length -= 2;
/* SHORT_BASE_LENGTH includes neither ".tab" nor ".c". */
short_base_length = base_length;
if (!strncmp (name_base + short_base_length - 4, ".tab", 4))
short_base_length -= 4;
else if (!strncmp (name_base + short_base_length - 4, "_tab", 4))
short_base_length -= 4;
}
else if (spec_file_prefix)
{
/* -b was specified. Construct names from it. */
/* SHORT_BASE_LENGTH includes neither ".tab" nor ".c". */
short_base_length = strlen (spec_file_prefix);
/* Count room for `.tab'. */
base_length = short_base_length + 4;
name_base = (char *) mallocate (base_length + 1);
/* Append `.tab'. */
strcpy (name_base, spec_file_prefix);
strcat (name_base, ".tab");
#ifdef MSDOS
strlwr (name_base);
#endif /* MSDOS */
}
else
{
/* -o was not specified; compute output file name from input
or use y.tab.c, etc., if -y was specified. */
name_base = fixed_outfiles ? "y.y" : infile;
/* BASE_LENGTH gets length of NAME_BASE, sans ".y" suffix if any. */
base_length = strlen (name_base);
if (!strcmp (name_base + base_length - 2, ".y"))
base_length -= 2;
short_base_length = base_length;
#ifdef VMS
name_base = stringappend(name_base, short_base_length, "_tab");
#else
#ifdef MSDOS
name_base = stringappend(name_base, short_base_length, "_tab");
#else
name_base = stringappend(name_base, short_base_length, ".tab");
#endif /* not MSDOS */
#endif
base_length = short_base_length + 4;
}
finput = tryopen(infile, "r");
filename = getenv("BISON_SIMPLE");
#ifdef MSDOS
/* File doesn't exist in current directory; try in INIT directory. */
cp = getenv("INIT");
if (filename == 0 && cp != 0)
{
filename = malloc(strlen(cp) + strlen(PFILE) + 2);
strcpy(filename, cp);
cp = filename + strlen(filename);
*cp++ = '/';
strcpy(cp, PFILE);
}
#endif /* MSDOS */
fparser = tryopen(filename ? filename : PFILE, "r");
if (verboseflag)
{
#ifdef MSDOS
outfile = stringappend(name_base, short_base_length, ".out");
#else
if (spec_name_prefix)
outfile = stringappend(name_base, short_base_length, ".out");
else
outfile = stringappend(name_base, short_base_length, ".output");
#endif
foutput = tryopen(outfile, "w");
}
if (definesflag)
{
defsfile = stringappend(name_base, base_length, ".h");
fdefines = tryopen(defsfile, "w");
}
#ifdef MSDOS
actfile = mktemp(stringappend(tmp_base, tmp_len, "acXXXXXX"));
tmpattrsfile = mktemp(stringappend(tmp_base, tmp_len, "atXXXXXX"));
tmptabfile = mktemp(stringappend(tmp_base, tmp_len, "taXXXXXX"));
#else
actfile = mktemp(stringappend(tmp_base, tmp_len, "act.XXXXXX"));
tmpattrsfile = mktemp(stringappend(tmp_base, tmp_len, "attrs.XXXXXX"));
tmptabfile = mktemp(stringappend(tmp_base, tmp_len, "tab.XXXXXX"));
#endif /* not MSDOS */
faction = tryopen(actfile, "w+");
fattrs = tryopen(tmpattrsfile,"w+");
ftable = tryopen(tmptabfile, "w+");
#ifndef MSDOS
unlink(actfile);
unlink(tmpattrsfile);
unlink(tmptabfile);
#endif
/* These are opened by `done' or `open_extra_files', if at all */
if (spec_outfile)
tabfile = spec_outfile;
else
tabfile = stringappend(name_base, base_length, ".c");
#ifdef VMS
attrsfile = stringappend(name_base, short_base_length, "_stype.h");
guardfile = stringappend(name_base, short_base_length, "_guard.c");
#else
#ifdef MSDOS
attrsfile = stringappend(name_base, short_base_length, ".sth");
guardfile = stringappend(name_base, short_base_length, ".guc");
#else
attrsfile = stringappend(name_base, short_base_length, ".stype.h");
guardfile = stringappend(name_base, short_base_length, ".guard.c");
#endif /* not MSDOS */
#endif /* not VMS */
}
/* open the output files needed only for the semantic parser.
This is done when %semantic_parser is seen in the declarations section. */
void
open_extra_files()
{
FILE *ftmp;
int c;
char *filename, *cp;
fclose(fparser);
filename = (char *) getenv ("BISON_HAIRY");
#ifdef MSDOS
/* File doesn't exist in current directory; try in INIT directory. */
cp = getenv("INIT");
if (filename == 0 && cp != 0)
{
filename = malloc(strlen(cp) + strlen(PFILE1) + 2);
strcpy(filename, cp);
cp = filename + strlen(filename);
*cp++ = '/';
strcpy(cp, PFILE1);
}
#endif
fparser= tryopen(filename ? filename : PFILE1, "r");
/* JF change from inline attrs file to separate one */
ftmp = tryopen(attrsfile, "w");
rewind(fattrs);
while((c=getc(fattrs))!=EOF) /* Thank god for buffering */
putc(c,ftmp);
fclose(fattrs);
fattrs=ftmp;
fguard = tryopen(guardfile, "w");
}
/* JF to make file opening easier. This func tries to open file
NAME with mode MODE, and prints an error message if it fails. */
FILE *
tryopen(name, mode)
char *name;
char *mode;
{
FILE *ptr;
ptr = fopen(name, mode);
if (ptr == NULL)
{
fprintf(stderr, "%s: ", program_name);
perror(name);
done(2);
}
return ptr;
}
void
done(k)
int k;
{
if (faction)
fclose(faction);
if (fattrs)
fclose(fattrs);
if (fguard)
fclose(fguard);
if (finput)
fclose(finput);
if (fparser)
fclose(fparser);
if (foutput)
fclose(foutput);
/* JF write out the output file */
if (k == 0 && ftable)
{
FILE *ftmp;
register int c;
ftmp=tryopen(tabfile, "w");
rewind(ftable);
while((c=getc(ftable)) != EOF)
putc(c,ftmp);
fclose(ftmp);
fclose(ftable);
}
#ifdef VMS
if (faction)
delete(actfile);
if (fattrs)
delete(tmpattrsfile);
if (ftable)
delete(tmptabfile);
if (k==0) sys$exit(SS$_NORMAL);
sys$exit(SS$_ABORT);
#else
#ifdef MSDOS
if (actfile) unlink(actfile);
if (tmpattrsfile) unlink(tmpattrsfile);
if (tmptabfile) unlink(tmptabfile);
#endif /* MSDOS */
exit(k);
#endif /* not VMS */
}
+52
View File
@@ -0,0 +1,52 @@
/* File names and variables for bison,
Copyright (C) 1984, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* These two should be pathnames for opening the sample parser files.
When bison is installed, they should be absolute pathnames.
XPFILE1 and XPFILE2 normally come from the Makefile. */
#define PFILE XPFILE /* Simple parser */
#define PFILE1 XPFILE1 /* Semantic parser */
extern FILE *finput; /* read grammar specifications */
extern FILE *foutput; /* optionally output messages describing the actions taken */
extern FILE *fdefines; /* optionally output #define's for token numbers. */
extern FILE *ftable; /* output the tables and the parser */
extern FILE *fattrs; /* if semantic parser, output a .h file that defines YYSTYPE */
/* and also contains all the %{ ... %} definitions. */
extern FILE *fguard; /* if semantic parser, output yyguard, containing all the guard code */
extern FILE *faction; /* output all the action code; precise form depends on which parser */
extern FILE *fparser; /* read the parser to copy into ftable */
/* File name specified with -o for the output file, or 0 if no -o. */
extern char *spec_outfile;
extern char *spec_name_prefix; /* for -a, from getargs.c */
/* File name pfx specified with -b, or 0 if no -b. */
extern char *spec_file_prefix;
extern char *infile;
extern char *outfile;
extern char *defsfile;
extern char *tabfile;
extern char *attrsfile;
extern char *guardfile;
extern char *actfile;
+130
View File
@@ -0,0 +1,130 @@
/* Parse command line arguments for bison,
Copyright (C) 1984, 1986, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "getopt.h"
#include "system.h"
#include "files.h"
int verboseflag;
int definesflag;
int debugflag;
int nolinesflag;
char *spec_name_prefix; /* for -p. */
char *spec_file_prefix; /* for -b. */
extern int fixed_outfiles;/* for -y */
extern void fatal();
struct option longopts[] =
{
{"debug", 0, &debugflag, 1},
{"defines", 0, &definesflag, 1},
{"file-prefix", 1, 0, 'b'},
{"fixed-output-files", 0, &fixed_outfiles, 1},
{"name-prefix", 1, 0, 'a'},
{"no-lines", 0, &nolinesflag, 1},
{"output-file", 1, 0, 'o'},
{"verbose", 0, &verboseflag, 1},
{"version", 0, 0, 'V'},
{"yacc", 0, &fixed_outfiles, 1},
{0, 0, 0, 0}
};
void
getargs(argc, argv)
int argc;
char *argv[];
{
register int c;
int longind;
extern char *program_name;
extern char *version_string;
verboseflag = 0;
definesflag = 0;
debugflag = 0;
fixed_outfiles = 0;
while ((c = getopt_long (argc, argv, "yvdltVo:b:p:", longopts, &longind))
!= EOF)
{
if (c == 0 && longopts[longind].flag == 0)
c = longopts[longind].val;
switch (c)
{
case 'y':
fixed_outfiles = 1;
break;
case 'V':
printf("%s", version_string);
break;
case 'v':
verboseflag = 1;
break;
case 'd':
definesflag = 1;
break;
case 'l':
nolinesflag = 1;
break;
case 't':
debugflag = 1;
break;
case 'o':
spec_outfile = optarg;
break;
case 'b':
spec_file_prefix = optarg;
break;
case 'p':
spec_name_prefix = optarg;
break;
default:
fprintf (stderr, "\
Usage: %s [-dltvyV] [-b file-prefix] [-o outfile] [-p name-prefix]\n\
[--debug] [--defines] [--fixed-output-files] [--no-lines]\n\
[--verbose] [--version] [--yacc]\n\
[--file-prefix=prefix] [--name-prefix=prefix]\n\
[--output-file=outfile] grammar-file\n",
program_name);
exit (1);
}
}
if (optind == argc)
{
fprintf(stderr, "%s: no grammar file given\n", program_name);
exit(1);
}
if (optind < argc - 1)
fprintf(stderr, "%s: warning: extra arguments ignored\n", program_name);
infile = argv[optind];
}
+675
View File
@@ -0,0 +1,675 @@
/* Getopt for GNU.
NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
before changing it!
Copyright (C) 1987, 88, 89, 90, 91, 1992 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* AIX requires this to be the first thing in the file. */
#ifdef __GNUC__
#define alloca __builtin_alloca
#else /* not __GNUC__ */
#ifdef sparc
#include <alloca.h>
#else
#ifdef _AIX
#pragma alloca
#else
char *alloca ();
#endif
#endif /* sparc */
#endif /* not __GNUC__ */
#ifdef LIBC
/* For when compiled as part of the GNU C library. */
#include <ansidecl.h>
#endif
#include <stdio.h>
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
#undef alloca
#include <stdlib.h>
#else /* Not GNU C library. */
#define __alloca alloca
#endif /* GNU C library. */
#ifndef __STDC__
#define const
#endif
/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
long-named option. Because this is not POSIX.2 compliant, it is
being phased out. */
#define GETOPT_COMPAT
/* This version of `getopt' appears to the caller like standard Unix `getopt'
but it behaves differently for the user, since it allows the user
to intersperse the options with the other arguments.
As `getopt' works, it permutes the elements of ARGV so that,
when it is done, all the options precede everything else. Thus
all application programs are extended to handle flexible argument order.
Setting the environment variable POSIXLY_CORRECT disables permutation.
Then the behavior is completely standard.
GNU application programs can use a third alternative mode in which
they can distinguish the relative order of options and other arguments. */
#include "getopt.h"
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
char *optarg = 0;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
int optind = 0;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
static char *nextchar;
/* Callers store zero here to inhibit the error message
for unrecognized options. */
int opterr = 1;
/* Describe how to deal with options that follow non-option ARGV-elements.
If the caller did not specify anything,
the default is REQUIRE_ORDER if the environment variable
POSIXLY_CORRECT is defined, PERMUTE otherwise.
REQUIRE_ORDER means don't recognize them as options;
stop option processing when the first non-option is seen.
This is what Unix does.
This mode of operation is selected by either setting the environment
variable POSIXLY_CORRECT, or using `+' as the first character
of the list of option characters.
PERMUTE is the default. We permute the contents of ARGV as we scan,
so that eventually all the non-options are at the end. This allows options
to be given in any order, even with programs that were not written to
expect this.
RETURN_IN_ORDER is an option available to programs that were written
to expect options and other ARGV-elements in any order and that care about
the ordering of the two. We describe each non-option ARGV-element
as if it were the argument of an option with character code 1.
Using `-' as the first character of the list of option characters
selects this mode of operation.
The special argument `--' forces an end of option-scanning regardless
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
`--' can cause `getopt' to return EOF with `optind' != ARGC. */
static enum
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering;
#ifdef __GNU_LIBRARY__
#include <string.h>
#define my_index strchr
#define my_bcopy(src, dst, n) memcpy ((dst), (src), (n))
#else
/* Avoid depending on library functions or files
whose names are inconsistent. */
char *getenv ();
static char *
my_index (string, chr)
char *string;
int chr;
{
while (*string)
{
if (*string == chr)
return string;
string++;
}
return 0;
}
static void
my_bcopy (from, to, size)
char *from, *to;
int size;
{
int i;
for (i = 0; i < size; i++)
to[i] = from[i];
}
#endif /* GNU C library. */
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
been skipped. `first_nonopt' is the index in ARGV of the first of them;
`last_nonopt' is the index after the last of them. */
static int first_nonopt;
static int last_nonopt;
/* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt)
which contains all the non-options that have been skipped so far.
The other is elements [last_nonopt,optind), which contains all
the options processed since those non-options were skipped.
`first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */
static void
exchange (argv)
char **argv;
{
int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *);
char **temp = (char **) __alloca (nonopts_size);
/* Interchange the two blocks of data in ARGV. */
my_bcopy (&argv[first_nonopt], temp, nonopts_size);
my_bcopy (&argv[last_nonopt], &argv[first_nonopt],
(optind - last_nonopt) * sizeof (char *));
my_bcopy (temp, &argv[first_nonopt + optind - last_nonopt], nonopts_size);
/* Update records for the slots the non-options now occupy. */
first_nonopt += (optind - last_nonopt);
last_nonopt = optind;
}
/* Scan elements of ARGV (whose length is ARGC) for option characters
given in OPTSTRING.
If an element of ARGV starts with '-', and is not exactly "-" or "--",
then it is an option element. The characters of this element
(aside from the initial '-') are option characters. If `getopt'
is called repeatedly, it returns successively each of the option characters
from each of the option elements.
If `getopt' finds another option character, it returns that character,
updating `optind' and `nextchar' so that the next call to `getopt' can
resume the scan with the following option character or ARGV-element.
If there are no more option characters, `getopt' returns `EOF'.
Then `optind' is the index in ARGV of the first ARGV-element
that is not an option. (The ARGV-elements have been permuted
so that those that are not options now come last.)
OPTSTRING is a string containing the legitimate option characters.
If an option character is seen that is not listed in OPTSTRING,
return '?' after printing an error message. If you set `opterr' to
zero, the error message is suppressed but we still return '?'.
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
so the following text in the same ARGV-element, or the text of the following
ARGV-element, is returned in `optarg'. Two colons mean an option that
wants an optional arg; if there is text in the current ARGV-element,
it is returned in `optarg', otherwise `optarg' is set to zero.
If OPTSTRING starts with `-' or `+', it requests different methods of
handling the non-option ARGV-elements.
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
Long-named options begin with `--' instead of `-'.
Their names may be abbreviated as long as the abbreviation is unique
or is an exact match for some defined option. If they have an
argument, it follows the option name in the same ARGV-element, separated
from the option name by a `=', or else the in next ARGV-element.
When `getopt' finds a long-named option, it returns 0 if that option's
`flag' field is nonzero, the value of the option's `val' field
if the `flag' field is zero.
The elements of ARGV aren't really const, because we permute them.
But we pretend they're const in the prototype to be compatible
with other systems.
LONGOPTS is a vector of `struct option' terminated by an
element containing a name which is zero.
LONGIND returns the index in LONGOPT of the long-named option found.
It is only valid when a long-named option has been found by the most
recent call.
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
long-named options. */
int
_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int argc;
char *const *argv;
const char *optstring;
const struct option *longopts;
int *longind;
int long_only;
{
int option_index;
optarg = 0;
/* Initialize the internal data when the first call is made.
Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */
if (optind == 0)
{
first_nonopt = last_nonopt = optind = 1;
nextchar = NULL;
/* Determine how to handle the ordering of options and nonoptions. */
if (optstring[0] == '-')
{
ordering = RETURN_IN_ORDER;
++optstring;
}
else if (optstring[0] == '+')
{
ordering = REQUIRE_ORDER;
++optstring;
}
else if (getenv ("POSIXLY_CORRECT") != NULL)
ordering = REQUIRE_ORDER;
else
ordering = PERMUTE;
}
if (nextchar == NULL || *nextchar == '\0')
{
if (ordering == PERMUTE)
{
/* If we have just processed some options following some non-options,
exchange them so that the options come first. */
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (last_nonopt != optind)
first_nonopt = optind;
/* Now skip any additional non-options
and extend the range of non-options previously skipped. */
while (optind < argc
&& (argv[optind][0] != '-' || argv[optind][1] == '\0')
#ifdef GETOPT_COMPAT
&& (longopts == NULL
|| argv[optind][0] != '+' || argv[optind][1] == '\0')
#endif /* GETOPT_COMPAT */
)
optind++;
last_nonopt = optind;
}
/* Special ARGV-element `--' means premature end of options.
Skip it like a null option,
then exchange with previous non-options as if it were an option,
then skip everything else like a non-option. */
if (optind != argc && !strcmp (argv[optind], "--"))
{
optind++;
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (first_nonopt == last_nonopt)
first_nonopt = optind;
last_nonopt = argc;
optind = argc;
}
/* If we have done all the ARGV-elements, stop the scan
and back over any non-options that we skipped and permuted. */
if (optind == argc)
{
/* Set the next-arg-index to point at the non-options
that we previously skipped, so the caller will digest them. */
if (first_nonopt != last_nonopt)
optind = first_nonopt;
return EOF;
}
/* If we have come to a non-option and did not permute it,
either stop the scan or describe it to the caller and pass it by. */
if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
#ifdef GETOPT_COMPAT
&& (longopts == NULL
|| argv[optind][0] != '+' || argv[optind][1] == '\0')
#endif /* GETOPT_COMPAT */
)
{
if (ordering == REQUIRE_ORDER)
return EOF;
optarg = argv[optind++];
return 1;
}
/* We have found another option-ARGV-element.
Start decoding its characters. */
nextchar = (argv[optind] + 1
+ (longopts != NULL && argv[optind][1] == '-'));
}
if (longopts != NULL
&& ((argv[optind][0] == '-'
&& (argv[optind][1] == '-' || long_only))
#ifdef GETOPT_COMPAT
|| argv[optind][0] == '+'
#endif /* GETOPT_COMPAT */
))
{
const struct option *p;
char *s = nextchar;
int exact = 0;
int ambig = 0;
const struct option *pfound = NULL;
int indfound;
while (*s && *s != '=')
s++;
/* Test all options for either exact match or abbreviated matches. */
for (p = longopts, option_index = 0; p->name;
p++, option_index++)
if (!strncmp (p->name, nextchar, s - nextchar))
{
if (s - nextchar == strlen (p->name))
{
/* Exact match found. */
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == NULL)
{
/* First nonexact match found. */
pfound = p;
indfound = option_index;
}
else
/* Second nonexact match found. */
ambig = 1;
}
if (ambig && !exact)
{
if (opterr)
fprintf (stderr, "%s: option `%s' is ambiguous\n",
argv[0], argv[optind]);
nextchar += strlen (nextchar);
optind++;
return '?';
}
if (pfound != NULL)
{
option_index = indfound;
optind++;
if (*s)
{
if (pfound->has_arg > 0)
optarg = s + 1;
else
{
if (opterr)
{
if (argv[optind - 1][1] == '-')
/* --option */
fprintf (stderr,
"%s: option `--%s' doesn't allow an argument\n",
argv[0], pfound->name);
else
/* +option or -option */
fprintf (stderr,
"%s: option `%c%s' doesn't allow an argument\n",
argv[0], argv[optind - 1][0], pfound->name);
}
nextchar += strlen (nextchar);
return '?';
}
}
else if (pfound->has_arg == 1)
{
if (optind < argc)
optarg = argv[optind++];
else
{
if (opterr)
fprintf (stderr, "%s: option `%s' requires an argument\n",
argv[0], argv[optind - 1]);
nextchar += strlen (nextchar);
return '?';
}
}
nextchar += strlen (nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
/* Can't find it as a long option. If this is not getopt_long_only,
or the option starts with '--' or is not a valid short
option, then it's an error.
Otherwise interpret it as a short option. */
if (!long_only || argv[optind][1] == '-'
#ifdef GETOPT_COMPAT
|| argv[optind][0] == '+'
#endif /* GETOPT_COMPAT */
|| my_index (optstring, *nextchar) == NULL)
{
if (opterr)
{
if (argv[optind][1] == '-')
/* --option */
fprintf (stderr, "%s: unrecognized option `--%s'\n",
argv[0], nextchar);
else
/* +option or -option */
fprintf (stderr, "%s: unrecognized option `%c%s'\n",
argv[0], argv[optind][0], nextchar);
}
nextchar += strlen (nextchar);
optind++;
return '?';
}
}
/* Look at and handle the next option-character. */
{
char c = *nextchar++;
char *temp = my_index (optstring, c);
/* Increment `optind' when we start to process its last character. */
if (*nextchar == '\0')
optind++;
if (temp == NULL || c == ':')
{
if (opterr)
{
if (c < 040 || c >= 0177)
fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
argv[0], c);
else
fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
}
return '?';
}
if (temp[1] == ':')
{
if (temp[2] == ':')
{
/* This is an option that accepts an argument optionally. */
if (*nextchar != '\0')
{
optarg = nextchar;
optind++;
}
else
optarg = 0;
nextchar = NULL;
}
else
{
/* This is an option that requires an argument. */
if (*nextchar != 0)
{
optarg = nextchar;
/* If we end this ARGV-element by taking the rest as an arg,
we must advance to the next element now. */
optind++;
}
else if (optind == argc)
{
if (opterr)
fprintf (stderr, "%s: option `-%c' requires an argument\n",
argv[0], c);
c = '?';
}
else
/* We already incremented `optind' once;
increment it again when taking next ARGV-elt as argument. */
optarg = argv[optind++];
nextchar = NULL;
}
}
return c;
}
}
int
getopt (argc, argv, optstring)
int argc;
char *const *argv;
const char *optstring;
{
return _getopt_internal (argc, argv, optstring,
(const struct option *) 0,
(int *) 0,
0);
}
#ifdef TEST
/* Compile with -DTEST to make an executable for use in testing
the above definition of `getopt'. */
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
c = getopt (argc, argv, "abc:d:0123456789");
if (c == EOF)
break;
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */
+107
View File
@@ -0,0 +1,107 @@
/* Declarations for getopt.
Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _GETOPT_H_
#define _GETOPT_H_
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
#ifdef __STDC__
const char *name;
#else
char *name;
#endif
enum
{
no_argument,
required_argument,
optional_argument
} has_arg;
int *flag;
int val;
};
#ifdef __STDC__
extern int getopt (int argc, char *const *argv, const char *shortopts);
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long_only (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
#else /* not __STDC__ */
extern int getopt ();
extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal ();
#endif /* not __STDC__ */
#endif /* _GETOPT_H_ */
+158
View File
@@ -0,0 +1,158 @@
/* Getopt for GNU.
Copyright (C) 1987, 88, 89, 90, 91, 1992 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef LIBC
/* For when compiled as part of the GNU C library. */
#include <ansidecl.h>
#endif
#include "getopt.h"
#ifndef __STDC__
#define const
#endif
#if defined(STDC_HEADERS) || defined(__GNU_LIBRARY__) || defined (LIBC)
#include <stdlib.h>
#else /* STDC_HEADERS or __GNU_LIBRARY__ */
char *getenv ();
#endif /* STDC_HEADERS or __GNU_LIBRARY__ */
#if !defined (NULL)
#define NULL 0
#endif
int
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
If an option that starts with '-' (not '--') doesn't match a long option,
but does match a short option, it is parsed as a short option
instead. */
int
getopt_long_only (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
}
#ifdef TEST
#include <stdio.h>
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] =
{
{"add", 1, 0, 0},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 0, 0, 0},
{"file", 1, 0, 0},
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "abc:d:0123456789",
long_options, &option_index);
if (c == EOF)
break;
switch (c)
{
case 0:
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case 'd':
printf ("option d with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */
+58
View File
@@ -0,0 +1,58 @@
/* Allocate input grammar variables for bison,
Copyright (C) 1984, 1986, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* comments for these variables are in gram.h */
int nitems;
int nrules;
int nsyms;
int ntokens;
int nvars;
short *ritem;
short *rlhs;
short *rrhs;
short *rprec;
short *rprecsym;
short *sprec;
short *rassoc;
short *sassoc;
short *token_translations;
short *rline;
int start_symbol;
int translations;
int max_user_token_number;
int semantic_parser;
int pure_parser;
int error_token_number;
/* This is to avoid linker problems which occur on VMS when using GCC,
when the file in question contains data definitions only. */
void
dummy()
{
}
+120
View File
@@ -0,0 +1,120 @@
/* Data definitions for internal representation of bison's input,
Copyright (C) 1984, 1986, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* representation of the grammar rules:
ntokens is the number of tokens, and nvars is the number of variables
(nonterminals). nsyms is the total number, ntokens + nvars.
Each symbol (either token or variable) receives a symbol number.
Numbers 0 to ntokens-1 are for tokens, and ntokens to nsyms-1 are for
variables. Symbol number zero is the end-of-input token. This token
is counted in ntokens.
The rules receive rule numbers 1 to nrules in the order they are written.
Actions and guards are accessed via the rule number.
The rules themselves are described by three arrays: rrhs, rlhs and
ritem. rlhs[R] is the symbol number of the left hand side of rule R.
The right hand side is stored as symbol numbers in a portion of
ritem. rrhs[R] contains the index in ritem of the beginning of the
portion for rule R.
If rlhs[R] is -1, the rule has been thrown out by reduce.c
and should be ignored.
The length of the portion is one greater
than the number of symbols in the rule's right hand side.
The last element in the portion contains minus R, which
identifies it as the end of a portion and says which rule it is for.
The portions of ritem come in order of increasing rule number and are
followed by an element which is zero to mark the end. nitems is the
total length of ritem, not counting the final zero. Each element of
ritem is called an "item" and its index in ritem is an item number.
Item numbers are used in the finite state machine to represent
places that parsing can get to.
Precedence levels are recorded in the vectors sprec and rprec.
sprec records the precedence level of each symbol,
rprec the precedence level of each rule.
rprecsym is the symbol-number of the symbol in %prec for this rule (if any).
Precedence levels are assigned in increasing order starting with 1 so
that numerically higher precedence values mean tighter binding as they
ought to. Zero as a symbol or rule's precedence means none is
assigned.
Associativities are recorded similarly in rassoc and sassoc. */
#define ISTOKEN(s) ((s) < ntokens)
#define ISVAR(s) ((s) >= ntokens)
extern int nitems;
extern int nrules;
extern int nsyms;
extern int ntokens;
extern int nvars;
extern short *ritem;
extern short *rlhs;
extern short *rrhs;
extern short *rprec;
extern short *rprecsym;
extern short *sprec;
extern short *rassoc;
extern short *sassoc;
extern short *rline; /* Source line number of each rule */
extern int start_symbol;
/* associativity values in elements of rassoc, sassoc. */
#define RIGHT_ASSOC 1
#define LEFT_ASSOC 2
#define NON_ASSOC 3
/* token translation table:
indexed by a token number as returned by the user's yylex routine,
it yields the internal token number used by the parser and throughout bison.
If translations is zero, the translation table is not used because
the two kinds of token numbers are the same. */
extern short *token_translations;
extern int translations;
extern int max_user_token_number;
/* semantic_parser is nonzero if the input file says to use the hairy parser
that provides for semantic error recovery. If it is zero, the yacc-compatible
simplified parser is used. */
extern int semantic_parser;
/* pure_parser is nonzero if should generate a parser that is all pure and reentrant. */
extern int pure_parser;
/* error_token_number is the token number of the error token. */
extern int error_token_number;
+770
View File
@@ -0,0 +1,770 @@
/* Compute look-ahead criteria for bison,
Copyright (C) 1984, 1986, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Compute how to make the finite state machine deterministic;
find which rules need lookahead in each state, and which lookahead tokens they accept.
lalr(), the entry point, builds these data structures:
goto_map, from_state and to_state
record each shift transition which accepts a variable (a nonterminal).
ngotos is the number of such transitions.
from_state[t] is the state number which a transition leads from
and to_state[t] is the state number it leads to.
All the transitions that accept a particular variable are grouped together and
goto_map[i - ntokens] is the index in from_state and to_state of the first of them.
consistent[s] is nonzero if no lookahead is needed to decide what to do in state s.
LAruleno is a vector which records the rules that need lookahead in various states.
The elements of LAruleno that apply to state s are those from
lookaheads[s] through lookaheads[s+1]-1.
Each element of LAruleno is a rule number.
If lr is the length of LAruleno, then a number from 0 to lr-1
can specify both a rule and a state where the rule might be applied.
LA is a lr by ntokens matrix of bits.
LA[l, i] is 1 if the rule LAruleno[l] is applicable in the appropriate state
when the next token is symbol i.
If LA[l, i] and LA[l, j] are both 1 for i != j, it is a conflict.
*/
#include <stdio.h>
#include "system.h"
#include "machine.h"
#include "types.h"
#include "state.h"
#include "new.h"
#include "gram.h"
extern short **derives;
extern char *nullable;
int tokensetsize;
short *lookaheads;
short *LAruleno;
unsigned *LA;
short *accessing_symbol;
char *consistent;
core **state_table;
shifts **shift_table;
reductions **reduction_table;
short *goto_map;
short *from_state;
short *to_state;
short **transpose();
void set_state_table();
void set_accessing_symbol();
void set_shift_table();
void set_reduction_table();
void set_maxrhs();
void initialize_LA();
void set_goto_map();
void initialize_F();
void build_relations();
void add_lookback_edge();
void compute_FOLLOWS();
void compute_lookaheads();
void digraph();
void traverse();
extern void toomany();
extern void berror();
static int infinity;
static int maxrhs;
static int ngotos;
static unsigned *F;
static short **includes;
static shorts **lookback;
static short **R;
static short *INDEX;
static short *VERTICES;
static int top;
void
lalr()
{
tokensetsize = WORDSIZE(ntokens);
set_state_table();
set_accessing_symbol();
set_shift_table();
set_reduction_table();
set_maxrhs();
initialize_LA();
set_goto_map();
initialize_F();
build_relations();
compute_FOLLOWS();
compute_lookaheads();
}
void
set_state_table()
{
register core *sp;
state_table = NEW2(nstates, core *);
for (sp = first_state; sp; sp = sp->next)
state_table[sp->number] = sp;
}
void
set_accessing_symbol()
{
register core *sp;
accessing_symbol = NEW2(nstates, short);
for (sp = first_state; sp; sp = sp->next)
accessing_symbol[sp->number] = sp->accessing_symbol;
}
void
set_shift_table()
{
register shifts *sp;
shift_table = NEW2(nstates, shifts *);
for (sp = first_shift; sp; sp = sp->next)
shift_table[sp->number] = sp;
}
void
set_reduction_table()
{
register reductions *rp;
reduction_table = NEW2(nstates, reductions *);
for (rp = first_reduction; rp; rp = rp->next)
reduction_table[rp->number] = rp;
}
void
set_maxrhs()
{
register short *itemp;
register int length;
register int max;
length = 0;
max = 0;
for (itemp = ritem; *itemp; itemp++)
{
if (*itemp > 0)
{
length++;
}
else
{
if (length > max) max = length;
length = 0;
}
}
maxrhs = max;
}
void
initialize_LA()
{
register int i;
register int j;
register int count;
register reductions *rp;
register shifts *sp;
register short *np;
consistent = NEW2(nstates, char);
lookaheads = NEW2(nstates + 1, short);
count = 0;
for (i = 0; i < nstates; i++)
{
register int k;
lookaheads[i] = count;
rp = reduction_table[i];
sp = shift_table[i];
if (rp && (rp->nreds > 1
|| (sp && ! ISVAR(accessing_symbol[sp->shifts[0]]))))
count += rp->nreds;
else
consistent[i] = 1;
if (sp)
for (k = 0; k < sp->nshifts; k++)
{
if (accessing_symbol[sp->shifts[k]] == error_token_number)
{
consistent[i] = 0;
break;
}
}
}
lookaheads[nstates] = count;
if (count == 0)
{
LA = NEW2(1 * tokensetsize, unsigned);
LAruleno = NEW2(1, short);
lookback = NEW2(1, shorts *);
}
else
{
LA = NEW2(count * tokensetsize, unsigned);
LAruleno = NEW2(count, short);
lookback = NEW2(count, shorts *);
}
np = LAruleno;
for (i = 0; i < nstates; i++)
{
if (!consistent[i])
{
if (rp = reduction_table[i])
for (j = 0; j < rp->nreds; j++)
*np++ = rp->rules[j];
}
}
}
void
set_goto_map()
{
register shifts *sp;
register int i;
register int symbol;
register int k;
register short *temp_map;
register int state2;
register int state1;
goto_map = NEW2(nvars + 1, short) - ntokens;
temp_map = NEW2(nvars + 1, short) - ntokens;
ngotos = 0;
for (sp = first_shift; sp; sp = sp->next)
{
for (i = sp->nshifts - 1; i >= 0; i--)
{
symbol = accessing_symbol[sp->shifts[i]];
if (ISTOKEN(symbol)) break;
if (ngotos == MAXSHORT)
toomany("gotos");
ngotos++;
goto_map[symbol]++;
}
}
k = 0;
for (i = ntokens; i < nsyms; i++)
{
temp_map[i] = k;
k += goto_map[i];
}
for (i = ntokens; i < nsyms; i++)
goto_map[i] = temp_map[i];
goto_map[nsyms] = ngotos;
temp_map[nsyms] = ngotos;
from_state = NEW2(ngotos, short);
to_state = NEW2(ngotos, short);
for (sp = first_shift; sp; sp = sp->next)
{
state1 = sp->number;
for (i = sp->nshifts - 1; i >= 0; i--)
{
state2 = sp->shifts[i];
symbol = accessing_symbol[state2];
if (ISTOKEN(symbol)) break;
k = temp_map[symbol]++;
from_state[k] = state1;
to_state[k] = state2;
}
}
FREE(temp_map + ntokens);
}
/* Map_goto maps a state/symbol pair into its numeric representation. */
int
map_goto(state, symbol)
int state;
int symbol;
{
register int high;
register int low;
register int middle;
register int s;
low = goto_map[symbol];
high = goto_map[symbol + 1] - 1;
while (low <= high)
{
middle = (low + high) / 2;
s = from_state[middle];
if (s == state)
return (middle);
else if (s < state)
low = middle + 1;
else
high = middle - 1;
}
berror("map_goto");
/* NOTREACHED */
return 0;
}
void
initialize_F()
{
register int i;
register int j;
register int k;
register shifts *sp;
register short *edge;
register unsigned *rowp;
register short *rp;
register short **reads;
register int nedges;
register int stateno;
register int symbol;
register int nwords;
nwords = ngotos * tokensetsize;
F = NEW2(nwords, unsigned);
reads = NEW2(ngotos, short *);
edge = NEW2(ngotos + 1, short);
nedges = 0;
rowp = F;
for (i = 0; i < ngotos; i++)
{
stateno = to_state[i];
sp = shift_table[stateno];
if (sp)
{
k = sp->nshifts;
for (j = 0; j < k; j++)
{
symbol = accessing_symbol[sp->shifts[j]];
if (ISVAR(symbol))
break;
SETBIT(rowp, symbol);
}
for (; j < k; j++)
{
symbol = accessing_symbol[sp->shifts[j]];
if (nullable[symbol])
edge[nedges++] = map_goto(stateno, symbol);
}
if (nedges)
{
reads[i] = rp = NEW2(nedges + 1, short);
for (j = 0; j < nedges; j++)
rp[j] = edge[j];
rp[nedges] = -1;
nedges = 0;
}
}
rowp += tokensetsize;
}
digraph(reads);
for (i = 0; i < ngotos; i++)
{
if (reads[i])
FREE(reads[i]);
}
FREE(reads);
FREE(edge);
}
void
build_relations()
{
register int i;
register int j;
register int k;
register short *rulep;
register short *rp;
register shifts *sp;
register int length;
register int nedges;
register int done;
register int state1;
register int stateno;
register int symbol1;
register int symbol2;
register short *shortp;
register short *edge;
register short *states;
register short **new_includes;
includes = NEW2(ngotos, short *);
edge = NEW2(ngotos + 1, short);
states = NEW2(maxrhs + 1, short);
for (i = 0; i < ngotos; i++)
{
nedges = 0;
state1 = from_state[i];
symbol1 = accessing_symbol[to_state[i]];
for (rulep = derives[symbol1]; *rulep > 0; rulep++)
{
length = 1;
states[0] = state1;
stateno = state1;
for (rp = ritem + rrhs[*rulep]; *rp > 0; rp++)
{
symbol2 = *rp;
sp = shift_table[stateno];
k = sp->nshifts;
for (j = 0; j < k; j++)
{
stateno = sp->shifts[j];
if (accessing_symbol[stateno] == symbol2) break;
}
states[length++] = stateno;
}
if (!consistent[stateno])
add_lookback_edge(stateno, *rulep, i);
length--;
done = 0;
while (!done)
{
done = 1;
rp--;
/* JF added rp>=ritem && I hope to god its right! */
if (rp>=ritem && ISVAR(*rp))
{
stateno = states[--length];
edge[nedges++] = map_goto(stateno, *rp);
if (nullable[*rp]) done = 0;
}
}
}
if (nedges)
{
includes[i] = shortp = NEW2(nedges + 1, short);
for (j = 0; j < nedges; j++)
shortp[j] = edge[j];
shortp[nedges] = -1;
}
}
new_includes = transpose(includes, ngotos);
for (i = 0; i < ngotos; i++)
if (includes[i])
FREE(includes[i]);
FREE(includes);
includes = new_includes;
FREE(edge);
FREE(states);
}
void
add_lookback_edge(stateno, ruleno, gotono)
int stateno;
int ruleno;
int gotono;
{
register int i;
register int k;
register int found;
register shorts *sp;
i = lookaheads[stateno];
k = lookaheads[stateno + 1];
found = 0;
while (!found && i < k)
{
if (LAruleno[i] == ruleno)
found = 1;
else
i++;
}
if (found == 0)
berror("add_lookback_edge");
sp = NEW(shorts);
sp->next = lookback[i];
sp->value = gotono;
lookback[i] = sp;
}
short **
transpose(R_arg, n)
short **R_arg;
int n;
{
register short **new_R;
register short **temp_R;
register short *nedges;
register short *sp;
register int i;
register int k;
nedges = NEW2(n, short);
for (i = 0; i < n; i++)
{
sp = R_arg[i];
if (sp)
{
while (*sp >= 0)
nedges[*sp++]++;
}
}
new_R = NEW2(n, short *);
temp_R = NEW2(n, short *);
for (i = 0; i < n; i++)
{
k = nedges[i];
if (k > 0)
{
sp = NEW2(k + 1, short);
new_R[i] = sp;
temp_R[i] = sp;
sp[k] = -1;
}
}
FREE(nedges);
for (i = 0; i < n; i++)
{
sp = R_arg[i];
if (sp)
{
while (*sp >= 0)
*temp_R[*sp++]++ = i;
}
}
FREE(temp_R);
return (new_R);
}
void
compute_FOLLOWS()
{
register int i;
digraph(includes);
for (i = 0; i < ngotos; i++)
{
if (includes[i]) FREE(includes[i]);
}
FREE(includes);
}
void
compute_lookaheads()
{
register int i;
register int n;
register unsigned *fp1;
register unsigned *fp2;
register unsigned *fp3;
register shorts *sp;
register unsigned *rowp;
/* register short *rulep; JF unused */
/* register int count; JF unused */
register shorts *sptmp;/* JF */
rowp = LA;
n = lookaheads[nstates];
for (i = 0; i < n; i++)
{
fp3 = rowp + tokensetsize;
for (sp = lookback[i]; sp; sp = sp->next)
{
fp1 = rowp;
fp2 = F + tokensetsize * sp->value;
while (fp1 < fp3)
*fp1++ |= *fp2++;
}
rowp = fp3;
}
for (i = 0; i < n; i++)
{/* JF removed ref to freed storage */
for (sp = lookback[i]; sp; sp = sptmp) {
sptmp=sp->next;
FREE(sp);
}
}
FREE(lookback);
FREE(F);
}
void
digraph(relation)
short **relation;
{
register int i;
infinity = ngotos + 2;
INDEX = NEW2(ngotos + 1, short);
VERTICES = NEW2(ngotos + 1, short);
top = 0;
R = relation;
for (i = 0; i < ngotos; i++)
INDEX[i] = 0;
for (i = 0; i < ngotos; i++)
{
if (INDEX[i] == 0 && R[i])
traverse(i);
}
FREE(INDEX);
FREE(VERTICES);
}
void
traverse(i)
register int i;
{
register unsigned *fp1;
register unsigned *fp2;
register unsigned *fp3;
register int j;
register short *rp;
int height;
unsigned *base;
VERTICES[++top] = i;
INDEX[i] = height = top;
base = F + i * tokensetsize;
fp3 = base + tokensetsize;
rp = R[i];
if (rp)
{
while ((j = *rp++) >= 0)
{
if (INDEX[j] == 0)
traverse(j);
if (INDEX[i] > INDEX[j])
INDEX[i] = INDEX[j];
fp1 = base;
fp2 = F + j * tokensetsize;
while (fp1 < fp3)
*fp1++ |= *fp2++;
}
}
if (INDEX[i] == height)
{
for (;;)
{
j = VERTICES[top--];
INDEX[j] = infinity;
if (i == j)
break;
fp1 = base;
fp2 = F + j * tokensetsize;
while (fp1 < fp3)
*fp2++ = *fp1++;
}
}
}
+501
View File
@@ -0,0 +1,501 @@
/* Token-reader for Bison's input parser,
Copyright (C) 1984, 1986, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
lex() is the entry point. It is called from reader.c.
It returns one of the token-type codes defined in lex.h.
When an identifier is seen, the code IDENTIFIER is returned
and the name is looked up in the symbol table using symtab.c;
symval is set to a pointer to the entry found. */
#include <stdio.h>
#include <ctype.h>
#include "system.h"
#include "files.h"
#include "symtab.h"
#include "lex.h"
#include "new.h"
extern int lineno;
extern int translations;
int parse_percent_token();
extern void fatals();
extern void fatal();
/* Buffer for storing the current token. */
char *token_buffer;
/* Allocated size of token_buffer, not including space for terminator. */
static int maxtoken;
bucket *symval;
int numval;
static int unlexed; /* these two describe a token to be reread */
static bucket *unlexed_symval; /* by the next call to lex */
void
init_lex()
{
maxtoken = 100;
token_buffer = NEW2 (maxtoken + 1, char);
unlexed = -1;
}
static char *
grow_token_buffer (p)
char *p;
{
int offset = p - token_buffer;
maxtoken *= 2;
token_buffer = (char *) realloc(token_buffer, maxtoken + 1);
if (token_buffer == 0)
fatal("virtual memory exhausted");
return token_buffer + offset;
}
int
skip_white_space()
{
register int c;
register int inside;
c = getc(finput);
for (;;)
{
switch (c)
{
case '/':
c = getc(finput);
if (c != '*')
fatals("unexpected `/%c' found",c);
c = getc(finput);
inside = 1;
while (inside)
{
if (c == '*')
{
while (c == '*')
c = getc(finput);
if (c == '/')
{
inside = 0;
c = getc(finput);
}
}
else if (c == '\n')
{
lineno++;
c = getc(finput);
}
else if (c == EOF)
fatal("unterminated comment");
else
c = getc(finput);
}
break;
case '\n':
lineno++;
case ' ':
case '\t':
case '\f':
c = getc(finput);
break;
default:
return (c);
}
}
}
void
unlex(token)
int token;
{
unlexed = token;
unlexed_symval = symval;
}
int
lex()
{
register int c;
register char *p;
if (unlexed >= 0)
{
symval = unlexed_symval;
c = unlexed;
unlexed = -1;
return (c);
}
c = skip_white_space();
switch (c)
{
case EOF:
return (ENDFILE);
case 'A': case 'B': case 'C': case 'D': case 'E':
case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'L': case 'M': case 'N': case 'O':
case 'P': case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'X': case 'Y':
case 'Z':
case 'a': case 'b': case 'c': case 'd': case 'e':
case 'f': case 'g': case 'h': case 'i': case 'j':
case 'k': case 'l': case 'm': case 'n': case 'o':
case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y':
case 'z':
case '.': case '_':
p = token_buffer;
while (isalnum(c) || c == '_' || c == '.')
{
if (p == token_buffer + maxtoken)
p = grow_token_buffer(p);
*p++ = c;
c = getc(finput);
}
*p = 0;
ungetc(c, finput);
symval = getsym(token_buffer);
return (IDENTIFIER);
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
{
numval = 0;
while (isdigit(c))
{
numval = numval*10 + c - '0';
c = getc(finput);
}
ungetc(c, finput);
return (NUMBER);
}
case '\'':
translations = -1;
/* parse the literal token and compute character code in code */
c = getc(finput);
{
register int code = 0;
if (c == '\\')
{
c = getc(finput);
if (c <= '7' && c >= '0')
{
while (c <= '7' && c >= '0')
{
code = (code * 8) + (c - '0');
c = getc(finput);
if (code >= 256 || code < 0)
fatals("malformatted literal token `\\%03o'", code);
}
}
else
{
if (c == 't')
code = '\t';
else if (c == 'n')
code = '\n';
else if (c == 'a')
code = '\007';
else if (c == 'r')
code = '\r';
else if (c == 'f')
code = '\f';
else if (c == 'b')
code = '\b';
else if (c == 'v')
code = 013;
else if (c == 'x')
{
c = getc(finput);
while ((c <= '9' && c >= '0')
|| (c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z'))
{
code *= 16;
if (c <= '9' && c >= '0')
code += c - '0';
else if (c >= 'a' && c <= 'z')
code += c - 'a' + 10;
else if (c >= 'A' && c <= 'Z')
code += c - 'A' + 10;
if (code >= 256 || code<0)/* JF this said if(c>=128) */
fatals("malformatted literal token `\\x%x'",code);
c = getc(finput);
}
ungetc(c, finput);
}
else if (c == '\\')
code = '\\';
else if (c == '\'')
code = '\'';
else if (c == '\"') /* JF this is a good idea */
code = '\"';
else
{
if (c >= 040 && c <= 0177)
fatals ("unknown escape sequence `\\%c'", c);
else
fatals ("unknown escape sequence: `\\' followed by char code 0x%x", c);
}
c = getc(finput);
}
}
else
{
code = c;
c = getc(finput);
}
if (c != '\'')
fatal("multicharacter literal tokens not supported");
/* now fill token_buffer with the canonical name for this character
as a literal token. Do not use what the user typed,
so that '\012' and '\n' can be interchangeable. */
p = token_buffer;
*p++ = '\'';
if (code == '\\')
{
*p++ = '\\';
*p++ = '\\';
}
else if (code == '\'')
{
*p++ = '\\';
*p++ = '\'';
}
else if (code >= 040 && code != 0177)
*p++ = code;
else if (code == '\t')
{
*p++ = '\\';
*p++ = 't';
}
else if (code == '\n')
{
*p++ = '\\';
*p++ = 'n';
}
else if (code == '\r')
{
*p++ = '\\';
*p++ = 'r';
}
else if (code == '\v')
{
*p++ = '\\';
*p++ = 'v';
}
else if (code == '\b')
{
*p++ = '\\';
*p++ = 'b';
}
else if (code == '\f')
{
*p++ = '\\';
*p++ = 'f';
}
else
{
*p++ = code / 0100 + '0';
*p++ = ((code / 010) & 07) + '0';
*p++ = (code & 07) + '0';
}
*p++ = '\'';
*p = 0;
symval = getsym(token_buffer);
symval->class = STOKEN;
if (! symval->user_token_number)
symval->user_token_number = code;
return (IDENTIFIER);
}
case ',':
return (COMMA);
case ':':
return (COLON);
case ';':
return (SEMICOLON);
case '|':
return (BAR);
case '{':
return (LEFT_CURLY);
case '=':
do
{
c = getc(finput);
if (c == '\n') lineno++;
}
while(c==' ' || c=='\n' || c=='\t');
if (c == '{')
return(LEFT_CURLY);
else
{
ungetc(c, finput);
return(ILLEGAL);
}
case '<':
p = token_buffer;
c = getc(finput);
while (c != '>')
{
if (c == '\n' || c == EOF)
fatal("unterminated type name");
if (p == token_buffer + maxtoken)
p = grow_token_buffer(p);
*p++ = c;
c = getc(finput);
}
*p = 0;
return (TYPENAME);
case '%':
return (parse_percent_token());
default:
return (ILLEGAL);
}
}
/* parse a token which starts with %. Assumes the % has already been read and discarded. */
int
parse_percent_token ()
{
register int c;
register char *p;
p = token_buffer;
c = getc(finput);
switch (c)
{
case '%':
return (TWO_PERCENTS);
case '{':
return (PERCENT_LEFT_CURLY);
case '<':
return (LEFT);
case '>':
return (RIGHT);
case '2':
return (NONASSOC);
case '0':
return (TOKEN);
case '=':
return (PREC);
}
if (!isalpha(c))
return (ILLEGAL);
while (isalpha(c) || c == '_')
{
if (p == token_buffer + maxtoken)
p = grow_token_buffer(p);
*p++ = c;
c = getc(finput);
}
ungetc(c, finput);
*p = 0;
if (strcmp(token_buffer, "token") == 0
||
strcmp(token_buffer, "term") == 0)
return (TOKEN);
else if (strcmp(token_buffer, "nterm") == 0)
return (NTERM);
else if (strcmp(token_buffer, "type") == 0)
return (TYPE);
else if (strcmp(token_buffer, "guard") == 0)
return (GUARD);
else if (strcmp(token_buffer, "union") == 0)
return (UNION);
else if (strcmp(token_buffer, "expect") == 0)
return (EXPECT);
else if (strcmp(token_buffer, "start") == 0)
return (START);
else if (strcmp(token_buffer, "left") == 0)
return (LEFT);
else if (strcmp(token_buffer, "right") == 0)
return (RIGHT);
else if (strcmp(token_buffer, "nonassoc") == 0
||
strcmp(token_buffer, "binary") == 0)
return (NONASSOC);
else if (strcmp(token_buffer, "semantic_parser") == 0)
return (SEMANTIC_PARSER);
else if (strcmp(token_buffer, "pure_parser") == 0)
return (PURE_PARSER);
else if (strcmp(token_buffer, "prec") == 0)
return (PREC);
else return (ILLEGAL);
}
+47
View File
@@ -0,0 +1,47 @@
/* Token type definitions for bison's input reader,
Copyright (C) 1984, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define ENDFILE 0
#define IDENTIFIER 1
#define COMMA 2
#define COLON 3
#define SEMICOLON 4
#define BAR 5
#define LEFT_CURLY 6
#define TWO_PERCENTS 7
#define PERCENT_LEFT_CURLY 8
#define TOKEN 9
#define NTERM 10
#define GUARD 11
#define TYPE 12
#define UNION 13
#define START 14
#define LEFT 15
#define RIGHT 16
#define NONASSOC 17
#define PREC 18
#define SEMANTIC_PARSER 19
#define PURE_PARSER 20
#define TYPENAME 21
#define NUMBER 22
#define EXPECT 23
#define ILLEGAL 24
#define MAXTOKEN 1024
+39
View File
@@ -0,0 +1,39 @@
/* Define machine-dependencies for bison,
Copyright (C) 1984, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef eta10
#define MAXSHORT 2147483647
#define MINSHORT -2147483648
#else
#define MAXSHORT 32767
#define MINSHORT -32768
#endif
#if defined (MSDOS) && !defined (__GO32__)
#define BITS_PER_WORD 16
#define MAXTABLE 16383
#else
#define BITS_PER_WORD 32
#define MAXTABLE 32767
#endif
#define WORDSIZE(n) (((n) + BITS_PER_WORD - 1) / BITS_PER_WORD)
#define SETBIT(x, i) ((x)[(i)/BITS_PER_WORD] |= (1<<((i) % BITS_PER_WORD)))
#define RESETBIT(x, i) ((x)[(i)/BITS_PER_WORD] &= ~(1<<((i) % BITS_PER_WORD)))
#define BITISSET(x, i) (((x)[(i)/BITS_PER_WORD] & (1<<((i) % BITS_PER_WORD))) != 0)
+138
View File
@@ -0,0 +1,138 @@
/* Top level entry point of bison,
Copyright (C) 1984, 1986, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "system.h"
#include "machine.h" /* JF for MAXSHORT */
extern int lineno;
extern int verboseflag;
/* Nonzero means failure has been detected; don't write a parser file. */
int failure;
/* The name this program was run with, for messages. */
char *program_name;
extern void getargs(), openfiles(), reader(), reduce_grammar();
extern void set_derives(), set_nullable(), generate_states();
extern void lalr(), initialize_conflicts(), verbose(), terse();
extern void output(), done(), abort();
/* VMS complained about using `int'. */
int
main(argc, argv)
int argc;
char *argv[];
{
program_name = argv[0];
failure = 0;
lineno = 0;
getargs(argc, argv);
openfiles();
/* read the input. Copy some parts of it to fguard, faction, ftable and fattrs.
In file reader.c.
The other parts are recorded in the grammar; see gram.h. */
reader();
/* find useless nonterminals and productions and reduce the grammar. In
file reduce.c */
reduce_grammar();
/* record other info about the grammar. In files derives and nullable. */
set_derives();
set_nullable();
/* convert to nondeterministic finite state machine. In file LR0.
See state.h for more info. */
generate_states();
/* make it deterministic. In file lalr. */
lalr();
/* Find and record any conflicts: places where one token of lookahead is not
enough to disambiguate the parsing. In file conflicts.
Currently this does not do anything to resolve them;
the trivial form of conflict resolution that exists is done in output. */
initialize_conflicts();
/* print information about results, if requested. In file print. */
if (verboseflag)
verbose();
else
terse();
/* output the tables and the parser to ftable. In file output. */
output();
done(failure);
}
/* functions to report errors which prevent a parser from being generated */
void
fatal(s)
char *s;
{
extern char *infile;
if (infile == 0)
fprintf(stderr, "fatal error: %s\n", s);
else
fprintf(stderr, "\"%s\", line %d: %s\n", infile, lineno, s);
done(1);
}
/* JF changed to accept/deal with variable args. Is a real kludge since
we don't support _doprnt calls */
/*VARARGS1*/
void
fatals(fmt,x1,x2,x3,x4,x5,x6,x7,x8)
char *fmt;
{
char buffer[200];
sprintf(buffer, fmt, x1,x2,x3,x4,x5,x6,x7,x8);
fatal(buffer);
}
void
toomany(s)
char *s;
{
char buffer[200];
/* JF new msg */
sprintf(buffer, "limit of %d exceeded, too many %s", MAXSHORT, s);
fatal(buffer);
}
void
berror(s)
char *s;
{
fprintf(stderr, "internal error, %s\n", s);
abort();
}
+30
View File
@@ -0,0 +1,30 @@
/* Storage allocation interface for bison,
Copyright (C) 1984, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define NEW(t) ((t *) mallocate((unsigned) sizeof(t)))
#define NEW2(n, t) ((t *) mallocate((unsigned) ((n) * sizeof(t))))
#ifdef __STDC__
#define FREE(x) (x ? (void) free((char *) (x)) : (void)0)
#else
#define FREE(x) (x && free((char *) (x)))
#endif
extern char *mallocate();
+136
View File
@@ -0,0 +1,136 @@
/* Part of the bison parser generator,
Copyright (C) 1984, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* set up nullable, a vector saying which nonterminals can expand into the null string.
nullable[i - ntokens] is nonzero if symbol i can do so. */
#include <stdio.h>
#include "system.h"
#include "types.h"
#include "gram.h"
#include "new.h"
char *nullable;
void
set_nullable()
{
register short *r;
register short *s1;
register short *s2;
register int ruleno;
register int symbol;
register shorts *p;
short *squeue;
short *rcount;
shorts **rsets;
shorts *relts;
char any_tokens;
short *r1;
#ifdef TRACE
fprintf(stderr, "Entering set_nullable");
#endif
nullable = NEW2(nvars, char) - ntokens;
squeue = NEW2(nvars, short);
s1 = s2 = squeue;
rcount = NEW2(nrules + 1, short);
rsets = NEW2(nvars, shorts *) - ntokens;
/* This is said to be more elements than we actually use.
Supposedly nitems - nrules is enough.
But why take the risk? */
relts = NEW2(nitems + nvars + 1, shorts);
p = relts;
r = ritem;
while (*r)
{
if (*r < 0)
{
symbol = rlhs[-(*r++)];
if (symbol >= 0 && !nullable[symbol])
{
nullable[symbol] = 1;
*s2++ = symbol;
}
}
else
{
r1 = r;
any_tokens = 0;
for (symbol = *r++; symbol > 0; symbol = *r++)
{
if (ISTOKEN(symbol))
any_tokens = 1;
}
if (!any_tokens)
{
ruleno = -symbol;
r = r1;
for (symbol = *r++; symbol > 0; symbol = *r++)
{
rcount[ruleno]++;
p->next = rsets[symbol];
p->value = ruleno;
rsets[symbol] = p;
p++;
}
}
}
}
while (s1 < s2)
{
p = rsets[*s1++];
while (p)
{
ruleno = p->value;
p = p->next;
if (--rcount[ruleno] == 0)
{
symbol = rlhs[ruleno];
if (symbol >= 0 && !nullable[symbol])
{
nullable[symbol] = 1;
*s2++ = symbol;
}
}
}
}
FREE(squeue);
FREE(rcount);
FREE(rsets + ntokens);
FREE(relts);
}
void
free_nullable()
{
FREE(nullable + ntokens);
}
File diff suppressed because it is too large Load Diff
+373
View File
@@ -0,0 +1,373 @@
/* Print information on generated parser, for bison,
Copyright (C) 1984, 1986, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "system.h"
#include "machine.h"
#include "new.h"
#include "files.h"
#include "gram.h"
#include "state.h"
extern char **tags;
extern int nstates;
extern short *accessing_symbol;
extern core **state_table;
extern shifts **shift_table;
extern errs **err_table;
extern reductions **reduction_table;
extern char *consistent;
extern char any_conflicts;
extern char *conflicts;
extern int final_state;
extern void conflict_log();
extern void verbose_conflict_log();
extern void print_reductions();
void print_token();
void print_state();
void print_core();
void print_actions();
void print_grammar();
void
terse()
{
if (any_conflicts)
{
conflict_log();
}
}
void
verbose()
{
register int i;
if (any_conflicts)
verbose_conflict_log();
print_grammar();
for (i = 0; i < nstates; i++)
{
print_state(i);
}
}
void
print_token(extnum, token)
int extnum, token;
{
fprintf(foutput, " type %d is %s\n", extnum, tags[token]);
}
void
print_state(state)
int state;
{
fprintf(foutput, "\n\nstate %d\n\n", state);
print_core(state);
print_actions(state);
}
void
print_core(state)
int state;
{
register int i;
register int k;
register int rule;
register core *statep;
register short *sp;
register short *sp1;
statep = state_table[state];
k = statep->nitems;
if (k == 0) return;
for (i = 0; i < k; i++)
{
sp1 = sp = ritem + statep->items[i];
while (*sp > 0)
sp++;
rule = -(*sp);
fprintf(foutput, " %s -> ", tags[rlhs[rule]]);
for (sp = ritem + rrhs[rule]; sp < sp1; sp++)
{
fprintf(foutput, "%s ", tags[*sp]);
}
putc('.', foutput);
while (*sp > 0)
{
fprintf(foutput, " %s", tags[*sp]);
sp++;
}
fprintf (foutput, " (rule %d)", rule);
putc('\n', foutput);
}
putc('\n', foutput);
}
void
print_actions(state)
int state;
{
register int i;
register int k;
register int state1;
register int symbol;
register shifts *shiftp;
register errs *errp;
register reductions *redp;
register int rule;
shiftp = shift_table[state];
redp = reduction_table[state];
errp = err_table[state];
if (!shiftp && !redp)
{
if (final_state == state)
fprintf(foutput, " $default\taccept\n");
else
fprintf(foutput, " NO ACTIONS\n");
return;
}
if (shiftp)
{
k = shiftp->nshifts;
for (i = 0; i < k; i++)
{
if (! shiftp->shifts[i]) continue;
state1 = shiftp->shifts[i];
symbol = accessing_symbol[state1];
/* The following line used to be turned off. */
if (ISVAR(symbol)) break;
if (symbol==0) /* I.e. strcmp(tags[symbol],"$")==0 */
fprintf(foutput, " $ \tgo to state %d\n", state1);
else
fprintf(foutput, " %-4s\tshift, and go to state %d\n",
tags[symbol], state1);
}
if (i > 0)
putc('\n', foutput);
}
else
{
i = 0;
k = 0;
}
if (errp)
{
int j, nerrs;
nerrs = errp->nerrs;
for (j = 0; j < nerrs; j++)
{
if (! errp->errs[j]) continue;
symbol = errp->errs[j];
fprintf(foutput, " %-4s\terror (nonassociative)\n", tags[symbol]);
}
if (j > 0)
putc('\n', foutput);
}
if (consistent[state] && redp)
{
rule = redp->rules[0];
symbol = rlhs[rule];
fprintf(foutput, " $default\treduce using rule %d (%s)\n\n",
rule, tags[symbol]);
}
else if (redp)
{
print_reductions(state);
}
if (i < k)
{
for (; i < k; i++)
{
if (! shiftp->shifts[i]) continue;
state1 = shiftp->shifts[i];
symbol = accessing_symbol[state1];
fprintf(foutput, " %-4s\tgo to state %d\n", tags[symbol], state1);
}
putc('\n', foutput);
}
}
#define END_TEST(end) \
if (column + strlen(buffer) > (end)) \
{ fprintf (foutput, "%s\n ", buffer); column = 3; buffer[0] = 0; } \
else
void
print_grammar()
{
int i, j;
short* rule;
char buffer[90];
int column = 0;
/* rule # : LHS -> RHS */
fputs("\nGrammar\n", foutput);
for (i = 1; i <= nrules; i++)
/* Don't print rules disabled in reduce_grammar_tables. */
if (rlhs[i] >= 0)
{
fprintf(foutput, "rule %-4d %s ->", i, tags[rlhs[i]]);
rule = &ritem[rrhs[i]];
if (*rule > 0)
while (*rule > 0)
fprintf(foutput, " %s", tags[*rule++]);
else
fputs (" /* empty */", foutput);
putc('\n', foutput);
}
/* TERMINAL (type #) : rule #s terminal is on RHS */
fputs("\nTerminals, with rules where they appear\n\n", foutput);
fprintf(foutput, "%s (-1)\n", tags[0]);
if (translations)
{
for (i = 0; i <= max_user_token_number; i++)
if (token_translations[i] != 2)
{
buffer[0] = 0;
column = strlen (tags[token_translations[i]]);
fprintf(foutput, "%s", tags[token_translations[i]]);
END_TEST (50);
sprintf (buffer, " (%d)", i);
for (j = 1; j <= nrules; j++)
{
for (rule = &ritem[rrhs[j]]; *rule > 0; rule++)
if (*rule == token_translations[i])
{
END_TEST (65);
sprintf (buffer + strlen(buffer), " %d", j);
break;
}
}
fprintf (foutput, "%s\n", buffer);
}
}
else
for (i = 1; i < ntokens; i++)
{
buffer[0] = 0;
column = strlen (tags[i]);
fprintf(foutput, "%s", tags[i]);
END_TEST (50);
sprintf (buffer, " (%d)", i);
for (j = 1; j <= nrules; j++)
{
for (rule = &ritem[rrhs[j]]; *rule > 0; rule++)
if (*rule == i)
{
END_TEST (65);
sprintf (buffer + strlen(buffer), " %d", j);
break;
}
}
fprintf (foutput, "%s\n", buffer);
}
fputs("\nNonterminals, with rules where they appear\n\n", foutput);
for (i = ntokens; i <= nsyms - 1; i++)
{
int left_count = 0, right_count = 0;
for (j = 1; j <= nrules; j++)
{
if (rlhs[j] == i)
left_count++;
for (rule = &ritem[rrhs[j]]; *rule > 0; rule++)
if (*rule == i)
{
right_count++;
break;
}
}
buffer[0] = 0;
fprintf(foutput, "%s", tags[i]);
column = strlen (tags[i]);
sprintf (buffer, " (%d)", i);
END_TEST (0);
if (left_count > 0)
{
END_TEST (50);
sprintf (buffer + strlen(buffer), " on left:");
for (j = 1; j <= nrules; j++)
{
END_TEST (65);
if (rlhs[j] == i)
sprintf (buffer + strlen(buffer), " %d", j);
}
}
if (right_count > 0)
{
if (left_count > 0)
sprintf (buffer + strlen(buffer), ",");
END_TEST (50);
sprintf (buffer + strlen(buffer), " on right:");
for (j = 1; j <= nrules; j++)
{
for (rule = &ritem[rrhs[j]]; *rule > 0; rule++)
if (*rule == i)
{
END_TEST (65);
sprintf (buffer + strlen(buffer), " %d", j);
break;
}
}
}
fprintf (foutput, "%s\n", buffer);
}
}
File diff suppressed because it is too large Load Diff
+598
View File
@@ -0,0 +1,598 @@
/* Grammar reduction for Bison.
Copyright (C) 1988, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* Reduce the grammar: Find and eliminate unreachable terminals,
* nonterminals, and productions. David S. Bakin.
*/
/*
* Don't eliminate unreachable terminals: They may be used by the user's
* parser.
*/
#include <stdio.h>
#include "system.h"
#include "files.h"
#include "gram.h"
#include "machine.h"
#include "new.h"
extern char **tags; /* reader.c */
extern int verboseflag; /* getargs.c */
static int statisticsflag; /* XXXXXXX */
#ifndef TRUE
#define TRUE (1)
#define FALSE (0)
#endif
typedef int bool;
typedef unsigned *BSet;
typedef short *rule;
/*
* N is set of all nonterminals which are not useless. P is set of all rules
* which have no useless nonterminals in their RHS. V is the set of all
* accessible symbols.
*/
static BSet N, P, V, V1;
static int nuseful_productions, nuseless_productions,
nuseful_nonterminals, nuseless_nonterminals;
static void useless_nonterminals();
static void inaccessable_symbols();
static void reduce_grammar_tables();
static void print_results();
static void print_notices();
void dump_grammar();
extern void fatals ();
bool
bits_equal (L, R, n)
BSet L;
BSet R;
int n;
{
int i;
for (i = n - 1; i >= 0; i--)
if (L[i] != R[i])
return FALSE;
return TRUE;
}
int
nbits (i)
unsigned i;
{
int count = 0;
while (i != 0) {
i ^= (i & -i);
++count;
}
return count;
}
int
bits_size (S, n)
BSet S;
int n;
{
int i, count = 0;
for (i = n - 1; i >= 0; i--)
count += nbits(S[i]);
return count;
}
void
reduce_grammar ()
{
bool reduced;
/* Allocate the global sets used to compute the reduced grammar */
N = NEW2(WORDSIZE(nvars), unsigned);
P = NEW2(WORDSIZE(nrules + 1), unsigned);
V = NEW2(WORDSIZE(nsyms), unsigned);
V1 = NEW2(WORDSIZE(nsyms), unsigned);
useless_nonterminals();
inaccessable_symbols();
reduced = (bool) (nuseless_nonterminals + nuseless_productions > 0);
if (verboseflag)
print_results();
if (reduced == FALSE)
goto done_reducing;
print_notices();
if (!BITISSET(N, start_symbol - ntokens))
fatals("Start symbol %s does not derive any sentence.",
tags[start_symbol]);
reduce_grammar_tables();
/* if (verboseflag) {
fprintf(foutput, "REDUCED GRAMMAR\n\n");
dump_grammar();
}
*/
/**/ statisticsflag = FALSE; /* someday getopts should handle this */
if (statisticsflag == TRUE)
fprintf(stderr,
"reduced %s defines %d terminal%s, %d nonterminal%s\
, and %d production%s.\n", infile,
ntokens, (ntokens == 1 ? "" : "s"),
nvars, (nvars == 1 ? "" : "s"),
nrules, (nrules == 1 ? "" : "s"));
done_reducing:
/* Free the global sets used to compute the reduced grammar */
FREE(N);
FREE(V);
FREE(P);
}
/*
* Another way to do this would be with a set for each production and then do
* subset tests against N, but even for the C grammar the whole reducing
* process takes only 2 seconds on my 8Mhz AT.
*/
static bool
useful_production (i, N)
int i;
BSet N;
{
rule r;
short n;
/*
* A production is useful if all of the nonterminals in its RHS
* appear in the set of useful nonterminals.
*/
for (r = &ritem[rrhs[i]]; *r > 0; r++)
if (ISVAR(n = *r))
if (!BITISSET(N, n - ntokens))
return FALSE;
return TRUE;
}
/* Remember that rules are 1-origin, symbols are 0-origin. */
static void
useless_nonterminals ()
{
BSet Np, Ns;
int i, n;
/*
* N is set as built. Np is set being built this iteration. P is set
* of all productions which have a RHS all in N.
*/
Np = NEW2(WORDSIZE(nvars), unsigned);
/*
* The set being computed is a set of nonterminals which can derive
* the empty string or strings consisting of all terminals. At each
* iteration a nonterminal is added to the set if there is a
* production with that nonterminal as its LHS for which all the
* nonterminals in its RHS are already in the set. Iterate until the
* set being computed remains unchanged. Any nonterminals not in the
* set at that point are useless in that they will never be used in
* deriving a sentence of the language.
*
* This iteration doesn't use any special traversal over the
* productions. A set is kept of all productions for which all the
* nonterminals in the RHS are in useful. Only productions not in
* this set are scanned on each iteration. At the end, this set is
* saved to be used when finding useful productions: only productions
* in this set will appear in the final grammar.
*/
n = 0;
while (1)
{
for (i = WORDSIZE(nvars) - 1; i >= 0; i--)
Np[i] = N[i];
for (i = 1; i <= nrules; i++)
{
if (!BITISSET(P, i))
{
if (useful_production(i, N))
{
SETBIT(Np, rlhs[i] - ntokens);
SETBIT(P, i);
}
}
}
if (bits_equal(N, Np, WORDSIZE(nvars)))
break;
Ns = Np;
Np = N;
N = Ns;
}
FREE(N);
N = Np;
}
static void
inaccessable_symbols ()
{
BSet Vp, Vs, Pp;
int i, n;
short t;
rule r;
/*
* Find out which productions are reachable and which symbols are
* used. Starting with an empty set of productions and a set of
* symbols which only has the start symbol in it, iterate over all
* productions until the set of productions remains unchanged for an
* iteration. For each production which has a LHS in the set of
* reachable symbols, add the production to the set of reachable
* productions, and add all of the nonterminals in the RHS of the
* production to the set of reachable symbols.
*
* Consider only the (partially) reduced grammar which has only
* nonterminals in N and productions in P.
*
* The result is the set P of productions in the reduced grammar, and
* the set V of symbols in the reduced grammar.
*
* Although this algorithm also computes the set of terminals which are
* reachable, no terminal will be deleted from the grammar. Some
* terminals might not be in the grammar but might be generated by
* semantic routines, and so the user might want them available with
* specified numbers. (Is this true?) However, the nonreachable
* terminals are printed (if running in verbose mode) so that the user
* can know.
*/
Vp = NEW2(WORDSIZE(nsyms), unsigned);
Pp = NEW2(WORDSIZE(nrules + 1), unsigned);
/* If the start symbol isn't useful, then nothing will be useful. */
if (!BITISSET(N, start_symbol - ntokens))
goto end_iteration;
SETBIT(V, start_symbol);
n = 0;
while (1)
{
for (i = WORDSIZE(nsyms) - 1; i >= 0; i--)
Vp[i] = V[i];
for (i = 1; i <= nrules; i++)
{
if (!BITISSET(Pp, i) && BITISSET(P, i) &&
BITISSET(V, rlhs[i]))
{
for (r = &ritem[rrhs[i]]; *r >= 0; r++)
{
if (ISTOKEN(t = *r)
|| BITISSET(N, t - ntokens))
{
SETBIT(Vp, t);
}
}
SETBIT(Pp, i);
}
}
if (bits_equal(V, Vp, WORDSIZE(nsyms)))
{
break;
}
Vs = Vp;
Vp = V;
V = Vs;
}
end_iteration:
FREE(V);
V = Vp;
/* Tokens 0, 1, and 2 are internal to Bison. Consider them useful. */
SETBIT(V, 0); /* end-of-input token */
SETBIT(V, 1); /* error token */
SETBIT(V, 2); /* illegal token */
FREE(P);
P = Pp;
nuseful_productions = bits_size(P, WORDSIZE(nrules + 1));
nuseless_productions = nrules - nuseful_productions;
nuseful_nonterminals = 0;
for (i = ntokens; i < nsyms; i++)
if (BITISSET(V, i))
nuseful_nonterminals++;
nuseless_nonterminals = nvars - nuseful_nonterminals;
/* A token that was used in %prec should not be warned about. */
for (i = 1; i < nrules; i++)
if (rprecsym[i] != 0)
SETBIT(V1, rprecsym[i]);
}
static void
reduce_grammar_tables ()
{
/* This is turned off because we would need to change the numbers
in the case statements in the actions file. */
#if 0
/* remove useless productions */
if (nuseless_productions > 0)
{
short np, pn, ni, pi;
np = 0;
ni = 0;
for (pn = 1; pn <= nrules; pn++)
{
if (BITISSET(P, pn))
{
np++;
if (pn != np)
{
rlhs[np] = rlhs[pn];
rline[np] = rline[pn];
rprec[np] = rprec[pn];
rassoc[np] = rassoc[pn];
rrhs[np] = rrhs[pn];
if (rrhs[np] != ni)
{
pi = rrhs[np];
rrhs[np] = ni;
while (ritem[pi] >= 0)
ritem[ni++] = ritem[pi++];
ritem[ni++] = -np;
}
} else {
while (ritem[ni++] >= 0);
}
}
}
ritem[ni] = 0;
nrules -= nuseless_productions;
nitems = ni;
/*
* Is it worth it to reduce the amount of memory for the
* grammar? Probably not.
*/
}
#endif /* 0 */
/* Disable useless productions,
since they may contain useless nonterms
that would get mapped below to -1 and confuse everyone. */
if (nuseless_productions > 0)
{
int pn;
for (pn = 1; pn <= nrules; pn++)
{
if (!BITISSET(P, pn))
{
rlhs[pn] = -1;
}
}
}
/* remove useless symbols */
if (nuseless_nonterminals > 0)
{
int i, n;
/* short j; JF unused */
short *nontermmap;
rule r;
/*
* create a map of nonterminal number to new nonterminal
* number. -1 in the map means it was useless and is being
* eliminated.
*/
nontermmap = NEW2(nvars, short) - ntokens;
for (i = ntokens; i < nsyms; i++)
nontermmap[i] = -1;
n = ntokens;
for (i = ntokens; i < nsyms; i++)
if (BITISSET(V, i))
nontermmap[i] = n++;
/* Shuffle elements of tables indexed by symbol number. */
for (i = ntokens; i < nsyms; i++)
{
n = nontermmap[i];
if (n >= 0)
{
sassoc[n] = sassoc[i];
sprec[n] = sprec[i];
tags[n] = tags[i];
} else {
free(tags[i]);
}
}
/* Replace all symbol numbers in valid data structures. */
for (i = 1; i <= nrules; i++)
{
/* Ignore the rules disabled above. */
if (rlhs[i] >= 0)
rlhs[i] = nontermmap[rlhs[i]];
if (ISVAR (rprecsym[i]))
/* Can this happen? */
rprecsym[i] = nontermmap[rprecsym[i]];
}
for (r = ritem; *r; r++)
if (ISVAR(*r))
*r = nontermmap[*r];
start_symbol = nontermmap[start_symbol];
nsyms -= nuseless_nonterminals;
nvars -= nuseless_nonterminals;
free(&nontermmap[ntokens]);
}
}
static void
print_results ()
{
int i;
/* short j; JF unused */
rule r;
bool b;
if (nuseless_nonterminals > 0)
{
fprintf(foutput, "Useless nonterminals:\n\n");
for (i = ntokens; i < nsyms; i++)
if (!BITISSET(V, i))
fprintf(foutput, " %s\n", tags[i]);
}
b = FALSE;
for (i = 0; i < ntokens; i++)
{
if (!BITISSET(V, i) && !BITISSET(V1, i))
{
if (!b)
{
fprintf(foutput, "\n\nTerminals which are not used:\n\n");
b = TRUE;
}
fprintf(foutput, " %s\n", tags[i]);
}
}
if (nuseless_productions > 0)
{
fprintf(foutput, "\n\nUseless rules:\n\n");
for (i = 1; i <= nrules; i++)
{
if (!BITISSET(P, i))
{
fprintf(foutput, "#%-4d ", i);
fprintf(foutput, "%s :\t", tags[rlhs[i]]);
for (r = &ritem[rrhs[i]]; *r >= 0; r++)
{
fprintf(foutput, " %s", tags[*r]);
}
fprintf(foutput, ";\n");
}
}
}
if (nuseless_nonterminals > 0 || nuseless_productions > 0 || b)
fprintf(foutput, "\n\n");
}
void
dump_grammar ()
{
int i;
rule r;
fprintf(foutput,
"ntokens = %d, nvars = %d, nsyms = %d, nrules = %d, nitems = %d\n\n",
ntokens, nvars, nsyms, nrules, nitems);
fprintf(foutput, "Variables\n---------\n\n");
fprintf(foutput, "Value Sprec Sassoc Tag\n");
for (i = ntokens; i < nsyms; i++)
fprintf(foutput, "%5d %5d %5d %s\n",
i, sprec[i], sassoc[i], tags[i]);
fprintf(foutput, "\n\n");
fprintf(foutput, "Rules\n-----\n\n");
for (i = 1; i <= nrules; i++)
{
fprintf(foutput, "%-5d(%5d%5d)%5d : (@%-5d)",
i, rprec[i], rassoc[i], rlhs[i], rrhs[i]);
for (r = &ritem[rrhs[i]]; *r > 0; r++)
fprintf(foutput, "%5d", *r);
fprintf(foutput, " [%d]\n", -(*r));
}
fprintf(foutput, "\n\n");
fprintf(foutput, "Rules interpreted\n-----------------\n\n");
for (i = 1; i <= nrules; i++)
{
fprintf(foutput, "%-5d %s :", i, tags[rlhs[i]]);
for (r = &ritem[rrhs[i]]; *r > 0; r++)
fprintf(foutput, " %s", tags[*r]);
fprintf(foutput, "\n");
}
fprintf(foutput, "\n\n");
}
static void
print_notices ()
{
extern int fixed_outfiles;
if (fixed_outfiles && nuseless_productions)
fprintf(stderr, "%d rules never reduced\n", nuseless_productions);
fprintf(stderr, "%s contains ", infile);
if (nuseless_nonterminals > 0)
{
fprintf(stderr, "%d useless nonterminal%s",
nuseless_nonterminals,
(nuseless_nonterminals == 1 ? "" : "s"));
}
if (nuseless_nonterminals > 0 && nuseless_productions > 0)
fprintf(stderr, " and ");
if (nuseless_productions > 0)
{
fprintf(stderr, "%d useless rule%s",
nuseless_productions,
(nuseless_productions == 1 ? "" : "s"));
}
fprintf(stderr, ".\n");
fflush(stderr);
}
+137
View File
@@ -0,0 +1,137 @@
/* Type definitions for nondeterministic finite state machine for bison,
Copyright (C) 1984, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* These type definitions are used to represent a nondeterministic
finite state machine that parses the specified grammar.
This information is generated by the function generate_states
in the file LR0.
Each state of the machine is described by a set of items --
particular positions in particular rules -- that are the possible
places where parsing could continue when the machine is in this state.
These symbols at these items are the allowable inputs that can follow now.
A core represents one state. States are numbered in the number field.
When generate_states is finished, the starting state is state 0
and nstates is the number of states. (A transition to a state
whose state number is nstates indicates termination.) All the cores
are chained together and first_state points to the first one (state 0).
For each state there is a particular symbol which must have been the
last thing accepted to reach that state. It is the accessing_symbol
of the core.
Each core contains a vector of nitems items which are the indices
in the ritems vector of the items that are selected in this state.
The link field is used for chaining buckets that hash states by
their itemsets. This is for recognizing equivalent states and
combining them when the states are generated.
The two types of transitions are shifts (push the lookahead token
and read another) and reductions (combine the last n things on the
stack via a rule, replace them with the symbol that the rule derives,
and leave the lookahead token alone). When the states are generated,
these transitions are represented in two other lists.
Each shifts structure describes the possible shift transitions out
of one state, the state whose number is in the number field.
The shifts structures are linked through next and first_shift points to them.
Each contains a vector of numbers of the states that shift transitions
can go to. The accessing_symbol fields of those states' cores say what kind
of input leads to them.
A shift to state zero should be ignored. Conflict resolution
deletes shifts by changing them to zero.
Each reductions structure describes the possible reductions at the state
whose number is in the number field. The data is a list of nreds rules,
represented by their rule numbers. first_reduction points to the list
of these structures.
Conflict resolution can decide that certain tokens in certain
states should explicitly be errors (for implementing %nonassoc).
For each state, the tokens that are errors for this reason
are recorded in an errs structure, which has the state number
in its number field. The rest of the errs structure is full
of token numbers.
There is at least one shift transition present in state zero.
It leads to a next-to-final state whose accessing_symbol is
the grammar's start symbol. The next-to-final state has one shift
to the final state, whose accessing_symbol is zero (end of input).
The final state has one shift, which goes to the termination state
(whose number is nstates-1).
The reason for the extra state at the end is to placate the parser's
strategy of making all decisions one token ahead of its actions. */
typedef
struct core
{
struct core *next;
struct core *link;
short number;
short accessing_symbol;
short nitems;
short items[1];
}
core;
typedef
struct shifts
{
struct shifts *next;
short number;
short nshifts;
short shifts[1];
}
shifts;
typedef
struct errs
{
short nerrs;
short errs[1];
}
errs;
typedef
struct reductions
{
struct reductions *next;
short number;
short nreds;
short rules[1];
}
reductions;
extern int nstates;
extern core *first_state;
extern shifts *first_shift;
extern reductions *first_reduction;
+150
View File
@@ -0,0 +1,150 @@
/* Symbol table manager for Bison,
Copyright (C) 1984, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "system.h"
#include "new.h"
#include "symtab.h"
#include "gram.h"
bucket **symtab;
bucket *firstsymbol;
bucket *lastsymbol;
int
hash(key)
char *key;
{
register char *cp;
register int k;
cp = key;
k = 0;
while (*cp)
k = ((k << 1) ^ (*cp++)) & 0x3fff;
return (k % TABSIZE);
}
char *
copys(s)
char *s;
{
register int i;
register char *cp;
register char *result;
i = 1;
for (cp = s; *cp; cp++)
i++;
result = mallocate((unsigned int)i);
strcpy(result, s);
return (result);
}
void
tabinit()
{
/* register int i; JF unused */
symtab = NEW2(TABSIZE, bucket *);
firstsymbol = NULL;
lastsymbol = NULL;
}
bucket *
getsym(key)
char *key;
{
register int hashval;
register bucket *bp;
register int found;
hashval = hash(key);
bp = symtab[hashval];
found = 0;
while (bp != NULL && found == 0)
{
if (strcmp(key, bp->tag) == 0)
found = 1;
else
bp = bp->link;
}
if (found == 0)
{
nsyms++;
bp = NEW(bucket);
bp->link = symtab[hashval];
bp->next = NULL;
bp->tag = copys(key);
bp->class = SUNKNOWN;
if (firstsymbol == NULL)
{
firstsymbol = bp;
lastsymbol = bp;
}
else
{
lastsymbol->next = bp;
lastsymbol = bp;
}
symtab[hashval] = bp;
}
return (bp);
}
void
free_symtab()
{
register int i;
register bucket *bp,*bptmp;/* JF don't use ptr after free */
for (i = 0; i < TABSIZE; i++)
{
bp = symtab[i];
while (bp)
{
bptmp = bp->link;
#if 0 /* This causes crashes because one string can appear more than once. */
if (bp->type_name)
FREE(bp->type_name);
#endif
FREE(bp);
bp = bptmp;
}
}
FREE(symtab);
}
+50
View File
@@ -0,0 +1,50 @@
/* Definitions for symtab.c and callers, part of bison,
Copyright (C) 1984, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define TABSIZE 1009
/* symbol classes */
#define SUNKNOWN 0
#define STOKEN 1
#define SNTERM 2
typedef
struct bucket
{
struct bucket *link;
struct bucket *next;
char *tag;
char *type_name;
short value;
short prec;
short assoc;
short user_token_number;
char class;
}
bucket;
extern bucket **symtab;
extern bucket *firstsymbol;
extern bucket *getsym();
+14
View File
@@ -0,0 +1,14 @@
#ifdef MSDOS
#include <stdlib.h>
#include <io.h>
#endif /* MSDOS */
#ifdef USG
#include <string.h>
#else /* not USG */
#ifdef MSDOS
#include <string.h>
#else
#include <strings.h>
#endif /* not MSDOS */
#endif /* not USG */
+27
View File
@@ -0,0 +1,27 @@
/* Define data type for representing bison's grammar input as it is parsed,
Copyright (C) 1984, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
typedef
struct shorts
{
struct shorts *next;
short value;
}
shorts;
+20
View File
@@ -0,0 +1,20 @@
/* The version number for this version of Bison
Copyright (C) 1984, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
char *version_string = "GNU Bison version 1.16\n";
+119
View File
@@ -0,0 +1,119 @@
/* Generate transitive closure of a matrix,
Copyright (C) 1984, 1989 Free Software Foundation, Inc.
This file is part of Bison, the GNU Compiler Compiler.
Bison is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
Bison is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bison; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include "system.h"
#include "machine.h"
/* given n by n matrix of bits R, modify its contents
to be the transive closure of what was given. */
void
TC(R, n)
unsigned *R;
int n;
{
register int rowsize;
register unsigned mask;
register unsigned *rowj;
register unsigned *rp;
register unsigned *rend;
register unsigned *ccol;
unsigned *relend;
unsigned *cword;
unsigned *rowi;
rowsize = WORDSIZE(n) * sizeof(unsigned);
relend = (unsigned *) ((char *) R + (n * rowsize));
cword = R;
mask = 1;
rowi = R;
while (rowi < relend)
{
ccol = cword;
rowj = R;
while (rowj < relend)
{
if (*ccol & mask)
{
rp = rowi;
rend = (unsigned *) ((char *) rowj + rowsize);
while (rowj < rend)
*rowj++ |= *rp++;
}
else
{
rowj = (unsigned *) ((char *) rowj + rowsize);
}
ccol = (unsigned *) ((char *) ccol + rowsize);
}
mask <<= 1;
if (mask == 0)
{
mask = 1;
cword++;
}
rowi = (unsigned *) ((char *) rowi + rowsize);
}
}
/* Reflexive Transitive Closure. Same as TC
and then set all the bits on the diagonal of R. */
void
RTC(R, n)
unsigned *R;
int n;
{
register int rowsize;
register unsigned mask;
register unsigned *rp;
register unsigned *relend;
TC(R, n);
rowsize = WORDSIZE(n) * sizeof(unsigned);
relend = (unsigned *) ((char *) R + n*rowsize);
mask = 1;
rp = R;
while (rp < relend)
{
*rp |= mask;
mask <<= 1;
if (mask == 0)
{
mask = 1;
rp++;
}
rp = (unsigned *) ((char *) rp + rowsize);
}
}