mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-27 20:41:58 +03:00
Convert lemon to use a single perfect hash table for storing the actions.
This should make the resulting parser both smaller and faster. (CVS 1112) FossilOrigin-Name: 4f955c00076b16166ff837749efb84201eab3c3a
This commit is contained in:
16
manifest
16
manifest
@ -1,5 +1,5 @@
|
|||||||
C Add\ssqlite_progress_handler()\sAPI\sfor\sspecifying\san\sprogress\scallback\s(CVS\s1111)
|
C Convert\slemon\sto\suse\sa\ssingle\sperfect\shash\stable\sfor\sstoring\sthe\sactions.\nThis\sshould\smake\sthe\sresulting\sparser\sboth\ssmaller\sand\sfaster.\s(CVS\s1112)
|
||||||
D 2003-10-18T09:37:26
|
D 2003-10-21T13:16:04
|
||||||
F Makefile.in ab585a91e34bc33928a1b6181fa2f6ebd4fb17e1
|
F Makefile.in ab585a91e34bc33928a1b6181fa2f6ebd4fb17e1
|
||||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||||
@ -138,8 +138,8 @@ F test/version.test 605fd0d7e7d571370c32b12dbf395b58953de246
|
|||||||
F test/view.test 1ee12c6f8f4791a2c0655120d5562a49400cfe53
|
F test/view.test 1ee12c6f8f4791a2c0655120d5562a49400cfe53
|
||||||
F test/where.test cb3a2ed062ce4b5f08aff2d08027c6a46d68c47b
|
F test/where.test cb3a2ed062ce4b5f08aff2d08027c6a46d68c47b
|
||||||
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
|
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
|
||||||
F tool/lemon.c 93db920de9479657d04ca73e9368db7fc2969990
|
F tool/lemon.c 37d1493549a238bba56cc8a6e614191f43eac573
|
||||||
F tool/lempar.c 73a991cc3017fb34804250fa901488b5147b3717
|
F tool/lempar.c a3406868634ef5e67a8a03675317dcf5623d4740
|
||||||
F tool/memleak.awk 16ef9493dcd36146f806e75148f4bb0201a123ec
|
F tool/memleak.awk 16ef9493dcd36146f806e75148f4bb0201a123ec
|
||||||
F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
|
F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
|
||||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
|
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
|
||||||
@ -174,7 +174,7 @@ F www/speed.tcl 2f6b1155b99d39adb185f900456d1d592c4832b3
|
|||||||
F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
|
F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
|
||||||
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
|
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
|
||||||
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
||||||
P 06d4e88394217fb1390b069bad82d6ac71981f72
|
P ddb364635a207658664ea92fc677cf16a143a938
|
||||||
R cde37f606921798e43de3b54f3499f6d
|
R c217117a68a15b5b6ece4f04bcc9b9b1
|
||||||
U danielk1977
|
U drh
|
||||||
Z a955533f397af1a9a7db7d26a39908ea
|
Z 76b8ed5abf9139dcfee1277f9c2ad231
|
||||||
|
@ -1 +1 @@
|
|||||||
ddb364635a207658664ea92fc677cf16a143a938
|
4f955c00076b16166ff837749efb84201eab3c3a
|
451
tool/lemon.c
451
tool/lemon.c
@ -10,6 +10,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
extern void qsort();
|
extern void qsort();
|
||||||
extern double strtod();
|
extern double strtod();
|
||||||
@ -215,10 +216,11 @@ struct state {
|
|||||||
struct config *cfp; /* All configurations in this set */
|
struct config *cfp; /* All configurations in this set */
|
||||||
int index; /* Sequencial number for this state */
|
int index; /* Sequencial number for this state */
|
||||||
struct action *ap; /* Array of actions for this state */
|
struct action *ap; /* Array of actions for this state */
|
||||||
int naction; /* Number of actions for this state */
|
int nTknAct, nNtAct; /* Number of actions on terminals and nonterminals */
|
||||||
int tabstart; /* First index of the action table */
|
int iTknOfst, iNtOfst; /* yy_action[] offset for terminals and nonterms */
|
||||||
int tabdfltact; /* Default action */
|
int iDflt; /* Default action */
|
||||||
};
|
};
|
||||||
|
#define NO_OFFSET (-2147483647)
|
||||||
|
|
||||||
/* A followset propagation link indicates that the contents of one
|
/* A followset propagation link indicates that the contents of one
|
||||||
** configuration followset should be propagated to another whenever
|
** configuration followset should be propagated to another whenever
|
||||||
@ -394,6 +396,160 @@ char *arg;
|
|||||||
new->x.rp = (struct rule *)arg;
|
new->x.rp = (struct rule *)arg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/********************** New code to implement the "acttab" module ***********/
|
||||||
|
/*
|
||||||
|
** This module implements routines use to construct the yy_action[] table.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
** The state of the yy_action table under construction is an instance of
|
||||||
|
** the following structure
|
||||||
|
*/
|
||||||
|
typedef struct acttab acttab;
|
||||||
|
struct acttab {
|
||||||
|
int nAction; /* Number of used slots in aAction[] */
|
||||||
|
int nActionAlloc; /* Slots allocated for aAction[] */
|
||||||
|
struct {
|
||||||
|
int lookahead; /* Value of the lookahead token */
|
||||||
|
int action; /* Action to take on the given lookahead */
|
||||||
|
} *aAction, /* The yy_action[] table under construction */
|
||||||
|
*aLookahead; /* A single new transaction set */
|
||||||
|
int mnLookahead; /* Minimum aLookahead[].lookahead */
|
||||||
|
int mnAction; /* Action associated with mnLookahead */
|
||||||
|
int mxLookahead; /* Maximum aLookahead[].lookahead */
|
||||||
|
int nLookahead; /* Used slots in aLookahead[] */
|
||||||
|
int nLookaheadAlloc; /* Slots allocated in aLookahead[] */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Return the number of entries in the yy_action table */
|
||||||
|
#define acttab_size(X) ((X)->nAction)
|
||||||
|
|
||||||
|
/* The value for the N-th entry in yy_action */
|
||||||
|
#define acttab_yyaction(X,N) ((X)->aAction[N].action)
|
||||||
|
|
||||||
|
/* The value for the N-th entry in yy_lookahead */
|
||||||
|
#define acttab_yylookahead(X,N) ((X)->aAction[N].lookahead)
|
||||||
|
|
||||||
|
/* Free all memory associated with the given acttab */
|
||||||
|
void acttab_free(acttab *p){
|
||||||
|
free( p->aAction );
|
||||||
|
free( p->aLookahead );
|
||||||
|
free( p );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate a new acttab structure */
|
||||||
|
acttab *acttab_alloc(void){
|
||||||
|
acttab *p = malloc( sizeof(*p) );
|
||||||
|
if( p==0 ){
|
||||||
|
fprintf(stderr,"Unable to allocate memory for a new acttab.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
memset(p, 0, sizeof(*p));
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add a new action to the current transaction set
|
||||||
|
*/
|
||||||
|
void acttab_action(acttab *p, int lookahead, int action){
|
||||||
|
if( p->nLookahead>=p->nLookaheadAlloc ){
|
||||||
|
p->nLookaheadAlloc += 25;
|
||||||
|
p->aLookahead = realloc( p->aLookahead,
|
||||||
|
sizeof(p->aLookahead[0])*p->nLookaheadAlloc );
|
||||||
|
if( p->aLookahead==0 ){
|
||||||
|
fprintf(stderr,"malloc failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( p->nLookahead==0 ){
|
||||||
|
p->mxLookahead = lookahead;
|
||||||
|
p->mnLookahead = lookahead;
|
||||||
|
p->mnAction = action;
|
||||||
|
}else{
|
||||||
|
if( p->mxLookahead<lookahead ) p->mxLookahead = lookahead;
|
||||||
|
if( p->mnLookahead>lookahead ){
|
||||||
|
p->mnLookahead = lookahead;
|
||||||
|
p->mnAction = action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p->aLookahead[p->nLookahead].lookahead = lookahead;
|
||||||
|
p->aLookahead[p->nLookahead].action = action;
|
||||||
|
p->nLookahead++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Add the transaction set built up with prior calls to acttab_action()
|
||||||
|
** into the current action table. Then reset the transaction set back
|
||||||
|
** to an empty set in preparation for a new round of acttab_action() calls.
|
||||||
|
**
|
||||||
|
** Return the offset into the action table of the new transaction.
|
||||||
|
*/
|
||||||
|
int acttab_insert(acttab *p){
|
||||||
|
int i, j, k, n;
|
||||||
|
assert( p->nLookahead>0 );
|
||||||
|
|
||||||
|
/* Make sure we have enough space to hold the expanded action table
|
||||||
|
** in the worst case. The worst case occurs if the transaction set
|
||||||
|
** must be appended to the current action table
|
||||||
|
*/
|
||||||
|
n = p->mxLookahead - p->mnLookahead + 1;
|
||||||
|
if( p->nAction + n >= p->nActionAlloc ){
|
||||||
|
p->nActionAlloc = p->nAction + n + p->nActionAlloc + 20;
|
||||||
|
p->aAction = realloc( p->aAction,
|
||||||
|
sizeof(p->aAction[0])*p->nActionAlloc);
|
||||||
|
if( p->aAction==0 ){
|
||||||
|
fprintf(stderr,"malloc failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
for(i=p->nAction; i<p->nActionAlloc; i++){
|
||||||
|
p->aAction[i].lookahead = -1;
|
||||||
|
p->aAction[i].action = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scan the existing action table looking for an offset where we can
|
||||||
|
** insert the current transaction set. Fall out of the loop when that
|
||||||
|
** offset is found. In the worst case, we fall out of the loop when
|
||||||
|
** i reaches p->nAction, which means we append the new transaction set.
|
||||||
|
**
|
||||||
|
** i is the index in p->aAction[] where p->mnLookahead is inserted.
|
||||||
|
*/
|
||||||
|
for(i=0; i<p->nAction; i++){
|
||||||
|
if( p->aAction[i].lookahead<0 ){
|
||||||
|
for(j=0; j<p->nLookahead; j++){
|
||||||
|
k = p->aLookahead[j].lookahead - p->mnLookahead + i;
|
||||||
|
if( k<0 ) break;
|
||||||
|
if( p->aAction[k].lookahead>=0 ) break;
|
||||||
|
}
|
||||||
|
if( j==p->nLookahead ) break; /* Fits in empty slots */
|
||||||
|
}else if( p->aAction[i].lookahead==p->mnLookahead ){
|
||||||
|
if( p->aAction[i].action!=p->mnAction ) continue;
|
||||||
|
for(j=0; j<p->nLookahead; j++){
|
||||||
|
k = p->aLookahead[j].lookahead - p->mnLookahead + i;
|
||||||
|
if( k<0 || k>=p->nAction ) break;
|
||||||
|
if( p->aLookahead[j].lookahead!=p->aAction[k].lookahead ) break;
|
||||||
|
if( p->aLookahead[j].action!=p->aAction[k].action ) break;
|
||||||
|
}
|
||||||
|
if( j<p->nLookahead ) continue;
|
||||||
|
n = 0;
|
||||||
|
for(j=0; j<p->nAction; j++){
|
||||||
|
if( p->aAction[j].lookahead==j+i-p->mnLookahead ) n++;
|
||||||
|
}
|
||||||
|
if( n==p->nLookahead ) break; /* Same as a prior transaction set */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Insert transaction set at index i. */
|
||||||
|
for(j=0; j<p->nLookahead; j++){
|
||||||
|
k = p->aLookahead[j].lookahead - p->mnLookahead + i;
|
||||||
|
p->aAction[k] = p->aLookahead[j];
|
||||||
|
if( k>=p->nAction ) p->nAction = k+1;
|
||||||
|
}
|
||||||
|
p->nLookahead = 0;
|
||||||
|
|
||||||
|
/* Return the offset that is added to the lookahead in order to get the
|
||||||
|
** index into yy_action of the action */
|
||||||
|
return i - p->mnLookahead;
|
||||||
|
}
|
||||||
|
|
||||||
/********************** From the file "assert.c" ****************************/
|
/********************** From the file "assert.c" ****************************/
|
||||||
/*
|
/*
|
||||||
** A more efficient way of handling assertions.
|
** A more efficient way of handling assertions.
|
||||||
@ -1672,17 +1828,17 @@ void OptPrint(){
|
|||||||
case OPT_INT:
|
case OPT_INT:
|
||||||
case OPT_FINT:
|
case OPT_FINT:
|
||||||
fprintf(errstream," %s=<integer>%*s %s\n",op[i].label,
|
fprintf(errstream," %s=<integer>%*s %s\n",op[i].label,
|
||||||
max-strlen(op[i].label)-9,"",op[i].message);
|
(int)(max-strlen(op[i].label)-9),"",op[i].message);
|
||||||
break;
|
break;
|
||||||
case OPT_DBL:
|
case OPT_DBL:
|
||||||
case OPT_FDBL:
|
case OPT_FDBL:
|
||||||
fprintf(errstream," %s=<real>%*s %s\n",op[i].label,
|
fprintf(errstream," %s=<real>%*s %s\n",op[i].label,
|
||||||
max-strlen(op[i].label)-6,"",op[i].message);
|
(int)(max-strlen(op[i].label)-6),"",op[i].message);
|
||||||
break;
|
break;
|
||||||
case OPT_STR:
|
case OPT_STR:
|
||||||
case OPT_FSTR:
|
case OPT_FSTR:
|
||||||
fprintf(errstream," %s=<string>%*s %s\n",op[i].label,
|
fprintf(errstream," %s=<string>%*s %s\n",op[i].label,
|
||||||
max-strlen(op[i].label)-8,"",op[i].message);
|
(int)(max-strlen(op[i].label)-8),"",op[i].message);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2654,7 +2810,7 @@ struct lemon *lemp;
|
|||||||
|
|
||||||
cp = strrchr(lemp->filename,'.');
|
cp = strrchr(lemp->filename,'.');
|
||||||
if( cp ){
|
if( cp ){
|
||||||
sprintf(buf,"%.*s.lt",(unsigned long)cp-(unsigned long)lemp->filename,lemp->filename);
|
sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename);
|
||||||
}else{
|
}else{
|
||||||
sprintf(buf,"%s.lt",lemp->filename);
|
sprintf(buf,"%s.lt",lemp->filename);
|
||||||
}
|
}
|
||||||
@ -2949,15 +3105,23 @@ int mhflag; /* True if generating makeheaders output */
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** Return the name of a C datatype able to represent values between
|
** Return the name of a C datatype able to represent values between
|
||||||
** 0 and N, inclusive.
|
** lwr and upr, inclusive.
|
||||||
*/
|
*/
|
||||||
static const char *minimum_size_type(int N){
|
static const char *minimum_size_type(int lwr, int upr){
|
||||||
if( N<=255 ){
|
if( lwr>=0 ){
|
||||||
return "unsigned char";
|
if( upr<=255 ){
|
||||||
}else if( N<65535 ){
|
return "unsigned char";
|
||||||
return "unsigned short int";
|
}else if( upr<65535 ){
|
||||||
|
return "unsigned short int";
|
||||||
|
}else{
|
||||||
|
return "unsigned int";
|
||||||
|
}
|
||||||
|
}else if( lwr>=-127 && upr<=127 ){
|
||||||
|
return "signed char";
|
||||||
|
}else if( lwr>=-32767 && upr<32767 ){
|
||||||
|
return "short";
|
||||||
}else{
|
}else{
|
||||||
return "unsigned int";
|
return "int";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2972,9 +3136,11 @@ int mhflag; /* Output in makeheaders format if true */
|
|||||||
struct state *stp;
|
struct state *stp;
|
||||||
struct action *ap;
|
struct action *ap;
|
||||||
struct rule *rp;
|
struct rule *rp;
|
||||||
int i, j;
|
struct acttab *pActtab;
|
||||||
int tablecnt;
|
int i, j, n;
|
||||||
char *name;
|
char *name;
|
||||||
|
int mnTknOfst, mxTknOfst;
|
||||||
|
int mnNtOfst, mxNtOfst;
|
||||||
|
|
||||||
in = tplt_open(lemp);
|
in = tplt_open(lemp);
|
||||||
if( in==0 ) return;
|
if( in==0 ) return;
|
||||||
@ -3012,10 +3178,10 @@ int mhflag; /* Output in makeheaders format if true */
|
|||||||
/* Generate the defines */
|
/* Generate the defines */
|
||||||
fprintf(out,"/* \001 */\n");
|
fprintf(out,"/* \001 */\n");
|
||||||
fprintf(out,"#define YYCODETYPE %s\n",
|
fprintf(out,"#define YYCODETYPE %s\n",
|
||||||
minimum_size_type(lemp->nsymbol+5)); lineno++;
|
minimum_size_type(0, lemp->nsymbol+5)); lineno++;
|
||||||
fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++;
|
fprintf(out,"#define YYNOCODE %d\n",lemp->nsymbol+1); lineno++;
|
||||||
fprintf(out,"#define YYACTIONTYPE %s\n",
|
fprintf(out,"#define YYACTIONTYPE %s\n",
|
||||||
minimum_size_type(lemp->nstate+lemp->nrule+5)); lineno++;
|
minimum_size_type(0, lemp->nstate+lemp->nrule+5)); lineno++;
|
||||||
print_stack_union(out,lemp,&lineno,mhflag);
|
print_stack_union(out,lemp,&lineno,mhflag);
|
||||||
if( lemp->stacksize ){
|
if( lemp->stacksize ){
|
||||||
if( atoi(lemp->stacksize)<=0 ){
|
if( atoi(lemp->stacksize)<=0 ){
|
||||||
@ -3062,111 +3228,161 @@ int mhflag; /* Output in makeheaders format if true */
|
|||||||
}
|
}
|
||||||
tplt_xfer(lemp->name,in,out,&lineno);
|
tplt_xfer(lemp->name,in,out,&lineno);
|
||||||
|
|
||||||
/* Generate the action table.
|
/* Generate the action table and its associates:
|
||||||
**
|
**
|
||||||
** Each entry in the action table is an element of the following
|
** yy_action[] A single table containing all actions.
|
||||||
** structure:
|
** yy_lookahead[] A table containing the lookahead for each entry in
|
||||||
** struct yyActionEntry {
|
** yy_action. Used to detect hash collisions.
|
||||||
** YYCODETYPE lookahead;
|
** yy_shift_ofst[] For each state, the offset into yy_action for
|
||||||
** YYCODETYPE next;
|
** shifting terminals.
|
||||||
** YYACTIONTYPE action;
|
** yy_reduce_ofst[] For each state, the offset into yy_action for
|
||||||
** }
|
** shifting non-terminals after a reduce.
|
||||||
**
|
** yy_default[] Default action for each state.
|
||||||
** The entries are grouped into hash tables, one hash table for each
|
|
||||||
** parser state. The hash table has a size which is the number of
|
|
||||||
** entries in that table. In case of a collision, the "next" value
|
|
||||||
** contains one more than the index into the hash table of the next
|
|
||||||
** entry in the collision chain. A "next" value of 0 means the end
|
|
||||||
** of the chain has been reached.
|
|
||||||
*/
|
*/
|
||||||
tablecnt = 0;
|
|
||||||
|
|
||||||
/* Loop over parser states */
|
/* Compute the actions on all states and count them up */
|
||||||
for(i=0; i<lemp->nstate; i++){
|
|
||||||
int tablesize; /* size of the hash table */
|
|
||||||
int j,k; /* Loop counter */
|
|
||||||
int collide[2048]; /* The collision chain for the table */
|
|
||||||
struct action *table[2048]; /* Build the hash table here */
|
|
||||||
|
|
||||||
/* Find the number of actions and initialize the hash table */
|
|
||||||
stp = lemp->sorted[i];
|
|
||||||
stp->tabstart = tablecnt;
|
|
||||||
stp->naction = 0;
|
|
||||||
for(ap=stp->ap; ap; ap=ap->next){
|
|
||||||
if( ap->sp->index!=lemp->nsymbol && compute_action(lemp,ap)>=0 ){
|
|
||||||
stp->naction++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tablesize = stp->naction;
|
|
||||||
assert( tablesize<= sizeof(table)/sizeof(table[0]) );
|
|
||||||
for(j=0; j<tablesize; j++){
|
|
||||||
table[j] = 0;
|
|
||||||
collide[j] = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hash the actions into the hash table */
|
|
||||||
stp->tabdfltact = lemp->nstate + lemp->nrule;
|
|
||||||
for(ap=stp->ap; ap; ap=ap->next){
|
|
||||||
int action = compute_action(lemp,ap);
|
|
||||||
int h;
|
|
||||||
if( ap->sp->index==lemp->nsymbol ){
|
|
||||||
stp->tabdfltact = action;
|
|
||||||
}else if( action>=0 ){
|
|
||||||
h = ap->sp->index % tablesize;
|
|
||||||
ap->collide = table[h];
|
|
||||||
table[h] = ap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Resolve collisions */
|
|
||||||
for(j=k=0; j<tablesize; j++){
|
|
||||||
if( table[j] && table[j]->collide ){
|
|
||||||
while( table[k] ) k++;
|
|
||||||
table[k] = table[j]->collide;
|
|
||||||
collide[j] = k;
|
|
||||||
table[j]->collide = 0;
|
|
||||||
if( k<j ) j = k-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print the hash table */
|
|
||||||
if( tablesize>0 ){
|
|
||||||
fprintf(out,"/* State %d */\n",stp->index); lineno++;
|
|
||||||
}
|
|
||||||
for(j=0; j<tablesize; j++){
|
|
||||||
assert( table[j]!=0 );
|
|
||||||
fprintf(out," {%4d,%4d,%4d}, /* %2d: ",
|
|
||||||
table[j]->sp->index,
|
|
||||||
collide[j]+1,
|
|
||||||
compute_action(lemp,table[j]),
|
|
||||||
j+1);
|
|
||||||
PrintAction(table[j],out,22);
|
|
||||||
fprintf(out," */\n");
|
|
||||||
lineno++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update the table count */
|
|
||||||
tablecnt += tablesize;
|
|
||||||
}
|
|
||||||
tplt_xfer(lemp->name,in,out,&lineno);
|
|
||||||
lemp->tablesize = tablecnt;
|
|
||||||
|
|
||||||
/* Generate the state table
|
|
||||||
**
|
|
||||||
** Each entry is an element of the following structure:
|
|
||||||
** struct yyStateEntry {
|
|
||||||
** struct yyActionEntry *hashtbl;
|
|
||||||
** YYCODETYPE nEntry;
|
|
||||||
** YYACTIONTYPE actionDefault;
|
|
||||||
** }
|
|
||||||
*/
|
|
||||||
for(i=0; i<lemp->nstate; i++){
|
for(i=0; i<lemp->nstate; i++){
|
||||||
stp = lemp->sorted[i];
|
stp = lemp->sorted[i];
|
||||||
fprintf(out," { &yyActionTable[%d],%4d,%4d },\n",
|
stp->nTknAct = stp->nNtAct = 0;
|
||||||
stp->tabstart,
|
stp->iDflt = lemp->nstate + lemp->nrule;
|
||||||
stp->naction,
|
stp->iTknOfst = NO_OFFSET;
|
||||||
stp->tabdfltact); lineno++;
|
stp->iNtOfst = NO_OFFSET;
|
||||||
|
for(ap=stp->ap; ap; ap=ap->next){
|
||||||
|
if( compute_action(lemp,ap)>=0 ){
|
||||||
|
if( ap->sp->index<lemp->nterminal ){
|
||||||
|
stp->nTknAct++;
|
||||||
|
}else if( ap->sp->index<lemp->nsymbol ){
|
||||||
|
stp->nNtAct++;
|
||||||
|
}else{
|
||||||
|
stp->iDflt = compute_action(lemp, ap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
mxTknOfst = mnTknOfst = 0;
|
||||||
|
mxNtOfst = mnNtOfst = 0;
|
||||||
|
|
||||||
|
/* Compute the action table. Do this in two passes. The first
|
||||||
|
** pass does all entries with two or more actions and the second
|
||||||
|
** pass does all states with a single action.
|
||||||
|
*/
|
||||||
|
pActtab = acttab_alloc();
|
||||||
|
for(j=0; j<=1; j++){
|
||||||
|
for(i=0; i<lemp->nstate; i++){
|
||||||
|
stp = lemp->sorted[i];
|
||||||
|
if( (j==0 && stp->nTknAct>=2) || (j==1 && stp->nTknAct==1) ){
|
||||||
|
for(ap=stp->ap; ap; ap=ap->next){
|
||||||
|
int action;
|
||||||
|
if( ap->sp->index>=lemp->nterminal ) continue;
|
||||||
|
action = compute_action(lemp, ap);
|
||||||
|
if( action<0 ) continue;
|
||||||
|
acttab_action(pActtab, ap->sp->index, action);
|
||||||
|
}
|
||||||
|
stp->iTknOfst = acttab_insert(pActtab);
|
||||||
|
if( stp->iTknOfst<mnTknOfst ) mnTknOfst = stp->iTknOfst;
|
||||||
|
if( stp->iTknOfst>mxTknOfst ) mxTknOfst = stp->iTknOfst;
|
||||||
|
}
|
||||||
|
if( (j==0 && stp->nNtAct>=2) || (j==1 && stp->nNtAct==1) ){
|
||||||
|
for(ap=stp->ap; ap; ap=ap->next){
|
||||||
|
int action;
|
||||||
|
if( ap->sp->index<lemp->nterminal ) continue;
|
||||||
|
if( ap->sp->index==lemp->nsymbol ) continue;
|
||||||
|
action = compute_action(lemp, ap);
|
||||||
|
if( action<0 ) continue;
|
||||||
|
acttab_action(pActtab, ap->sp->index, action);
|
||||||
|
}
|
||||||
|
stp->iNtOfst = acttab_insert(pActtab);
|
||||||
|
if( stp->iNtOfst<mnNtOfst ) mnNtOfst = stp->iNtOfst;
|
||||||
|
if( stp->iNtOfst>mxNtOfst ) mxNtOfst = stp->iNtOfst;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Output the yy_action table */
|
||||||
|
fprintf(out,"static YYACTIONTYPE yy_action[] = {\n"); lineno++;
|
||||||
|
n = acttab_size(pActtab);
|
||||||
|
for(i=j=0; i<n; i++){
|
||||||
|
int action = acttab_yyaction(pActtab, i);
|
||||||
|
if( action<0 ) action = lemp->nsymbol + lemp->nrule + 2;
|
||||||
|
fprintf(out, " %4d,", action);
|
||||||
|
if( j==9 || i==n-1 ){
|
||||||
|
fprintf(out, "\n"); lineno++;
|
||||||
|
j = 0;
|
||||||
|
}else{
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(out, "};\n"); lineno++;
|
||||||
|
|
||||||
|
/* Output the yy_lookahead table */
|
||||||
|
fprintf(out,"static YYCODETYPE yy_lookahead[] = {\n"); lineno++;
|
||||||
|
for(i=j=0; i<n; i++){
|
||||||
|
int la = acttab_yylookahead(pActtab, i);
|
||||||
|
if( la<0 ) la = lemp->nsymbol;
|
||||||
|
fprintf(out, " %4d,", la);
|
||||||
|
if( j==9 || i==n-1 ){
|
||||||
|
fprintf(out, "\n"); lineno++;
|
||||||
|
j = 0;
|
||||||
|
}else{
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(out, "};\n"); lineno++;
|
||||||
|
|
||||||
|
/* Output the yy_shift_ofst[] table */
|
||||||
|
fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
|
||||||
|
fprintf(out, "static %s yy_shift_ofst[] = {\n",
|
||||||
|
minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
|
||||||
|
n = lemp->nstate;
|
||||||
|
for(i=j=0; i<n; i++){
|
||||||
|
int ofst;
|
||||||
|
stp = lemp->sorted[i];
|
||||||
|
ofst = stp->iTknOfst;
|
||||||
|
if( ofst==NO_OFFSET ) ofst = mnTknOfst - 1;
|
||||||
|
fprintf(out, " %4d,", ofst);
|
||||||
|
if( j==9 || i==n-1 ){
|
||||||
|
fprintf(out, "\n"); lineno++;
|
||||||
|
j = 0;
|
||||||
|
}else{
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(out, "};\n"); lineno++;
|
||||||
|
|
||||||
|
/* Output the yy_reduce_ofst[] table */
|
||||||
|
fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
|
||||||
|
fprintf(out, "static %s yy_reduce_ofst[] = {\n",
|
||||||
|
minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
|
||||||
|
n = lemp->nstate;
|
||||||
|
for(i=j=0; i<n; i++){
|
||||||
|
int ofst;
|
||||||
|
stp = lemp->sorted[i];
|
||||||
|
ofst = stp->iNtOfst;
|
||||||
|
if( ofst==NO_OFFSET ) ofst = mnNtOfst - 1;
|
||||||
|
fprintf(out, " %4d,", ofst);
|
||||||
|
if( j==9 || i==n-1 ){
|
||||||
|
fprintf(out, "\n"); lineno++;
|
||||||
|
j = 0;
|
||||||
|
}else{
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(out, "};\n"); lineno++;
|
||||||
|
|
||||||
|
/* Output the default action table */
|
||||||
|
fprintf(out, "static YYACTIONTYPE yy_default[] = {\n"); lineno++;
|
||||||
|
n = lemp->nstate;
|
||||||
|
for(i=j=0; i<n; i++){
|
||||||
|
stp = lemp->sorted[i];
|
||||||
|
fprintf(out, " %4d,", stp->iDflt);
|
||||||
|
if( j==9 || i==n-1 ){
|
||||||
|
fprintf(out, "\n"); lineno++;
|
||||||
|
j = 0;
|
||||||
|
}else{
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(out, "};\n"); lineno++;
|
||||||
tplt_xfer(lemp->name,in,out,&lineno);
|
tplt_xfer(lemp->name,in,out,&lineno);
|
||||||
|
|
||||||
/* Generate the table of fallback tokens.
|
/* Generate the table of fallback tokens.
|
||||||
@ -3336,7 +3552,6 @@ struct lemon *lemp;
|
|||||||
struct rule *rp, *rp2, *rbest;
|
struct rule *rp, *rp2, *rbest;
|
||||||
int nbest, n;
|
int nbest, n;
|
||||||
int i;
|
int i;
|
||||||
int cnt;
|
|
||||||
|
|
||||||
for(i=0; i<lemp->nstate; i++){
|
for(i=0; i<lemp->nstate; i++){
|
||||||
stp = lemp->sorted[i];
|
stp = lemp->sorted[i];
|
||||||
|
152
tool/lempar.c
152
tool/lempar.c
@ -58,55 +58,49 @@
|
|||||||
#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
|
#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
|
||||||
#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
|
#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
|
||||||
#define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
|
#define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
|
||||||
/* Next is the action table. Each entry in this table contains
|
|
||||||
**
|
|
||||||
** + An integer which is the number representing the look-ahead
|
|
||||||
** token
|
|
||||||
**
|
|
||||||
** + An integer indicating what action to take. Number (N) between
|
|
||||||
** 0 and YYNSTATE-1 mean shift the look-ahead and go to state N.
|
|
||||||
** Numbers between YYNSTATE and YYNSTATE+YYNRULE-1 mean reduce by
|
|
||||||
** rule N-YYNSTATE. Number YYNSTATE+YYNRULE means that a syntax
|
|
||||||
** error has occurred. Number YYNSTATE+YYNRULE+1 means the parser
|
|
||||||
** accepts its input.
|
|
||||||
**
|
|
||||||
** + A pointer to the next entry with the same hash value.
|
|
||||||
**
|
|
||||||
** The action table is really a series of hash tables. Each hash
|
|
||||||
** table contains a number of entries which is a power of two. The
|
|
||||||
** "state" table (which follows) contains information about the starting
|
|
||||||
** point and size of each hash table.
|
|
||||||
*/
|
|
||||||
struct yyActionEntry {
|
|
||||||
YYCODETYPE lookahead; /* The value of the look-ahead token */
|
|
||||||
YYCODETYPE next; /* Next entry + 1. Zero at end of collision chain */
|
|
||||||
YYACTIONTYPE action; /* Action to take for this look-ahead */
|
|
||||||
};
|
|
||||||
typedef struct yyActionEntry yyActionEntry;
|
|
||||||
static const yyActionEntry yyActionTable[] = {
|
|
||||||
%%
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The state table contains information needed to look up the correct
|
/* Next are that ables used to determine what action to take based on the
|
||||||
** action in the action table, given the current state of the parser.
|
** current state and lookahead token. These tables are used to implement
|
||||||
** Information needed includes:
|
** functions that take a state number and lookahead value and return an
|
||||||
|
** action integer.
|
||||||
**
|
**
|
||||||
** + A pointer to the start of the action hash table in yyActionTable.
|
** The action integer is a number N between
|
||||||
|
** 0 and YYNSTATE-1 mean shift the look-ahead and go to state N.
|
||||||
|
** Numbers between YYNSTATE and YYNSTATE+YYNRULE-1 mean reduce by
|
||||||
|
** rule N-YYNSTATE. Number YYNSTATE+YYNRULE means that a syntax
|
||||||
|
** error has occurred. Number YYNSTATE+YYNRULE+1 means the parser
|
||||||
|
** accepts its input.
|
||||||
**
|
**
|
||||||
** + The number of entries in the action hash table.
|
** The action table is constructed as a single large hash table with
|
||||||
|
** a perfect hash. Given state S and lookahead X, the action is computed
|
||||||
|
** as
|
||||||
**
|
**
|
||||||
** + The default action. This is the action to take if no entry for
|
** yy_action[ yy_shift_ofst[S] + X ]
|
||||||
** the given look-ahead is found in the action hash table.
|
**
|
||||||
|
** If the index yy_shift_ofst[S]+X is out of range or if the value
|
||||||
|
** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
|
||||||
|
** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
|
||||||
|
** and that yy_default[S] should be used instead.
|
||||||
|
**
|
||||||
|
** The formula above is for computing the action when the lookahead is
|
||||||
|
** a terminal symbol. If the lookahead is a non-terminal (as occurs after
|
||||||
|
** a reduce action) then the yy_reduce_ofst[] array is used in place of
|
||||||
|
** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
|
||||||
|
** YY_SHIFT_USE_DFLT.
|
||||||
|
**
|
||||||
|
** The following are the tables generated in this section:
|
||||||
|
**
|
||||||
|
** yy_action[] A single table containing all actions.
|
||||||
|
** yy_lookahead[] A table containing the lookahead for each entry in
|
||||||
|
** yy_action. Used to detect hash collisions.
|
||||||
|
** yy_shift_ofst[] For each state, the offset into yy_action for
|
||||||
|
** shifting terminals.
|
||||||
|
** yy_reduce_ofst[] For each state, the offset into yy_action for
|
||||||
|
** shifting non-terminals after a reduce.
|
||||||
|
** yy_default[] Default action for each state.
|
||||||
*/
|
*/
|
||||||
struct yyStateEntry {
|
|
||||||
const yyActionEntry *hashtbl; /* Start of the hash table in yyActionTable */
|
|
||||||
YYCODETYPE nEntry; /* Number of entries in action hash table */
|
|
||||||
YYACTIONTYPE actionDefault; /* Default action if look-ahead not found */
|
|
||||||
};
|
|
||||||
typedef struct yyStateEntry yyStateEntry;
|
|
||||||
static const yyStateEntry yyStateTable[] = {
|
|
||||||
%%
|
%%
|
||||||
};
|
#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
|
||||||
|
|
||||||
/* The next table maps tokens into fallback tokens. If a construct
|
/* The next table maps tokens into fallback tokens. If a construct
|
||||||
** like the following:
|
** like the following:
|
||||||
@ -312,32 +306,31 @@ void ParseFree(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Find the appropriate action for a parser given the look-ahead token.
|
** Find the appropriate action for a parser given the terminal
|
||||||
|
** look-ahead token iLookAhead.
|
||||||
**
|
**
|
||||||
** If the look-ahead token is YYNOCODE, then check to see if the action is
|
** If the look-ahead token is YYNOCODE, then check to see if the action is
|
||||||
** independent of the look-ahead. If it is, return the action, otherwise
|
** independent of the look-ahead. If it is, return the action, otherwise
|
||||||
** return YY_NO_ACTION.
|
** return YY_NO_ACTION.
|
||||||
*/
|
*/
|
||||||
static int yy_find_parser_action(
|
static int yy_find_shift_action(
|
||||||
yyParser *pParser, /* The parser */
|
yyParser *pParser, /* The parser */
|
||||||
int iLookAhead /* The look-ahead token */
|
int iLookAhead /* The look-ahead token */
|
||||||
){
|
){
|
||||||
const yyStateEntry *pState; /* Appropriate entry in the state table */
|
int i;
|
||||||
const yyActionEntry *pAction; /* Action appropriate for the look-ahead */
|
|
||||||
int iFallback; /* Fallback token */
|
|
||||||
|
|
||||||
/* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
|
/* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
|
||||||
pState = &yyStateTable[pParser->yytop->stateno];
|
i = yy_shift_ofst[pParser->yytop->stateno];
|
||||||
if( pState->nEntry==0 ){
|
if( i==YY_SHIFT_USE_DFLT ){
|
||||||
return pState->actionDefault;
|
return yy_default[pParser->yytop->stateno];
|
||||||
}else if( iLookAhead!=YYNOCODE ){
|
}
|
||||||
pAction = &pState->hashtbl[iLookAhead % pState->nEntry];
|
if( iLookAhead==YYNOCODE ){
|
||||||
while( 1 ){
|
return YY_NO_ACTION;
|
||||||
if( pAction->lookahead==iLookAhead ) return pAction->action;
|
}
|
||||||
if( pAction->next==0 ) break;
|
i += iLookAhead;
|
||||||
pAction = &pState->hashtbl[pAction->next-1];
|
if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
|
||||||
}
|
|
||||||
#ifdef YYFALLBACK
|
#ifdef YYFALLBACK
|
||||||
|
int iFallback; /* Fallback token */
|
||||||
if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
|
if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
|
||||||
&& (iFallback = yyFallback[iLookAhead])!=0 ){
|
&& (iFallback = yyFallback[iLookAhead])!=0 ){
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
@ -346,13 +339,42 @@ static int yy_find_parser_action(
|
|||||||
yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
|
yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return yy_find_parser_action(pParser, iFallback);
|
return yy_find_shift_action(pParser, iFallback);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}else if( pState->hashtbl->lookahead!=YYNOCODE ){
|
return yy_default[pParser->yytop->stateno];
|
||||||
|
}else{
|
||||||
|
return yy_action[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Find the appropriate action for a parser given the non-terminal
|
||||||
|
** look-ahead token iLookAhead.
|
||||||
|
**
|
||||||
|
** If the look-ahead token is YYNOCODE, then check to see if the action is
|
||||||
|
** independent of the look-ahead. If it is, return the action, otherwise
|
||||||
|
** return YY_NO_ACTION.
|
||||||
|
*/
|
||||||
|
static int yy_find_reduce_action(
|
||||||
|
yyParser *pParser, /* The parser */
|
||||||
|
int iLookAhead /* The look-ahead token */
|
||||||
|
){
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = yy_reduce_ofst[pParser->yytop->stateno];
|
||||||
|
if( i==YY_REDUCE_USE_DFLT ){
|
||||||
|
return yy_default[pParser->yytop->stateno];
|
||||||
|
}
|
||||||
|
if( iLookAhead==YYNOCODE ){
|
||||||
return YY_NO_ACTION;
|
return YY_NO_ACTION;
|
||||||
}
|
}
|
||||||
return pState->actionDefault;
|
i += iLookAhead;
|
||||||
|
if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
|
||||||
|
return yy_default[pParser->yytop->stateno];
|
||||||
|
}else{
|
||||||
|
return yy_action[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -447,7 +469,7 @@ static void yy_reduce(
|
|||||||
yysize = yyRuleInfo[yyruleno].nrhs;
|
yysize = yyRuleInfo[yyruleno].nrhs;
|
||||||
yypParser->yyidx -= yysize;
|
yypParser->yyidx -= yysize;
|
||||||
yypParser->yytop -= yysize;
|
yypParser->yytop -= yysize;
|
||||||
yyact = yy_find_parser_action(yypParser,yygoto);
|
yyact = yy_find_reduce_action(yypParser,yygoto);
|
||||||
if( yyact < YYNSTATE ){
|
if( yyact < YYNSTATE ){
|
||||||
yy_shift(yypParser,yyact,yygoto,&yygotominor);
|
yy_shift(yypParser,yyact,yygoto,&yygotominor);
|
||||||
}else if( yyact == YYNSTATE + YYNRULE + 1 ){
|
}else if( yyact == YYNSTATE + YYNRULE + 1 ){
|
||||||
@ -559,7 +581,7 @@ void Parse(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
do{
|
do{
|
||||||
yyact = yy_find_parser_action(yypParser,yymajor);
|
yyact = yy_find_shift_action(yypParser,yymajor);
|
||||||
if( yyact<YYNSTATE ){
|
if( yyact<YYNSTATE ){
|
||||||
yy_shift(yypParser,yyact,yymajor,&yyminorunion);
|
yy_shift(yypParser,yyact,yymajor,&yyminorunion);
|
||||||
yypParser->yyerrcnt--;
|
yypParser->yyerrcnt--;
|
||||||
@ -612,7 +634,7 @@ void Parse(
|
|||||||
while(
|
while(
|
||||||
yypParser->yyidx >= 0 &&
|
yypParser->yyidx >= 0 &&
|
||||||
yypParser->yytop->major != YYERRORSYMBOL &&
|
yypParser->yytop->major != YYERRORSYMBOL &&
|
||||||
(yyact = yy_find_parser_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE
|
(yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE
|
||||||
){
|
){
|
||||||
yy_pop_parser_stack(yypParser);
|
yy_pop_parser_stack(yypParser);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user