Enhance Lemon so that if reduce code contains a comment of the form

"/*A-overwrites-X*/" then a LHS label A is allowed to overwrite the
RHS label X.

FossilOrigin-Name: 5cfe9545d478a2c500083613dd20e14b2ffce645
This commit is contained in:
drh 2016-02-17 04:33:10 +00:00
parent dabd04c656
commit cf82f0d3d2
4 changed files with 66 additions and 48 deletions

View File

@ -1,5 +1,5 @@
C Further\simprovements\sto\sthe\sLemon-generated\scode\sfor\syy_reduce().
D 2016-02-17T01:46:19.413
C Enhance\sLemon\sso\sthat\sif\sreduce\scode\scontains\sa\scomment\sof\sthe\sform\n"/*A-overwrites-X*/"\sthen\sa\sLHS\slabel\sA\sis\sallowed\sto\soverwrite\sthe\nRHS\slabel\sX.
D 2016-02-17T04:33:10.506
F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 30f075dc4f27a07abb76088946b2944178d85347
@ -337,7 +337,7 @@ F src/os_win.c f0d7aa603eb6262143d7169a222aea07c4fca91d
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
F src/pager.c 6812f3803951774b56abded396171e1c12b0b003
F src/pager.h f3eb324a3ff2408b28bab7e81c1c55c13720f865
F src/parse.y b845cfc4ba7d96b843856007a3c09c5b7ca2878f
F src/parse.y 8c2f7e7e12cb03ddeaa204463198978aab2dcde9
F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df
F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545
F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051
@ -1378,7 +1378,7 @@ F tool/fuzzershell.c 94019b185caceffc9f7c7b678a6489e42bc2aefa
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/lemon.c 61844c3d01865473bce2dc8134e17346cda07000
F tool/lemon.c 31a7325a4407fa35af7e5913b67517debae8181b
F tool/lempar.c c7dde8fae568759a1a136b1acf35c4084864d035
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
@ -1427,7 +1427,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 4bb94c7c4c3cb3ccad72c2451d88684130dde845
R 8570435db7ea690b60e76be3d8d02f8b
P ef95a7d6490e33a9af4bc7b4b622de7328742ca7
R f9d92e1ecf92fd9298e3c4ee80590b18
U drh
Z bc476c236d739b2c3e79f3d57d12535c
Z 42e27a9e216e6c463abe3b883471bdc4

View File

@ -1 +1 @@
ef95a7d6490e33a9af4bc7b4b622de7328742ca7
5cfe9545d478a2c500083613dd20e14b2ffce645

View File

