From: drh Date: Wed, 17 Feb 2016 04:33:10 +0000 (+0000) Subject: Enhance Lemon so that if reduce code contains a comment of the form X-Git-Tag: version-3.12.0~180^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cf82f0d3d2606af4caff3845240dceb4c7c4d25c;p=thirdparty%2Fsqlite.git 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 --- diff --git a/manifest b/manifest index afad0890ac..c34c4dda4b 100644 --- a/manifest +++ b/manifest @@ -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 diff --git a/manifest.uuid b/manifest.uuid index e8f5fde5d6..2c12f2f200 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ef95a7d6490e33a9af4bc7b4b622de7328742ca7 \ No newline at end of file +5cfe9545d478a2c500083613dd20e14b2ffce645 \ No newline at end of file diff --git a/src/parse.y b/src/parse.y index cf9bc0f2bb..f1060305ee 100644 --- a/src/parse.y +++ b/src/parse.y @@ -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); diff --git a/tool/lemon.c b/tool/lemon.c index 1f81717c7c..1058d14ae6 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -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; inrhs; 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++);