Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Added the %fallback directive to the lemon parser generator and used this in the parser to make the parse tables much smaller. This reduced the size of the library by 15K. (CVS 605) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
7ac5bd293cbb2bf252f31f1571f7efac |
User & Date: | drh 2002-06-06 18:54:40.000 |
Context
2002-06-06
| ||
19:04 | Additional grammar cleanup resulting from the %fallback directive. (CVS 606) (check-in: c0cb3a012e user: drh tags: trunk) | |
18:54 | Added the %fallback directive to the lemon parser generator and used this in the parser to make the parse tables much smaller. This reduced the size of the library by 15K. (CVS 605) (check-in: 7ac5bd293c user: drh tags: trunk) | |
2002-06-02
| ||
18:22 | Fix a compiler warning. (CVS 604) (check-in: 637ee587b5 user: drh tags: trunk) | |
Changes
Changes to src/insert.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** ** $Id: insert.c,v 1.60 2002/06/06 18:54:40 drh Exp $ */ #include "sqliteInt.h" /* ** This routine is call to handle SQL of the following forms: ** ** insert into TABLE (IDLIST) values(EXPRLIST) |
︙ | ︙ | |||
547 548 549 550 551 552 553 554 | default: assert(0); } sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v)); } /* Test all CHECK constraints */ | > > | > > > | 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 | default: assert(0); } sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v)); } /* Test all CHECK constraints */ /**** TBD ****/ /* If we have an INTEGER PRIMARY KEY, make sure the primary key ** of the new record does not previously exist. Except, if this ** is an UPDATE and the primary key is not changing, that is OK. ** Also, if the conflict resolution policy is REPLACE, then we ** can skip this test. */ if( (recnoChng || !isUpdate) && pTab->iPKey>=0 ){ onError = pTab->keyConf; if( overrideError!=OE_Default ){ onError = overrideError; }else if( onError==OE_Default ){ onError = pParse->db->onError; |
︙ | ︙ | |||
589 590 591 592 593 594 595 596 597 598 599 600 601 602 | if( isUpdate ){ sqliteVdbeChangeP2(v, jumpInst1, contAddr); sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1); sqliteVdbeAddOp(v, OP_MoveTo, base, 0); } } } extra = 0; for(extra=(-1), iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){ if( aIdxUsed && aIdxUsed[iCur]==0 ) continue; extra++; sqliteVdbeAddOp(v, OP_Dup, nCol+extra, 1); for(i=0; i<pIdx->nColumn; i++){ int idx = pIdx->aiColumn[i]; | > > > > > | 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 | if( isUpdate ){ sqliteVdbeChangeP2(v, jumpInst1, contAddr); sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1); sqliteVdbeAddOp(v, OP_MoveTo, base, 0); } } } /* Test all UNIQUE constraints by creating entries for each UNIQUE ** index and making sure that duplicate entries do not already exist. ** Add the new records to the indices as we go. */ extra = 0; for(extra=(-1), iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){ if( aIdxUsed && aIdxUsed[iCur]==0 ) continue; extra++; sqliteVdbeAddOp(v, OP_Dup, nCol+extra, 1); for(i=0; i<pIdx->nColumn; i++){ int idx = pIdx->aiColumn[i]; |
︙ | ︙ | |||
638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 | } seenReplace = 1; break; } default: assert(0); } contAddr = sqliteVdbeCurrentAddr(v); sqliteVdbeChangeP2(v, jumpInst1, contAddr); sqliteVdbeChangeP2(v, jumpInst2, contAddr); } } /* ** This routine generates code to finish the INSERT or UPDATE operation ** that was started by a prior call to sqliteGenerateConstraintChecks. | > > | 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 | } seenReplace = 1; break; } default: assert(0); } contAddr = sqliteVdbeCurrentAddr(v); #if NULL_DISTINCT_FOR_UNIQUE sqliteVdbeChangeP2(v, jumpInst1, contAddr); #endif sqliteVdbeChangeP2(v, jumpInst2, contAddr); } } /* ** This routine generates code to finish the INSERT or UPDATE operation ** that was started by a prior call to sqliteGenerateConstraintChecks. |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** ** @(#) $Id: parse.y,v 1.71 2002/06/06 18:54:40 drh Exp $ */ %token_prefix TK_ %token_type {Token} %default_type {Token} %extra_argument {Parse *pParse} %syntax_error { sqliteSetString(&pParse->zErrMsg,"syntax error",0); |
︙ | ︙ | |||
106 107 108 109 110 111 112 | column ::= columnid type carglist. columnid ::= ids(X). {sqliteAddColumn(pParse,&X);} // An IDENTIFIER can be a generic identifier, or one of several // keywords. Any non-standard keyword can also be an identifier. // %type id {Token} | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | column ::= columnid type carglist. columnid ::= ids(X). {sqliteAddColumn(pParse,&X);} // An IDENTIFIER can be a generic identifier, or one of several // keywords. Any non-standard keyword can also be an identifier. // %type id {Token} //id(A) ::= ABORT(X). {A = X;} //id(A) ::= AFTER(X). {A = X;} //id(A) ::= ASC(X). {A = X;} //id(A) ::= BEFORE(X). {A = X;} //id(A) ::= BEGIN(X). {A = X;} //id(A) ::= CASCADE(X). {A = X;} //id(A) ::= CLUSTER(X). {A = X;} //id(A) ::= CONFLICT(X). {A = X;} //id(A) ::= COPY(X). {A = X;} //id(A) ::= DEFERRED(X). {A = X;} //id(A) ::= DELIMITERS(X). {A = X;} //id(A) ::= DESC(X). {A = X;} //id(A) ::= EACH(X). {A = X;} //id(A) ::= END(X). {A = X;} //id(A) ::= EXPLAIN(X). {A = X;} //id(A) ::= FAIL(X). {A = X;} //id(A) ::= FOR(X). {A = X;} //id(A) ::= FULL(X). {A = X;} id(A) ::= ID(X). {A = X;} //id(A) ::= IGNORE(X). {A = X;} //id(A) ::= IMMEDATE(X). {A = X;} //id(A) ::= INITIALLY(X). {A = X;} //id(A) ::= INSTEAD(X). {A = X;} //id(A) ::= MATCH(X). {A = X;} //id(A) ::= JOIN(X). {A = X;} //id(A) ::= KEY(X). {A = X;} //id(A) ::= OF(X). {A = X;} //id(A) ::= OFFSET(X). {A = X;} //id(A) ::= PARTIAL(X). {A = X;} //id(A) ::= PRAGMA(X). {A = X;} //id(A) ::= REPLACE(X). {A = X;} //id(A) ::= RESTRICT(X). {A = X;} //id(A) ::= ROW(X). {A = X;} //id(A) ::= STATEMENT(X). {A = X;} //id(A) ::= TEMP(X). {A = X;} //id(A) ::= TRIGGER(X). {A = X;} //id(A) ::= VACUUM(X). {A = X;} //id(A) ::= VIEW(X). {A = X;} %fallback ID ABORT AFTER ASC BEFORE BEGIN CASCADE CLUSTER CONFLICT COPY DEFERRED DELIMITERS DESC EACH END EXPLAIN FAIL FOR FULL IGNORE IMMEDIATE INITIALLY INSTEAD MATCH JOIN KEY OF OFFSET PARTIAL PRAGMA REPLACE RESTRICT ROW STATEMENT TEMP TRIGGER VACUUM VIEW. // And "ids" is an identifer-or-string. // %type ids {Token} ids(A) ::= id(X). {A = X;} ids(A) ::= STRING(X). {A = X;} |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** ** $Id: select.c,v 1.91 2002/06/06 18:54:40 drh Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. */ |
︙ | ︙ | |||
322 323 324 325 326 327 328 | } /* If the DISTINCT keyword was present on the SELECT statement ** and this row has been seen before, then do not make this row ** part of the result. */ if( distinct>=0 && pEList && pEList->nExpr>0 ){ | | < < < | < > | 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 | } /* If the DISTINCT keyword was present on the SELECT statement ** and this row has been seen before, then do not make this row ** part of the result. */ if( distinct>=0 && pEList && pEList->nExpr>0 ){ #if NULL_ALWAYS_DISTINCT sqliteVdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqliteVdbeCurrentAddr(v)+7); #endif sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1); sqliteVdbeAddOp(v, OP_Distinct, distinct, sqliteVdbeCurrentAddr(v)+3); sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0); sqliteVdbeAddOp(v, OP_Goto, 0, iContinue); sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeAddOp(v, OP_PutStrKey, distinct, 0); } |
︙ | ︙ | |||
359 360 361 362 363 364 365 | sqliteVdbeAddOp(v, OP_SortPut, 0, 0); }else /* In this mode, write each query result to the key of the temporary ** table iParm. */ if( eDest==SRT_Union ){ | | > | | 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 | sqliteVdbeAddOp(v, OP_SortPut, 0, 0); }else /* In this mode, write each query result to the key of the temporary ** table iParm. */ if( eDest==SRT_Union ){ sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT); sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0); }else /* Store the result as data using a unique key. */ if( eDest==SRT_Table || eDest==SRT_TempTable ){ sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0); sqliteVdbeAddOp(v, OP_NewRecno, iParm, 0); sqliteVdbeAddOp(v, OP_Pull, 1, 0); sqliteVdbeAddOp(v, OP_PutIntKey, iParm, 0); }else /* Construct a record from the query result, but instead of ** saving that record, use it as a key to delete elements from ** the temporary table iParm. */ if( eDest==SRT_Except ){ int addr; addr = sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT); sqliteVdbeAddOp(v, OP_NotFound, iParm, addr+3); sqliteVdbeAddOp(v, OP_Delete, iParm, 0); }else /* If we are creating a set for an "expr IN (SELECT ...)" construct, ** then there should be a single item on the stack. Write this ** item into the set table with bogus data. |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.120 2002/06/06 18:54:41 drh Exp $ */ #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> /* ** The maximum number of in-memory pages to use for the main database ** table and for temporary tables. */ #define MAX_PAGES 2000 #define TEMP_PAGES 500 /* ** If the following macro is set to 1, then NULL values are considered ** distinct for the SELECT DISTINCT statement and for UNION or EXCEPT ** compound queries. No other SQL database engine (among those tested) ** works this way except for OCELOT. But the SQL92 spec implies that ** this is how things should work. ** ** If the following macro is set to 0, then NULLs are indistinct for ** SELECT DISTINCT and for UNION. */ #define NULL_ALWAYS_DISTINCT 0 /* ** If the following macro is set to 1, then NULL values are considered ** distinct when determining whether or not two entries are the same ** in a UNIQUE index. This is the way PostgreSQL, Oracle, DB2, MySQL, ** OCELOT, and Firebird all work. The SQL92 spec explicitly says this ** is the way things are suppose to work. ** ** If the following macro is set to 0, the NULLs are indistinct for ** a UNIQUE index. In this mode, you can only have a single NULL entry ** for a column declared UNIQUE. This is the way Informix and SQL Server ** work. */ #define NULL_DISTINCT_FOR_UNIQUE 1 /* ** Integers of known sizes. These typedefs might change for architectures ** where the sizes very. Preprocessor macros are available so that the ** types can be conveniently redefined at compile-type. Like this: ** ** cc '-DUINTPTR_TYPE=long long int' ... */ |
︙ | ︙ | |||
210 211 212 213 214 215 216 | /* ** Each SQL function is defined by an instance of the following ** structure. A pointer to this structure is stored in the sqlite.aFunc ** hash table. When multiple functions have the same name, the hash table ** points to a linked list of these structures. */ struct FuncDef { | | | 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 | /* ** Each SQL function is defined by an instance of the following ** structure. A pointer to this structure is stored in the sqlite.aFunc ** hash table. When multiple functions have the same name, the hash table ** points to a linked list of these structures. */ struct FuncDef { void (*xFunc)(sqlite_func*,int,const char**); /* Regular function */ void (*xStep)(sqlite_func*,int,const char**); /* Aggregate function step */ void (*xFinalize)(sqlite_func*); /* Aggregate function finializer */ int nArg; /* Number of arguments */ void *pUserData; /* User data parameter */ FuncDef *pNext; /* Next function with same name */ }; |
︙ | ︙ | |||
280 281 282 283 284 285 286 | Trigger *pTrigger; /* List of SQL triggers on this table */ }; /* ** SQLite supports 5 different ways to resolve a contraint ** error. ROLLBACK processing means that a constraint violation | | | 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 | Trigger *pTrigger; /* List of SQL triggers on this table */ }; /* ** SQLite supports 5 different ways to resolve a contraint ** error. ROLLBACK processing means that a constraint violation ** causes the operation in process to fail and for the current transaction ** to be rolled back. ABORT processing means the operation in process ** fails and any prior changes from that one operation are backed out, ** but the transaction is not rolled back. FAIL processing means that ** the operation in progress stops and returns an error code. But prior ** changes due to the same operation are not backed out and no rollback ** occurs. IGNORE means that the particular row that caused the constraint ** error is not inserted or updated. Processing continues and no error |
︙ | ︙ |
Changes to tool/lemon.c.
︙ | ︙ | |||
125 126 127 128 129 130 131 132 133 134 135 136 137 138 | char *name; /* Name of the symbol */ int index; /* Index number for this symbol */ enum { TERMINAL, NONTERMINAL } type; /* Symbols are all either TERMINALS or NTs */ struct rule *rule; /* Linked list of rules of this (if an NT) */ int prec; /* Precedence if defined (-1 otherwise) */ enum e_assoc { LEFT, RIGHT, NONE, UNK } assoc; /* Associativity if predecence is defined */ | > | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | char *name; /* Name of the symbol */ int index; /* Index number for this symbol */ enum { TERMINAL, NONTERMINAL } type; /* Symbols are all either TERMINALS or NTs */ struct rule *rule; /* Linked list of rules of this (if an NT) */ struct symbol *fallback; /* fallback token in case this token doesn't parse */ int prec; /* Precedence if defined (-1 otherwise) */ enum e_assoc { LEFT, RIGHT, NONE, UNK } assoc; /* Associativity if predecence is defined */ |
︙ | ︙ | |||
265 266 267 268 269 270 271 272 273 274 275 276 277 278 | int vardestln; /* Line number for default non-term destructor code*/ char *filename; /* Name of the input file */ char *outname; /* Name of the current output file */ char *tokenprefix; /* A prefix added to token names in the .h file */ int nconflict; /* Number of parsing conflicts */ int tablesize; /* Size of the parse tables */ int basisflag; /* Print only basis configurations */ char *argv0; /* Name of the program */ }; #define MemoryCheck(X) if((X)==0){ \ extern void memory_error(); \ memory_error(); \ } | > | 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 | int vardestln; /* Line number for default non-term destructor code*/ char *filename; /* Name of the input file */ char *outname; /* Name of the current output file */ char *tokenprefix; /* A prefix added to token names in the .h file */ int nconflict; /* Number of parsing conflicts */ int tablesize; /* Size of the parse tables */ int basisflag; /* Print only basis configurations */ int has_fallback; /* True if any %fallback is seen in the grammer */ char *argv0; /* Name of the program */ }; #define MemoryCheck(X) if((X)==0){ \ extern void memory_error(); \ memory_error(); \ } |
︙ | ︙ | |||
1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 | /* Initialize the machine */ Strsafe_init(); Symbol_init(); State_init(); lem.argv0 = argv[0]; lem.filename = OptArg(0); lem.basisflag = basisflag; lem.nconflict = 0; lem.name = lem.include = lem.arg = lem.tokentype = lem.start = 0; lem.vartype = 0; lem.stacksize = 0; lem.error = lem.overflow = lem.failure = lem.accept = lem.tokendest = lem.tokenprefix = lem.outname = lem.extracode = 0; lem.vardest = 0; | > | 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 | /* Initialize the machine */ Strsafe_init(); Symbol_init(); State_init(); lem.argv0 = argv[0]; lem.filename = OptArg(0); lem.basisflag = basisflag; lem.has_fallback = 0; lem.nconflict = 0; lem.name = lem.include = lem.arg = lem.tokentype = lem.start = 0; lem.vartype = 0; lem.stacksize = 0; lem.error = lem.overflow = lem.failure = lem.accept = lem.tokendest = lem.tokenprefix = lem.outname = lem.extracode = 0; lem.vardest = 0; |
︙ | ︙ | |||
1718 1719 1720 1721 1722 1723 1724 | RHS_ALIAS_1, RHS_ALIAS_2, PRECEDENCE_MARK_1, PRECEDENCE_MARK_2, RESYNC_AFTER_RULE_ERROR, RESYNC_AFTER_DECL_ERROR, WAITING_FOR_DESTRUCTOR_SYMBOL, | | > > | 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 | RHS_ALIAS_1, RHS_ALIAS_2, PRECEDENCE_MARK_1, PRECEDENCE_MARK_2, RESYNC_AFTER_RULE_ERROR, RESYNC_AFTER_DECL_ERROR, WAITING_FOR_DESTRUCTOR_SYMBOL, WAITING_FOR_DATATYPE_SYMBOL, WAITING_FOR_FALLBACK_ID } state; /* The state of the parser */ struct symbol *fallback; /* The fallback token */ struct symbol *lhs; /* Left-hand side of current rule */ char *lhsalias; /* Alias for the LHS */ int nrhs; /* Number of right-hand side symbols seen */ struct symbol *rhs[MAXRHS]; /* RHS symbols */ char *alias[MAXRHS]; /* Aliases for each RHS symbol (or NULL) */ struct rule *prevrule; /* Previous rule parsed */ char *declkeyword; /* Keyword of a declaration */ |
︙ | ︙ | |||
1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 | psp->preccounter++; psp->declassoc = NONE; psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; }else if( strcmp(x,"destructor")==0 ){ psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL; }else if( strcmp(x,"type")==0 ){ psp->state = WAITING_FOR_DATATYPE_SYMBOL; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Unknown declaration keyword: \"%%%s\".",x); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; } }else{ | > > > | 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 | psp->preccounter++; psp->declassoc = NONE; psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; }else if( strcmp(x,"destructor")==0 ){ psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL; }else if( strcmp(x,"type")==0 ){ psp->state = WAITING_FOR_DATATYPE_SYMBOL; }else if( strcmp(x,"fallback")==0 ){ psp->fallback = 0; psp->state = WAITING_FOR_FALLBACK_ID; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Unknown declaration keyword: \"%%%s\".",x); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; } }else{ |
︙ | ︙ | |||
2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 | psp->state = WAITING_FOR_DECL_OR_RULE; } }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Illegal argument to %%%s: %s",psp->declkeyword,x); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; } break; case RESYNC_AFTER_RULE_ERROR: /* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; ** break; */ case RESYNC_AFTER_DECL_ERROR: if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; | > > > > > > > > > > > > > > > > > > > > > | 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 | psp->state = WAITING_FOR_DECL_OR_RULE; } }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Illegal argument to %%%s: %s",psp->declkeyword,x); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; } break; case WAITING_FOR_FALLBACK_ID: if( x[0]=='.' ){ psp->state = WAITING_FOR_DECL_OR_RULE; }else if( !isupper(x[0]) ){ ErrorMsg(psp->filename, psp->tokenlineno, "%%fallback argument \"%s\" should be a token", x); psp->errorcnt++; }else{ struct symbol *sp = Symbol_new(x); if( psp->fallback==0 ){ psp->fallback = sp; }else if( sp->fallback ){ ErrorMsg(psp->filename, psp->tokenlineno, "More than one fallback assigned to token %s", x); psp->errorcnt++; }else{ sp->fallback = psp->fallback; psp->gp->has_fallback = 1; } } break; case RESYNC_AFTER_RULE_ERROR: /* if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; ** break; */ case RESYNC_AFTER_DECL_ERROR: if( x[0]=='.' ) psp->state = WAITING_FOR_DECL_OR_RULE; |
︙ | ︙ | |||
2948 2949 2950 2951 2952 2953 2954 | { FILE *out, *in; char line[LINESIZE]; int lineno; struct state *stp; struct action *ap; struct rule *rp; | | | 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 | { FILE *out, *in; char line[LINESIZE]; int lineno; struct state *stp; struct action *ap; struct rule *rp; int i, j; int tablecnt; char *name; in = tplt_open(lemp); if( in==0 ) return; out = file_open(lemp,".c","w"); if( out==0 ){ |
︙ | ︙ | |||
3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 | if( mhflag ){ fprintf(out,"#endif\n"); lineno++; } fprintf(out,"#define YYNSTATE %d\n",lemp->nstate); lineno++; fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++; fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++; fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++; tplt_xfer(lemp->name,in,out,&lineno); /* Generate the action table. ** ** Each entry in the action table is an element of the following ** structure: ** struct yyActionEntry { | > > > | 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 | if( mhflag ){ fprintf(out,"#endif\n"); lineno++; } fprintf(out,"#define YYNSTATE %d\n",lemp->nstate); lineno++; fprintf(out,"#define YYNRULE %d\n",lemp->nrule); lineno++; fprintf(out,"#define YYERRORSYMBOL %d\n",lemp->errsym->index); lineno++; fprintf(out,"#define YYERRSYMDT yy%d\n",lemp->errsym->dtnum); lineno++; if( lemp->has_fallback ){ fprintf(out,"#define YYFALLBACK 1\n"); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); /* Generate the action table. ** ** Each entry in the action table is an element of the following ** structure: ** struct yyActionEntry { |
︙ | ︙ | |||
3142 3143 3144 3145 3146 3147 3148 | fprintf(out," { &yyActionTable[%d],%4d,%4d },\n", stp->tabstart, stp->naction, stp->tabdfltact); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); | > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > | > | 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 | fprintf(out," { &yyActionTable[%d],%4d,%4d },\n", stp->tabstart, stp->naction, stp->tabdfltact); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); /* Generate the table of fallback tokens. */ if( lemp->has_fallback ){ for(i=0; i<lemp->nterminal; i++){ struct symbol *p = lemp->symbols[i]; if( p->fallback==0 ){ fprintf(out, " 0, /* %10s => nothing */\n", p->name); }else{ fprintf(out, " %3d, /* %10s => %s */\n", p->fallback->index, p->name, p->fallback->name); } lineno++; } } tplt_xfer(lemp->name, in, out, &lineno); /* Generate a table containing the symbolic name of every symbol */ for(i=0; i<lemp->nsymbol; i++){ sprintf(line,"\"%s\",",lemp->symbols[i]->name); fprintf(out," %-15s",line); if( (i&3)==3 ){ fprintf(out,"\n"); lineno++; } } if( (i&3)!=0 ){ fprintf(out,"\n"); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); /* Generate a table containing a text string that describes every ** rule in the rule set of the grammer. This information is used ** when tracing REDUCE actions. */ for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){ assert( rp->index==i ); fprintf(out," /* %3d */ \"%s ::=", i, rp->lhs->name); for(j=0; j<rp->nrhs; j++) fprintf(out," %s",rp->rhs[j]->name); fprintf(out,"\",\n"); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which executes every time a symbol is popped from ** the stack while processing errors or while destroying the parser. ** (In other words, generate the %destructor actions) */ if( lemp->tokendest ){ for(i=0; i<lemp->nsymbol; i++){ struct symbol *sp = lemp->symbols[i]; if( sp==0 || sp->type!=TERMINAL ) continue; fprintf(out," case %d:\n",sp->index); lineno++; } for(i=0; i<lemp->nsymbol && lemp->symbols[i]->type!=TERMINAL; i++); |
︙ | ︙ | |||
3206 3207 3208 3209 3210 3211 3212 | fprintf(out," { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which execution during each REDUCE action */ for(rp=lemp->rule; rp; rp=rp->next){ fprintf(out," case %d:\n",rp->index); lineno++; | < < < | 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 | fprintf(out," { %d, %d },\n",rp->lhs->index,rp->nrhs); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which execution during each REDUCE action */ for(rp=lemp->rule; rp; rp=rp->next){ fprintf(out," case %d:\n",rp->index); lineno++; emit_code(out,rp,lemp,&lineno); fprintf(out," break;\n"); lineno++; } tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which executes if a parse fails */ tplt_print(out,lemp,lemp->failure,lemp->failureln,&lineno); |
︙ | ︙ | |||
3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 | sp = Symbol_find(x); if( sp==0 ){ sp = (struct symbol *)malloc( sizeof(struct symbol) ); MemoryCheck(sp); sp->name = Strsafe(x); sp->type = isupper(*x) ? TERMINAL : NONTERMINAL; sp->rule = 0; sp->prec = -1; sp->assoc = UNK; sp->firstset = 0; sp->lambda = FALSE; sp->destructor = 0; sp->datatype = 0; Symbol_insert(sp,sp->name); | > | 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 | sp = Symbol_find(x); if( sp==0 ){ sp = (struct symbol *)malloc( sizeof(struct symbol) ); MemoryCheck(sp); sp->name = Strsafe(x); sp->type = isupper(*x) ? TERMINAL : NONTERMINAL; sp->rule = 0; sp->fallback = 0; sp->prec = -1; sp->assoc = UNK; sp->firstset = 0; sp->lambda = FALSE; sp->destructor = 0; sp->datatype = 0; Symbol_insert(sp,sp->name); |
︙ | ︙ |
Changes to tool/lempar.c.
︙ | ︙ | |||
27 28 29 30 31 32 33 34 35 36 37 38 39 40 | ** and nonterminal numbers. "unsigned char" is ** used if there are fewer than 250 terminals ** and nonterminals. "int" is used otherwise. ** YYNOCODE is a number of type YYCODETYPE which corresponds ** to no legal terminal or nonterminal number. This ** number is used to fill in empty slots of the hash ** table. ** YYACTIONTYPE is the data type used for storing terminal ** and nonterminal numbers. "unsigned char" is ** used if there are fewer than 250 rules and ** states combined. "int" is used otherwise. ** ParseTOKENTYPE is the data type used for minor tokens given ** directly to the parser from the tokenizer. ** YYMINORTYPE is the data type used for all minor tokens. | > > > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | ** and nonterminal numbers. "unsigned char" is ** used if there are fewer than 250 terminals ** and nonterminals. "int" is used otherwise. ** YYNOCODE is a number of type YYCODETYPE which corresponds ** to no legal terminal or nonterminal number. This ** number is used to fill in empty slots of the hash ** table. ** YYFALLBACK If defined, this indicates that one or more tokens ** have fall-back values which should be used if the ** original value of the token will not parse. ** YYACTIONTYPE is the data type used for storing terminal ** and nonterminal numbers. "unsigned char" is ** used if there are fewer than 250 rules and ** states combined. "int" is used otherwise. ** ParseTOKENTYPE is the data type used for minor tokens given ** directly to the parser from the tokenizer. ** YYMINORTYPE is the data type used for all minor tokens. |
︙ | ︙ | |||
100 101 102 103 104 105 106 107 108 109 110 111 112 113 | 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[] = { %% }; /* The following structure represents a single element of the ** parser's stack. Information stored includes: ** ** + The state number for the parser at this level of the stack. ** ** + The value of the token stored at this level of the stack. | > > > > > > > > > > > > > > > > | 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | 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[] = { %% }; /* The next table maps tokens into fallback tokens. If a construct ** like the following: ** ** %fallback ID X Y Z. ** ** appears in the grammer, then ID becomes a fallback token for X, Y, ** and Z. Whenever one of the tokens X, Y, or Z is input to the parser ** but it does not parse, the type of the token is changed to ID and ** the parse is retried before an error is thrown. */ #ifdef YYFALLBACK static const YYCODETYPE yyFallback[] = { %% }; #endif /* YYFALLBACK */ /* The following structure represents a single element of the ** parser's stack. Information stored includes: ** ** + The state number for the parser at this level of the stack. ** ** + The value of the token stored at this level of the stack. |
︙ | ︙ | |||
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | }; typedef struct yyParser yyParser; #ifndef NDEBUG #include <stdio.h> static FILE *yyTraceFILE = 0; static char *yyTracePrompt = 0; /* ** Turn parser tracing on by giving a stream to which to write the trace ** and a prompt to preface each trace message. Tracing is turned off ** by making either argument NULL ** ** Inputs: ** <ul> | > > | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | }; typedef struct yyParser yyParser; #ifndef NDEBUG #include <stdio.h> static FILE *yyTraceFILE = 0; static char *yyTracePrompt = 0; #endif /* NDEBUG */ #ifndef NDEBUG /* ** Turn parser tracing on by giving a stream to which to write the trace ** and a prompt to preface each trace message. Tracing is turned off ** by making either argument NULL ** ** Inputs: ** <ul> |
︙ | ︙ | |||
161 162 163 164 165 166 167 168 169 170 171 172 173 | */ void ParseTrace(FILE *TraceFILE, char *zTracePrompt){ yyTraceFILE = TraceFILE; yyTracePrompt = zTracePrompt; if( yyTraceFILE==0 ) yyTracePrompt = 0; else if( yyTracePrompt==0 ) yyTraceFILE = 0; } /* For tracing shifts, the names of all terminals and nonterminals ** are required. The following table supplies these names */ static const char *yyTokenName[] = { %% }; | > > < < < | > > > > > > > | 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | */ void ParseTrace(FILE *TraceFILE, char *zTracePrompt){ yyTraceFILE = TraceFILE; yyTracePrompt = zTracePrompt; if( yyTraceFILE==0 ) yyTracePrompt = 0; else if( yyTracePrompt==0 ) yyTraceFILE = 0; } #endif /* NDEBUG */ #ifndef NDEBUG /* For tracing shifts, the names of all terminals and nonterminals ** are required. The following table supplies these names */ static const char *yyTokenName[] = { %% }; #endif /* NDEBUG */ #ifndef NDEBUG /* For tracing reduce actions, the names of all rules are required. */ static const char *yyRuleName[] = { %% }; #endif /* NDEBUG */ /* ** This function returns the symbolic name associated with a token ** value. */ const char *ParseTokenName(int tokenType){ #ifndef NDEBUG |
︙ | ︙ | |||
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 | */ static int yy_find_parser_action( yyParser *pParser, /* The parser */ int iLookAhead /* The look-ahead token */ ){ const yyStateEntry *pState; /* Appropriate entry in the state table */ const yyActionEntry *pAction; /* Action appropriate for the look-ahead */ /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */ pState = &yyStateTable[pParser->yytop->stateno]; if( pState->nEntry==0 ){ return pState->actionDefault; }else if( iLookAhead!=YYNOCODE ){ pAction = &pState->hashtbl[iLookAhead % pState->nEntry]; while( 1 ){ if( pAction->lookahead==iLookAhead ) return pAction->action; | > | > > > > > > > > > > > > | 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 | */ static int yy_find_parser_action( yyParser *pParser, /* The parser */ int iLookAhead /* The look-ahead token */ ){ const yyStateEntry *pState; /* Appropriate entry in the state table */ const yyActionEntry *pAction; /* Action appropriate for the look-ahead */ int iFallback; /* Fallback token */ /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */ pState = &yyStateTable[pParser->yytop->stateno]; if( pState->nEntry==0 ){ return pState->actionDefault; }else if( iLookAhead!=YYNOCODE ){ pAction = &pState->hashtbl[iLookAhead % pState->nEntry]; while( 1 ){ if( pAction->lookahead==iLookAhead ) return pAction->action; if( pAction->next==0 ) break; pAction = &pState->hashtbl[pAction->next-1]; } #ifdef YYFALLBACK if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0]) && (iFallback = yyFallback[iLookAhead])!=0 ){ #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n", yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); } #endif return yy_find_parser_action(pParser, iFallback); } #endif }else if( pState->hashtbl->lookahead!=YYNOCODE ){ return YY_NO_ACTION; } return pState->actionDefault; } /* |
︙ | ︙ | |||
380 381 382 383 384 385 386 387 388 389 390 | int yygoto; /* The next state */ int yyact; /* The next action */ YYMINORTYPE yygotominor; /* The LHS of the rule reduced */ yyStackEntry *yymsp; /* The top of the parser's stack */ int yysize; /* Amount to pop the stack */ ParseARG_FETCH; yymsp = yypParser->yytop; switch( yyruleno ){ /* Beginning here are the reduction cases. A typical example ** follows: ** case 0: | > > > > > > > > < | 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 | int yygoto; /* The next state */ int yyact; /* The next action */ YYMINORTYPE yygotominor; /* The LHS of the rule reduced */ yyStackEntry *yymsp; /* The top of the parser's stack */ int yysize; /* Amount to pop the stack */ ParseARG_FETCH; yymsp = yypParser->yytop; #ifndef NDEBUG if( yyTraceFILE && yyruleno>=0 && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){ fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt, yyRuleName[yyruleno]); } #endif /* NDEBUG */ switch( yyruleno ){ /* Beginning here are the reduction cases. A typical example ** follows: ** case 0: ** #line <lineno> <grammarfile> ** { ... } // User supplied code ** #line <lineno> <thisfile> ** break; */ %% }; |
︙ | ︙ |