@ -138,9 +138,9 @@ trans_opt ::= TRANSACTION.
trans_opt ::= TRANSACTION nm.
%type transtype {int}
transtype(A) ::= . {A = TK_DEFERRED;}
transtype(A) ::= DEFERRED(X). {A = @X;}
transtype(A) ::= IMMEDIATE(X). {A = @X;}
transtype(A) ::= EXCLUSIVE(X). {A = @X;}
transtype(A) ::= DEFERRED(X). {A = @X; /*A-overwrites-X*/}
transtype(A) ::= IMMEDIATE(X). {A = @X; /*A-overwrites-X*/}
transtype(A) ::= EXCLUSIVE(X). {A = @X; /*A-overwrites-X*/}
cmd ::= COMMIT trans_opt. {sqlite3CommitTransaction(pParse);}
cmd ::= END trans_opt. {sqlite3CommitTransaction(pParse);}
cmd ::= ROLLBACK trans_opt. {sqlite3RollbackTransaction(pParse);}
@ -456,7 +456,7 @@ select(A) ::= with(W) selectnowith(X). {
}else{
sqlite3WithDelete(pParse->db, W);
}
A = p;
A = p; /*A-overwrites-W*/
}
selectnowith(A) ::= oneselect(A).
@ -484,9 +484,9 @@ selectnowith(A) ::= selectnowith(A) multiselect_op(Y) oneselect(Z). {
A = pRhs;
}
%type multiselect_op {int}
multiselect_op(A) ::= UNION(OP). {A = @OP;}
multiselect_op(A) ::= UNION(OP). {A = @OP; /*A-overwrites-OP*/}
multiselect_op(A) ::= UNION ALL. {A = TK_ALL;}
multiselect_op(A) ::= EXCEPT|INTERSECT(OP). {A = @OP;}
multiselect_op(A) ::= EXCEPT|INTERSECT(OP). {A = @OP; /*A-overwrites-OP*/}
%endif SQLITE_OMIT_COMPOUND_SELECT
oneselect(A) ::= SELECT(S) distinct(D) selcollist(W) from(X) where_opt(Y)
groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). {
@ -648,14 +648,17 @@ dbnm(A) ::= DOT nm(X). {A = X;}
%type fullname {SrcList*}
%destructor fullname {sqlite3SrcListDelete(pParse->db, $$);}
fullname(A) ::= nm(X) dbnm(Y). {A = sqlite3SrcListAppend(pParse->db,0,&X,&Y);}
fullname(A) ::= nm(X) dbnm(Y).
{A = sqlite3SrcListAppend(pParse->db,0,&X,&Y); /*A-overwrites-X*/}
%type joinop {int}
joinop(X) ::= COMMA|JOIN. { X = JT_INNER; }
joinop(X) ::= JOIN_KW(A) JOIN. { X = sqlite3JoinType(pParse,&A,0,0); }
joinop(X) ::= JOIN_KW(A) nm(B) JOIN. { X = sqlite3JoinType(pParse,&A,&B,0); }
joinop(X) ::= JOIN_KW(A) JOIN.
{X = sqlite3JoinType(pParse,&A,0,0); /*X-overwrites-A*/}
joinop(X) ::= JOIN_KW(A) nm(B) JOIN.
{X = sqlite3JoinType(pParse,&A,&B,0); /*X-overwrites-A*/}
joinop(X) ::= JOIN_KW(A) nm(B) nm(C) JOIN.
{ X = sqlite3JoinType(pParse,&A,&B,&C); }
{X = sqlite3JoinType(pParse,&A,&B,&C);/*X-overwrites-A*/}
%type on_opt {Expr*}
%destructor on_opt {sqlite3ExprDelete(pParse->db, $$);}
@ -700,7 +703,7 @@ sortlist(A) ::= sortlist(A) COMMA expr(Y) sortorder(Z). {
sqlite3ExprListSetSortOrder(A,Z);
}
sortlist(A) ::= expr(Y) sortorder(Z). {
A = sqlite3ExprListAppend(pParse,0,Y.pExpr);
A = sqlite3ExprListAppend(pParse,0,Y.pExpr); /*A-overwrites-Y*/
sqlite3ExprListSetSortOrder(A,Z);
}
@ -825,7 +828,7 @@ idlist_opt(A) ::= LP idlist(X) RP. {A = X;}
idlist(A) ::= idlist(A) COMMA nm(Y).
{A = sqlite3IdListAppend(pParse->db,A,&Y);}
idlist(A) ::= nm(Y).
{A = sqlite3IdListAppend(pParse->db,0,&Y);}
{A = sqlite3IdListAppend(pParse->db,0,&Y); /*A-overwrites-Y*/}
/////////////////////////// Expression Processing /////////////////////////////
//
@ -864,16 +867,16 @@ expr(A) ::= JOIN_KW(X). {spanExpr(&A, pParse, TK_ID, &X);}
expr(A) ::= nm(X) DOT nm(Y). {
Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y);
spanSet(&A,&X,&Y); /*A-overwrites-X*/
A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
spanSet(&A,&X,&Y);
}
expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). {
Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y);
Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Z);
Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0);
spanSet(&A,&X,&Z); /*A-overwrites-X*/
A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
spanSet(&A,&X,&Z);
}
term(A) ::= INTEGER|FLOAT|BLOB(X). {spanExpr(&A, pParse, @X, &X);}
term(A) ::= STRING(X). {spanExpr(&A, pParse, @X, &X);}
@ -961,7 +964,7 @@ expr(A) ::= expr(A) STAR|SLASH|REM(OP) expr(Y).
{spanBinaryExpr(pParse,@OP,&A,&Y);}
expr(A) ::= expr(A) CONCAT(OP) expr(Y). {spanBinaryExpr(pParse,@OP,&A,&Y);}
%type likeop {struct LikeOp}
likeop(A) ::= LIKE_KW|MATCH(X). {A.eOperator = X; A.bNot = 0;}
likeop(A) ::= LIKE_KW|MATCH(X). {A.eOperator = X; A.bNot = 0;/*A-overwrites-X*/}
likeop(A) ::= NOT LIKE_KW|MATCH(X). {A.eOperator = X; A.bNot = 1;}
expr(A) ::= expr(A) likeop(OP) expr(Y). [LIKE_KW] {
ExprList *pList;
@ -1203,7 +1206,7 @@ case_else(A) ::= ELSE expr(X). {A = X.pExpr;}
case_else(A) ::= . {A = 0;}
%type case_operand {Expr*}
%destructor case_operand {sqlite3ExprDelete(pParse->db, $$);}
case_operand(A) ::= expr(X). {A = X.pExpr;}
case_operand(A) ::= expr(X). {A = X.pExpr; /*A-overwrites-X*/}
case_operand(A) ::= . {A = 0;}
%type exprlist {ExprList*}
@ -1216,7 +1219,7 @@ exprlist(A) ::= . {A = 0;}
nexprlist(A) ::= nexprlist(A) COMMA expr(Y).
{A = sqlite3ExprListAppend(pParse,A,Y.pExpr);}
nexprlist(A) ::= expr(Y).
{A = sqlite3ExprListAppend(pParse,0,Y.pExpr);}
{A = sqlite3ExprListAppend(pParse,0,Y.pExpr); /*A-overwrites-Y*/}
///////////////////////////// The CREATE INDEX command ///////////////////////
@ -1284,7 +1287,7 @@ eidlist(A) ::= eidlist(A) COMMA nm(Y) collate(C) sortorder(Z). {
A = parserAddExprIdListTerm(pParse, A, &Y, C, Z);
}
eidlist(A) ::= nm(Y) collate(C) sortorder(Z). {
A = parserAddExprIdListTerm(pParse, 0, &Y, C, Z);
A = parserAddExprIdListTerm(pParse, 0, &Y, C, Z); /*A-overwrites-Y*/
}
%type collate {int}
@ -1316,15 +1319,15 @@ cmd ::= PRAGMA nm(X) dbnm(Z) EQ minus_num(Y).
cmd ::= PRAGMA nm(X) dbnm(Z) LP minus_num(Y) RP.
{sqlite3Pragma(pParse,&X,&Z,&Y,1);}
nmnum(A) ::= plus_num(X). {A = X;}
nmnum(A) ::= nm(X). {A = X;}
nmnum(A) ::= ON(X). {A = X;}
nmnum(A) ::= DELETE(X). {A = X;}
nmnum(A) ::= DEFAULT(X). {A = X;}
nmnum(A) ::= plus_num(A).
nmnum(A) ::= nm(A).
nmnum(A) ::= ON(A).
nmnum(A) ::= DELETE(A).
nmnum(A) ::= DEFAULT(A).
%endif SQLITE_OMIT_PRAGMA
%token_class number INTEGER|FLOAT.
plus_num(A) ::= PLUS number(X). {A = X;}
plus_num(A) ::= number(X). {A = X;}
plus_num(A) ::= number(A).
minus_num(A) ::= MINUS number(X). {A = X;}
//////////////////////////// The CREATE TRIGGER command /////////////////////
@ -1341,7 +1344,7 @@ trigger_decl(A) ::= temp(T) TRIGGER ifnotexists(NOERR) nm(B) dbnm(Z)
trigger_time(C) trigger_event(D)
ON fullname(E) foreach_clause when_clause(G). {
sqlite3BeginTrigger(pParse, &B, &Z, C, D.a, D.b, E, G, T, NOERR);
A = (Z.n==0?B:Z);
A = (Z.n==0?B:Z); /*A-overwrites-T*/
}
%type trigger_time {int}
@ -1352,9 +1355,9 @@ trigger_time(A) ::= . { A = TK_BEFORE; }
%type trigger_event {struct TrigEvent}
%destructor trigger_event {sqlite3IdListDelete(pParse->db, $$.b);}
trigger_event(A) ::= DELETE|INSERT(OP). {A.a = @OP; A.b = 0;}
trigger_event(A) ::= UPDATE(OP). {A.a = @OP; A.b = 0;}
trigger_event(A) ::= UPDATE OF idlist(X). {A.a = TK_UPDATE; A.b = X;}
trigger_event(A) ::= DELETE|INSERT(X). {A.a = @X; /*A-overwrites-X*/ A.b = 0;}
trigger_event(A) ::= UPDATE(X). {A.a = @X; /*A-overwrites-X*/ A.b = 0;}
trigger_event(A) ::= UPDATE OF idlist(X).{A.a = TK_UPDATE; A.b = X;}
foreach_clause ::= .
foreach_clause ::= FOR EACH ROW.
@ -1423,24 +1426,23 @@ trigger_cmd(A) ::= DELETE FROM trnm(X) tridxby where_opt(Y).
{A = sqlite3TriggerDeleteStep(pParse->db, &X, Y);}
// SELECT
trigger_cmd(A) ::= select(X). {A = sqlite3TriggerSelectStep(pParse->db, X); }
trigger_cmd(A) ::= select(X).
{A = sqlite3TriggerSelectStep(pParse->db, X); /*A-overwrites-X*/}
// The special RAISE expression that may occur in trigger programs
expr(A) ::= RAISE(X) LP IGNORE RP(Y). {
spanSet(&A,&X,&Y); /*A-overwrites-X*/
A.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
if( A.pExpr ){
A.pExpr->affinity = OE_Ignore;
}
A.zStart = X.z;
A.zEnd = &Y.z[Y.n];
}
expr(A) ::= RAISE(X) LP raisetype(T) COMMA nm(Z) RP(Y). {
spanSet(&A,&X,&Y); /*A-overwrites-X*/
A.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &Z);
if( A.pExpr ) {
A.pExpr->affinity = (char)T;
}
A.zStart = X.z;
A.zEnd = &Y.z[Y.n];
}
%endif !SQLITE_OMIT_TRIGGER
@ -1536,7 +1538,7 @@ with(A) ::= WITH wqlist(W). { A = W; }
with(A) ::= WITH RECURSIVE wqlist(W). { A = W; }
wqlist(A) ::= nm(X) eidlist_opt(Y) AS LP select(Z) RP. {
A = sqlite3WithAdd(pParse, 0, &X, Y, Z);
A = sqlite3WithAdd(pParse, 0, &X, Y, Z); /*A-overwrites-X*/
}
wqlist(A) ::= wqlist(A) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. {
A = sqlite3WithAdd(pParse, A, &X, Y, Z);

View File

@ -3476,11 +3476,13 @@ PRIVATE char *append_str(const char *zText, int n, int p1, int p2){
PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){
char *cp, *xp;
int i;
int rc = 0; /* True if yylhsminor is used */
char lhsused = 0; /* True if the LHS element has been used */
char lhsdirect; /* True if LHS writes directly into stack */
char used[MAXRHS]; /* True for each RHS element which is used */
char zLhs[50]; /* Convert the LHS symbol into this string */
int rc = 0; /* True if yylhsminor is used */
const char *zSkip = 0; /* The zOvwrt comment within rp->code, or NULL */
char lhsused = 0; /* True if the LHS element has been used */
char lhsdirect; /* True if LHS writes directly into stack */
char used[MAXRHS]; /* True for each RHS element which is used */
char zLhs[50]; /* Convert the LHS symbol into this string */
char zOvwrt[900]; /* Comment that to allow LHS to overwrite RHS */
for(i=0; i<rp->nrhs; i++) used[i] = 0;
lhsused = 0;
@ -3522,7 +3524,16 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){
lemp->errorcnt++;
}
}else{
lhsdirect = 0;
lemon_sprintf(zOvwrt, "/*%s-overwrites-%s*/",
rp->lhsalias, rp->rhsalias[0]);
zSkip = strstr(rp->code, zOvwrt);
if( zSkip!=0 ){
/* The code contains a special comment that indicates that it is safe
** for the LHS label to overwrite left-most RHS label. */
lhsdirect = 1;
}else{
lhsdirect = 0;
}
}
if( lhsdirect ){
sprintf(zLhs, "yymsp[%d].minor.yy%d",1-rp->nrhs,rp->lhs->dtnum);
@ -3535,6 +3546,11 @@ PRIVATE int translate_code(struct lemon *lemp, struct rule *rp){
/* This const cast is wrong but harmless, if we're careful. */
for(cp=(char *)rp->code; *cp; cp++){
if( cp==zSkip ){
append_str(zOvwrt,0,0,0);
cp += lemonStrlen(zOvwrt)-1;
continue;
}
if( ISALPHA(*cp) && (cp==rp->code || (!ISALNUM(cp[-1]) && cp[-1]!='_')) ){
char saved;
for(xp= &cp[1]; ISALNUM(*xp) || *xp=='_'; xp++);