]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
In Lemon, add the ability for the left-most RHS label to be the same as the
authordrh <drh@noemail.net>
Wed, 17 Feb 2016 01:18:33 +0000 (01:18 +0000)
committerdrh <drh@noemail.net>
Wed, 17 Feb 2016 01:18:33 +0000 (01:18 +0000)
LHS label, causing the LHS values to be written directly into the stack.

FossilOrigin-Name: 4bb94c7c4c3cb3ccad72c2451d88684130dde845

manifest
manifest.uuid
src/parse.y
tool/lemon.c
tool/lempar.c

index 309d908101c10afc12a63871e389b4e80c38a016..32bf38b8897ff386310486aa33cf0c81326bf3ba 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Experimental\schanges\sto\sLemon\sfor\simproved\sparser\sperformance.
-D 2016-02-16T21:19:49.726
+C In\sLemon,\sadd\sthe\sability\sfor\sthe\sleft-most\sRHS\slabel\sto\sbe\sthe\ssame\sas\sthe\nLHS\slabel,\scausing\sthe\sLHS\svalues\sto\sbe\swritten\sdirectly\sinto\sthe\sstack.
+D 2016-02-17T01:18:33.698
 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 36a367a623589fb1123c10d577737aa3a06177e6
+F src/parse.y eb7d241ca23d6035e5f902de571bb066884fd4ca
 F src/pcache.c 647bb53a86b7bbcf55ad88089b3ea5a9170b90df
 F src/pcache.h 4d0ccaad264d360981ec5e6a2b596d6e85242545
 F src/pcache1.c 72f644dc9e1468c72922eff5904048427b817051
@@ -1378,8 +1378,8 @@ F tool/fuzzershell.c 94019b185caceffc9f7c7b678a6489e42bc2aefa
 F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
 F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
 F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
-F tool/lemon.c 799e73e19a33b8dd7767a7fa34618ed2a9c2397d
-F tool/lempar.c 5478c5298763b47908b6632a7e3f9d656a98748b
+F tool/lemon.c 501104fc7fbb01a86078841bed704184ccfd6036
+F tool/lempar.c 08bbb0fbca9c1f61d2a20a7af893110aefd571a0
 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
 F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
 F tool/mkautoconfamal.sh c78caa3214f25dc28ea157b5a82abb311f209906
@@ -1427,10 +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 9570b6b43df3bc5ce314cded20bca8be9e968efe
-R bd4538940a7fa7274e5766ff6172546b
-T *branch * parser-performance
-T *sym-parser-performance *
-T -sym-trunk *
+P a65d583ce97b8c08157268bd054479cda3957a94
+R e1ed8179ef03a39381f66ed9ce3ecd2f
 U drh
-Z c2a93192e4911cf28788507cc4af2d10
+Z a9c8340faee95f29d20e3673b4598420
index 13e75b598d8251dd964ebe19e9bff4abd45b81a8..9f1cd50eb1a32459104a01af28fc3bd385f4ef0c 100644 (file)
@@ -1 +1 @@
-a65d583ce97b8c08157268bd054479cda3957a94
\ No newline at end of file
+4bb94c7c4c3cb3ccad72c2451d88684130dde845
\ No newline at end of file
index b5755820b343a5df727e0dd45b9ec40db911ed2a..b48ed526d42ee989a5bc19d3cec19199f198a99c 100644 (file)
@@ -200,13 +200,11 @@ columnlist ::= column.
 // datatype, and other keywords such as PRIMARY KEY, UNIQUE, REFERENCES,
 // NOT NULL and so forth.
 //
-column(A) ::= columnid(X) type carglist. {
-  A.z = X.z;
-  A.n = (int)(pParse->sLastToken.z-X.z) + pParse->sLastToken.n;
+column(A) ::= columnid(A) type carglist. {
+  A.n = (int)(pParse->sLastToken.z-A.z) + pParse->sLastToken.n;
 }
-columnid(A) ::= nm(X). {
-  sqlite3AddColumn(pParse,&X);
-  A = X;
+columnid(A) ::= nm(A). {
+  sqlite3AddColumn(pParse,&A);
   pParse->constraintName.n = 0;
 }
 
@@ -264,9 +262,9 @@ columnid(A) ::= nm(X). {
 // The name of a column or table can be any of the following:
 //
 %type nm {Token}
-nm(A) ::= id(X).         {A = X;}
-nm(A) ::= STRING(X).     {A = X;}
-nm(A) ::= JOIN_KW(X).    {A = X;}
+nm(A) ::= id(A).
+nm(A) ::= STRING(A).
+nm(A) ::= JOIN_KW(A).
 
 // A typetoken is really one or more tokens that form a type name such
 // as can be found after the column name in a CREATE TABLE statement.
@@ -275,18 +273,16 @@ nm(A) ::= JOIN_KW(X).    {A = X;}
 %type typetoken {Token}
 type ::= .
 type ::= typetoken(X).                   {sqlite3AddColumnType(pParse,&X);}
-typetoken(A) ::= typename(X).   {A = X;}
-typetoken(A) ::= typename(X) LP signed RP(Y). {
-  A.z = X.z;
-  A.n = (int)(&Y.z[Y.n] - X.z);
+typetoken(A) ::= typename(A).
+typetoken(A) ::= typename(A) LP signed RP(Y). {
+  A.n = (int)(&Y.z[Y.n] - A.z);
 }
-typetoken(A) ::= typename(X) LP signed COMMA signed RP(Y). {
-  A.z = X.z;
-  A.n = (int)(&Y.z[Y.n] - X.z);
+typetoken(A) ::= typename(A) LP signed COMMA signed RP(Y). {
+  A.n = (int)(&Y.z[Y.n] - A.z);
 }
 %type typename {Token}
-typename(A) ::= ids(X).             {A = X;}
-typename(A) ::= typename(X) ids(Y). {A.z=X.z; A.n=Y.n+(int)(Y.z-X.z);}
+typename(A) ::= ids(A).
+typename(A) ::= typename(A) ids(Y). {A.n=Y.n+(int)(Y.z-A.z);}
 signed ::= plus_num.
 signed ::= minus_num.
 
@@ -338,7 +334,7 @@ autoinc(X) ::= AUTOINCR.  {X = 1;}
 //
 %type refargs {int}
 refargs(A) ::= .                  { A = OE_None*0x0101; /* EV: R-19803-45884 */}
-refargs(A) ::= refargs(X) refarg(Y). { A = (X & ~Y.mask) | Y.value; }
+refargs(A) ::= refargs(A) refarg(Y). { A = (A & ~Y.mask) | Y.value; }
 %type refarg {struct {int value; int mask;}}
 refarg(A) ::= MATCH nm.              { A.value = 0;     A.mask = 0x000000; }
 refarg(A) ::= ON INSERT refact.      { A.value = 0;     A.mask = 0x000000; }
@@ -359,7 +355,7 @@ init_deferred_pred_opt(A) ::= INITIALLY DEFERRED.     {A = 1;}
 init_deferred_pred_opt(A) ::= INITIALLY IMMEDIATE.    {A = 0;}
 
 conslist_opt(A) ::= .                         {A.n = 0; A.z = 0;}
-conslist_opt(A) ::= COMMA(X) conslist.        {A = X;}
+conslist_opt(A) ::= COMMA(A) conslist.
 conslist ::= conslist tconscomma tcons.
 conslist ::= tcons.
 tconscomma ::= COMMA.            {pParse->constraintName.n = 0;}
@@ -378,7 +374,7 @@ tcons ::= FOREIGN KEY LP eidlist(FA) RP
 }
 %type defer_subclause_opt {int}
 defer_subclause_opt(A) ::= .                    {A = 0;}
-defer_subclause_opt(A) ::= defer_subclause(X).  {A = X;}
+defer_subclause_opt(A) ::= defer_subclause(A).
 
 // The following is a non-standard extension that allows us to declare the
 // default behavior when there is a constraint conflict.
@@ -390,7 +386,7 @@ onconf(A) ::= .                              {A = OE_Default;}
 onconf(A) ::= ON CONFLICT resolvetype(X).    {A = X;}
 orconf(A) ::= .                              {A = OE_Default;}
 orconf(A) ::= OR resolvetype(X).             {A = X;}
-resolvetype(A) ::= raisetype(X).             {A = X;}
+resolvetype(A) ::= raisetype(A).
 resolvetype(A) ::= IGNORE.                   {A = OE_Ignore;}
 resolvetype(A) ::= REPLACE.                  {A = OE_Replace;}
 
@@ -465,11 +461,11 @@ select(A) ::= with(W) selectnowith(X). {
   A = p;
 }
 
-selectnowith(A) ::= oneselect(X).                      {A = X;}
+selectnowith(A) ::= oneselect(A).
 %ifndef SQLITE_OMIT_COMPOUND_SELECT
-selectnowith(A) ::= selectnowith(X) multiselect_op(Y) oneselect(Z).  {
+selectnowith(A) ::= selectnowith(A) multiselect_op(Y) oneselect(Z).  {
   Select *pRhs = Z;
-  Select *pLhs = X;
+  Select *pLhs = A;
   if( pRhs && pRhs->pPrior ){
     SrcList *pFrom;
     Token x;
@@ -522,20 +518,19 @@ oneselect(A) ::= SELECT(S) distinct(D) selcollist(W) from(X) where_opt(Y)
   }
 #endif /* SELECTRACE_ENABLED */
 }
-oneselect(A) ::= values(X).    {A = X;}
+oneselect(A) ::= values(A).
 
 %type values {Select*}
 %destructor values {sqlite3SelectDelete(pParse->db, $$);}
 values(A) ::= VALUES LP nexprlist(X) RP. {
   A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0,0);
 }
-values(A) ::= values(X) COMMA LP exprlist(Y) RP. {
-  Select *pRight, *pLeft = X;
+values(A) ::= values(A) COMMA LP exprlist(Y) RP. {
+  Select *pRight, *pLeft = A;
   pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values|SF_MultiValue,0,0);
   if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue;
   if( pRight ){
     pRight->op = TK_ALL;
-    pLeft = X;
     pRight->pPrior = pLeft;
     A = pRight;
   }else{
@@ -560,22 +555,22 @@ distinct(A) ::= .           {A = 0;}
 %destructor selcollist {sqlite3ExprListDelete(pParse->db, $$);}
 %type sclp {ExprList*}
 %destructor sclp {sqlite3ExprListDelete(pParse->db, $$);}
-sclp(A) ::= selcollist(X) COMMA.             {A = X;}
+sclp(A) ::= selcollist(A) COMMA.
 sclp(A) ::= .                                {A = 0;}
-selcollist(A) ::= sclp(P) expr(X) as(Y).     {
-   A = sqlite3ExprListAppend(pParse, P, X.pExpr);
+selcollist(A) ::= sclp(A) expr(X) as(Y).     {
+   A = sqlite3ExprListAppend(pParse, A, X.pExpr);
    if( Y.n>0 ) sqlite3ExprListSetName(pParse, A, &Y, 1);
    sqlite3ExprListSetSpan(pParse,A,&X);
 }
-selcollist(A) ::= sclp(P) STAR. {
+selcollist(A) ::= sclp(A) STAR. {
   Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
-  A = sqlite3ExprListAppend(pParse, P, p);
+  A = sqlite3ExprListAppend(pParse, A, p);
 }
-selcollist(A) ::= sclp(P) nm(X) DOT STAR(Y). {
+selcollist(A) ::= sclp(A) nm(X) DOT STAR(Y). {
   Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0, &Y);
   Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
   Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
-  A = sqlite3ExprListAppend(pParse,P, pDot);
+  A = sqlite3ExprListAppend(pParse,A, pDot);
 }
 
 // An option "AS <id>" phrase that can follow one of the expressions that
@@ -583,7 +578,7 @@ selcollist(A) ::= sclp(P) nm(X) DOT STAR(Y). {
 //
 %type as {Token}
 as(X) ::= AS nm(Y).    {X = Y;}
-as(X) ::= ids(Y).      {X = Y;}
+as(X) ::= ids(X).
 as(X) ::= .            {X.n = 0;}
 
 
@@ -605,32 +600,31 @@ from(A) ::= FROM seltablist(X). {
 // "seltablist" is a "Select Table List" - the content of the FROM clause
 // in a SELECT statement.  "stl_prefix" is a prefix of this list.
 //
-stl_prefix(A) ::= seltablist(X) joinop(Y).    {
-   A = X;
+stl_prefix(A) ::= seltablist(A) joinop(Y).    {
    if( ALWAYS(A && A->nSrc>0) ) A->a[A->nSrc-1].fg.jointype = (u8)Y;
 }
 stl_prefix(A) ::= .                           {A = 0;}
-seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) indexed_opt(I)
+seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) as(Z) indexed_opt(I)
                   on_opt(N) using_opt(U). {
-  A = sqlite3SrcListAppendFromTerm(pParse,X,&Y,&D,&Z,0,N,U);
+  A = sqlite3SrcListAppendFromTerm(pParse,A,&Y,&D,&Z,0,N,U);
   sqlite3SrcListIndexedBy(pParse, A, &I);
 }
-seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) LP exprlist(E) RP as(Z)
+seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) LP exprlist(E) RP as(Z)
                   on_opt(N) using_opt(U). {
-  A = sqlite3SrcListAppendFromTerm(pParse,X,&Y,&D,&Z,0,N,U);
+  A = sqlite3SrcListAppendFromTerm(pParse,A,&Y,&D,&Z,0,N,U);
   sqlite3SrcListFuncArgs(pParse, A, E);
 }
 %ifndef SQLITE_OMIT_SUBQUERY
-  seltablist(A) ::= stl_prefix(X) LP select(S) RP
+  seltablist(A) ::= stl_prefix(A) LP select(S) RP
                     as(Z) on_opt(N) using_opt(U). {
-    A = sqlite3SrcListAppendFromTerm(pParse,X,0,0,&Z,S,N,U);
+    A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,S,N,U);
   }
-  seltablist(A) ::= stl_prefix(X) LP seltablist(F) RP
+  seltablist(A) ::= stl_prefix(A) LP seltablist(F) RP
                     as(Z) on_opt(N) using_opt(U). {
-    if( X==0 && Z.n==0 && N==0 && U==0 ){
+    if( A==0 && Z.n==0 && N==0 && U==0 ){
       A = F;
     }else if( F->nSrc==1 ){
-      A = sqlite3SrcListAppendFromTerm(pParse,X,0,0,&Z,0,N,U);
+      A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,0,N,U);
       if( A ){
         struct SrcList_item *pNew = &A->a[A->nSrc-1];
         struct SrcList_item *pOld = F->a;
@@ -645,7 +639,7 @@ seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) LP exprlist(E) RP as(Z)
       Select *pSubquery;
       sqlite3SrcListShiftJoinType(F);
       pSubquery = sqlite3SelectNew(pParse,0,F,0,0,0,0,SF_NestedFrom,0,0);
-      A = sqlite3SrcListAppendFromTerm(pParse,X,0,0,&Z,pSubquery,N,U);
+      A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,pSubquery,N,U);
     }
   }
 %endif  SQLITE_OMIT_SUBQUERY
@@ -703,8 +697,8 @@ using_opt(U) ::= .                        {U = 0;}
 
 orderby_opt(A) ::= .                          {A = 0;}
 orderby_opt(A) ::= ORDER BY sortlist(X).      {A = X;}
-sortlist(A) ::= sortlist(X) COMMA expr(Y) sortorder(Z). {
-  A = sqlite3ExprListAppend(pParse,X,Y.pExpr);
+sortlist(A) ::= sortlist(A) COMMA expr(Y) sortorder(Z). {
+  A = sqlite3ExprListAppend(pParse,A,Y.pExpr);
   sqlite3ExprListSetSortOrder(A,Z);
 }
 sortlist(A) ::= expr(Y) sortorder(Z). {
@@ -798,8 +792,8 @@ cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y)
 %type setlist {ExprList*}
 %destructor setlist {sqlite3ExprListDelete(pParse->db, $$);}
 
-setlist(A) ::= setlist(Z) COMMA nm(X) EQ expr(Y). {
-  A = sqlite3ExprListAppend(pParse, Z, Y.pExpr);
+setlist(A) ::= setlist(A) COMMA nm(X) EQ expr(Y). {
+  A = sqlite3ExprListAppend(pParse, A, Y.pExpr);
   sqlite3ExprListSetName(pParse, A, &X, 1);
 }
 setlist(A) ::= nm(X) EQ expr(Y). {
@@ -830,8 +824,8 @@ insert_cmd(A) ::= REPLACE.            {A = OE_Replace;}
 
 idlist_opt(A) ::= .                       {A = 0;}
 idlist_opt(A) ::= LP idlist(X) RP.    {A = X;}
-idlist(A) ::= idlist(X) COMMA nm(Y).
-    {A = sqlite3IdListAppend(pParse->db,X,&Y);}
+idlist(A) ::= idlist(A) COMMA nm(Y).
+    {A = sqlite3IdListAppend(pParse->db,A,&Y);}
 idlist(A) ::= nm(Y).
     {A = sqlite3IdListAppend(pParse->db,0,&Y);}
 
@@ -864,7 +858,7 @@ idlist(A) ::= nm(Y).
   }
 }
 
-expr(A) ::= term(X).             {A = X;}
+expr(A) ::= term(A).
 expr(A) ::= LP(B) expr(X) RP(E). {A.pExpr = X.pExpr; spanSet(&A,&B,&E);}
 term(A) ::= NULL(X).             {spanExpr(&A, pParse, @X, &X);}
 expr(A) ::= id(X).               {spanExpr(&A, pParse, TK_ID, &X);}
@@ -903,9 +897,8 @@ expr(A) ::= VARIABLE(X).     {
   }
   spanSet(&A, &X, &X);
 }
-expr(A) ::= expr(E) COLLATE ids(C). {
-  A.pExpr = sqlite3ExprAddCollateToken(pParse, E.pExpr, &C, 1);
-  A.zStart = E.zStart;
+expr(A) ::= expr(A) COLLATE ids(C). {
+  A.pExpr = sqlite3ExprAddCollateToken(pParse, A.pExpr, &C, 1);
   A.zEnd = &C.z[C.n];
 }
 %ifndef SQLITE_OMIT_CAST
@@ -938,58 +931,56 @@ term(A) ::= CTIME_KW(OP). {
   ** objects and uses the result to populate a new ExprSpan object.
   */
   static void spanBinaryExpr(
-    ExprSpan *pOut,     /* Write the result here */
     Parse *pParse,      /* The parsing context.  Errors accumulate here */
     int op,             /* The binary operation */
-    ExprSpan *pLeft,    /* The left operand */
+    ExprSpan *pLeft,    /* The left operand, and output */
     ExprSpan *pRight    /* The right operand */
   ){
-    pOut->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr, 0);
-    pOut->zStart = pLeft->zStart;
-    pOut->zEnd = pRight->zEnd;
+    pLeft->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr, 0);
+    pLeft->zEnd = pRight->zEnd;
   }
 
   /* If doNot is true, then add a TK_NOT Expr-node wrapper around the
   ** outside of *ppExpr.
   */
-  static void exprNot(Parse *pParse, int doNot, Expr **ppExpr){
-    if( doNot ) *ppExpr = sqlite3PExpr(pParse, TK_NOT, *ppExpr, 0, 0);
+  static void exprNot(Parse *pParse, int doNot, ExprSpan *pSpan){
+    if( doNot ){
+      pSpan->pExpr = sqlite3PExpr(pParse, TK_NOT, pSpan->pExpr, 0, 0);
+    }
   }
 }
 
-expr(A) ::= expr(X) AND(OP) expr(Y).    {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
-expr(A) ::= expr(X) OR(OP) expr(Y).     {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
-expr(A) ::= expr(X) LT|GT|GE|LE(OP) expr(Y).
-                                        {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
-expr(A) ::= expr(X) EQ|NE(OP) expr(Y).  {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
-expr(A) ::= expr(X) BITAND|BITOR|LSHIFT|RSHIFT(OP) expr(Y).
-                                        {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
-expr(A) ::= expr(X) PLUS|MINUS(OP) expr(Y).
-                                        {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
-expr(A) ::= expr(X) STAR|SLASH|REM(OP) expr(Y).
-                                        {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
-expr(A) ::= expr(X) CONCAT(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
+expr(A) ::= expr(A) AND(OP) expr(Y).    {spanBinaryExpr(pParse,@OP,&A,&Y);}
+expr(A) ::= expr(A) OR(OP) expr(Y).     {spanBinaryExpr(pParse,@OP,&A,&Y);}
+expr(A) ::= expr(A) LT|GT|GE|LE(OP) expr(Y).
+                                        {spanBinaryExpr(pParse,@OP,&A,&Y);}
+expr(A) ::= expr(A) EQ|NE(OP) expr(Y).  {spanBinaryExpr(pParse,@OP,&A,&Y);}
+expr(A) ::= expr(A) BITAND|BITOR|LSHIFT|RSHIFT(OP) expr(Y).
+                                        {spanBinaryExpr(pParse,@OP,&A,&Y);}
+expr(A) ::= expr(A) PLUS|MINUS(OP) expr(Y).
+                                        {spanBinaryExpr(pParse,@OP,&A,&Y);}
+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) ::= NOT LIKE_KW|MATCH(X). {A.eOperator = X; A.bNot = 1;}
-expr(A) ::= expr(X) likeop(OP) expr(Y).  [LIKE_KW]  {
+expr(A) ::= expr(A) likeop(OP) expr(Y).  [LIKE_KW]  {
   ExprList *pList;
   pList = sqlite3ExprListAppend(pParse,0, Y.pExpr);
-  pList = sqlite3ExprListAppend(pParse,pList, X.pExpr);
+  pList = sqlite3ExprListAppend(pParse,pList, A.pExpr);
   A.pExpr = sqlite3ExprFunction(pParse, pList, &OP.eOperator);
-  exprNot(pParse, OP.bNot, &A.pExpr);
-  A.zStart = X.zStart;
+  exprNot(pParse, OP.bNot, &A);
   A.zEnd = Y.zEnd;
   if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc;
 }
-expr(A) ::= expr(X) likeop(OP) expr(Y) ESCAPE expr(E).  [LIKE_KW]  {
+expr(A) ::= expr(A) likeop(OP) expr(Y) ESCAPE expr(E).  [LIKE_KW]  {
   ExprList *pList;
   pList = sqlite3ExprListAppend(pParse,0, Y.pExpr);
-  pList = sqlite3ExprListAppend(pParse,pList, X.pExpr);
+  pList = sqlite3ExprListAppend(pParse,pList, A.pExpr);
   pList = sqlite3ExprListAppend(pParse,pList, E.pExpr);
   A.pExpr = sqlite3ExprFunction(pParse, pList, &OP.eOperator);
-  exprNot(pParse, OP.bNot, &A.pExpr);
-  A.zStart = X.zStart;
+  exprNot(pParse, OP.bNot, &A);
   A.zEnd = E.zEnd;
   if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc;
 }
@@ -998,20 +989,18 @@ expr(A) ::= expr(X) likeop(OP) expr(Y) ESCAPE expr(E).  [LIKE_KW]  {
   /* Construct an expression node for a unary postfix operator
   */
   static void spanUnaryPostfix(
-    ExprSpan *pOut,        /* Write the new expression node here */
     Parse *pParse,         /* Parsing context to record errors */
     int op,                /* The operator */
-    ExprSpan *pOperand,    /* The operand */
+    ExprSpan *pOperand,    /* The operand, and output */
     Token *pPostOp         /* The operand token for setting the span */
   ){
-    pOut->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0);
-    pOut->zStart = pOperand->zStart;
-    pOut->zEnd = &pPostOp->z[pPostOp->n];
+    pOperand->pExpr = sqlite3PExpr(pParse, op, pOperand->pExpr, 0, 0);
+    pOperand->zEnd = &pPostOp->z[pPostOp->n];
   }                           
 }
 
-expr(A) ::= expr(X) ISNULL|NOTNULL(E).   {spanUnaryPostfix(&A,pParse,@E,&X,&E);}
-expr(A) ::= expr(X) NOT NULL(E). {spanUnaryPostfix(&A,pParse,TK_NOTNULL,&X,&E);}
+expr(A) ::= expr(A) ISNULL|NOTNULL(E).   {spanUnaryPostfix(pParse,@E,&A,&E);}
+expr(A) ::= expr(A) NOT NULL(E). {spanUnaryPostfix(pParse,TK_NOTNULL,&A,&E);}
 
 %include {
   /* A routine to convert a binary TK_IS or TK_ISNOT expression into a
@@ -1032,12 +1021,12 @@ expr(A) ::= expr(X) NOT NULL(E). {spanUnaryPostfix(&A,pParse,TK_NOTNULL,&X,&E);}
 // If expr2 is NULL then code as TK_ISNULL or TK_NOTNULL.  If expr2
 // is any other expression, code as TK_IS or TK_ISNOT.
 // 
-expr(A) ::= expr(X) IS expr(Y).     {
-  spanBinaryExpr(&A,pParse,TK_IS,&X,&Y);
+expr(A) ::= expr(A) IS expr(Y).     {
+  spanBinaryExpr(pParse,TK_IS,&A,&Y);
   binaryToUnaryIfNull(pParse, Y.pExpr, A.pExpr, TK_ISNULL);
 }
-expr(A) ::= expr(X) IS NOT expr(Y). {
-  spanBinaryExpr(&A,pParse,TK_ISNOT,&X,&Y);
+expr(A) ::= expr(A) IS NOT expr(Y). {
+  spanBinaryExpr(pParse,TK_ISNOT,&A,&Y);
   binaryToUnaryIfNull(pParse, Y.pExpr, A.pExpr, TK_NOTNULL);
 }
 
@@ -1069,24 +1058,23 @@ expr(A) ::= PLUS(B) expr(X). [BITNOT]
 %type between_op {int}
 between_op(A) ::= BETWEEN.     {A = 0;}
 between_op(A) ::= NOT BETWEEN. {A = 1;}
-expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
+expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
   ExprList *pList = sqlite3ExprListAppend(pParse,0, X.pExpr);
   pList = sqlite3ExprListAppend(pParse,pList, Y.pExpr);
-  A.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, W.pExpr, 0, 0);
+  A.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, A.pExpr, 0, 0);
   if( A.pExpr ){
     A.pExpr->x.pList = pList;
   }else{
     sqlite3ExprListDelete(pParse->db, pList);
   } 
-  exprNot(pParse, N, &A.pExpr);
-  A.zStart = W.zStart;
+  exprNot(pParse, N, &A);
   A.zEnd = Y.zEnd;
 }
 %ifndef SQLITE_OMIT_SUBQUERY
   %type in_op {int}
   in_op(A) ::= IN.      {A = 0;}
   in_op(A) ::= NOT IN.  {A = 1;}
-  expr(A) ::= expr(X) in_op(N) LP exprlist(Y) RP(E). [IN] {
+  expr(A) ::= expr(A) in_op(N) LP exprlist(Y) RP(E). [IN] {
     if( Y==0 ){
       /* Expressions of the form
       **
@@ -1096,8 +1084,8 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
       ** simplify to constants 0 (false) and 1 (true), respectively,
       ** regardless of the value of expr1.
       */
+      sqlite3ExprDelete(pParse->db, A.pExpr);
       A.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[N]);
-      sqlite3ExprDelete(pParse->db, X.pExpr);
     }else if( Y->nExpr==1 ){
       /* Expressions of the form:
       **
@@ -1124,18 +1112,17 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
         pRHS->flags &= ~EP_Collate;
         pRHS->flags |= EP_Generic;
       }
-      A.pExpr = sqlite3PExpr(pParse, N ? TK_NE : TK_EQ, X.pExpr, pRHS, 0);
+      A.pExpr = sqlite3PExpr(pParse, N ? TK_NE : TK_EQ, A.pExpr, pRHS, 0);
     }else{
-      A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0);
+      A.pExpr = sqlite3PExpr(pParse, TK_IN, A.pExpr, 0, 0);
       if( A.pExpr ){
         A.pExpr->x.pList = Y;
         sqlite3ExprSetHeightAndFlags(pParse, A.pExpr);
       }else{
         sqlite3ExprListDelete(pParse->db, Y);
       }
-      exprNot(pParse, N, &A.pExpr);
+      exprNot(pParse, N, &A);
     }
-    A.zStart = X.zStart;
     A.zEnd = &E.z[E.n];
   }
   expr(A) ::= LP(B) select(X) RP(E). {
@@ -1150,8 +1137,8 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
     A.zStart = B.z;
     A.zEnd = &E.z[E.n];
   }
-  expr(A) ::= expr(X) in_op(N) LP select(Y) RP(E).  [IN] {
-    A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0);
+  expr(A) ::= expr(A) in_op(N) LP select(Y) RP(E).  [IN] {
+    A.pExpr = sqlite3PExpr(pParse, TK_IN, A.pExpr, 0, 0);
     if( A.pExpr ){
       A.pExpr->x.pSelect = Y;
       ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery);
@@ -1159,13 +1146,12 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
     }else{
       sqlite3SelectDelete(pParse->db, Y);
     }
-    exprNot(pParse, N, &A.pExpr);
-    A.zStart = X.zStart;
+    exprNot(pParse, N, &A);
     A.zEnd = &E.z[E.n];
   }
-  expr(A) ::= expr(X) in_op(N) nm(Y) dbnm(Z). [IN] {
+  expr(A) ::= expr(A) in_op(N) nm(Y) dbnm(Z). [IN] {
     SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z);
-    A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0);
+    A.pExpr = sqlite3PExpr(pParse, TK_IN, A.pExpr, 0, 0);
     if( A.pExpr ){
       A.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
       ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery);
@@ -1173,8 +1159,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
     }else{
       sqlite3SrcListDelete(pParse->db, pSrc);
     }
-    exprNot(pParse, N, &A.pExpr);
-    A.zStart = X.zStart;
+    exprNot(pParse, N, &A);
     A.zEnd = Z.z ? &Z.z[Z.n] : &Y.z[Y.n];
   }
   expr(A) ::= EXISTS(B) LP select(Y) RP(E). {
@@ -1206,8 +1191,8 @@ expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). {
 }
 %type case_exprlist {ExprList*}
 %destructor case_exprlist {sqlite3ExprListDelete(pParse->db, $$);}
-case_exprlist(A) ::= case_exprlist(X) WHEN expr(Y) THEN expr(Z). {
-  A = sqlite3ExprListAppend(pParse,X, Y.pExpr);
+case_exprlist(A) ::= case_exprlist(A) WHEN expr(Y) THEN expr(Z). {
+  A = sqlite3ExprListAppend(pParse,A, Y.pExpr);
   A = sqlite3ExprListAppend(pParse,A, Z.pExpr);
 }
 case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). {
@@ -1228,10 +1213,10 @@ case_operand(A) ::= .                   {A = 0;}
 %type nexprlist {ExprList*}
 %destructor nexprlist {sqlite3ExprListDelete(pParse->db, $$);}
 
-exprlist(A) ::= nexprlist(X).                {A = X;}
+exprlist(A) ::= nexprlist(A).
 exprlist(A) ::= .                            {A = 0;}
-nexprlist(A) ::= nexprlist(X) COMMA expr(Y).
-    {A = sqlite3ExprListAppend(pParse,X,Y.pExpr);}
+nexprlist(A) ::= nexprlist(A) COMMA expr(Y).
+    {A = sqlite3ExprListAppend(pParse,A,Y.pExpr);}
 nexprlist(A) ::= expr(Y).
     {A = sqlite3ExprListAppend(pParse,0,Y.pExpr);}
 
@@ -1297,8 +1282,8 @@ uniqueflag(A) ::= .        {A = OE_None;}
 
 eidlist_opt(A) ::= .                         {A = 0;}
 eidlist_opt(A) ::= LP eidlist(X) RP.         {A = X;}
-eidlist(A) ::= eidlist(X) COMMA nm(Y) collate(C) sortorder(Z).  {
-  A = parserAddExprIdListTerm(pParse, X, &Y, C, Z);
+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);
@@ -1383,16 +1368,14 @@ when_clause(A) ::= WHEN expr(X). { A = X.pExpr; }
 
 %type trigger_cmd_list {TriggerStep*}
 %destructor trigger_cmd_list {sqlite3DeleteTriggerStep(pParse->db, $$);}
-trigger_cmd_list(A) ::= trigger_cmd_list(Y) trigger_cmd(X) SEMI. {
-  assert( Y!=0 );
-  Y->pLast->pNext = X;
-  Y->pLast = X;
-  A = Y;
-}
-trigger_cmd_list(A) ::= trigger_cmd(X) SEMI. { 
-  assert( X!=0 );
-  X->pLast = X;
-  A = X;
+trigger_cmd_list(A) ::= trigger_cmd_list(A) trigger_cmd(X) SEMI. {
+  assert( A!=0 );
+  A->pLast->pNext = X;
+  A->pLast = X;
+}
+trigger_cmd_list(A) ::= trigger_cmd(A) SEMI. { 
+  assert( A!=0 );
+  A->pLast = A;
 }
 
 // Disallow qualified table names on INSERT, UPDATE, and DELETE statements
@@ -1400,7 +1383,7 @@ trigger_cmd_list(A) ::= trigger_cmd(X) SEMI. {
 // the same database as the table that the trigger fires on.
 //
 %type trnm {Token}
-trnm(A) ::= nm(X).   {A = X;}
+trnm(A) ::= nm(A).
 trnm(A) ::= nm DOT nm(X). {
   A = X;
   sqlite3ErrorMsg(pParse, 
@@ -1557,7 +1540,7 @@ 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);
 }
-wqlist(A) ::= wqlist(W) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. {
-  A = sqlite3WithAdd(pParse, W, &X, Y, Z);
+wqlist(A) ::= wqlist(A) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. {
+  A = sqlite3WithAdd(pParse, A, &X, Y, Z);
 }
 %endif  SQLITE_OMIT_CTE
index d704deb624d42b39ca455db5bc5617e2197d62d9..c678fa0da6daccceb9098f417de976ed249e7369 100644 (file)
@@ -286,6 +286,8 @@ struct rule {
   const char **rhsalias;   /* An alias for each RHS symbol (NULL if none) */
   int line;                /* Line number at which code begins */
   const char *code;        /* The code executed when this rule is reduced */
+  const char *codePrefix;  /* Setup code before code[] above */
+  const char *codeSuffix;  /* Breakdown code after code[] above */
   struct symbol *precsym;  /* Precedence symbol for this rule */
   int index;               /* An index number for this rule */
   Boolean canReduce;       /* True if this rule is ever reduced */
@@ -3430,6 +3432,7 @@ PRIVATE char *append_str(const char *zText, int n, int p1, int p2){
   int c;
   char zInt[40];
   if( zText==0 ){
+    if( used==0 && z!=0 ) z[0] = 0;
     used = 0;
     return z;
   }
@@ -3471,7 +3474,9 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
   char *cp, *xp;
   int i;
   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 */
 
   for(i=0; i<rp->nrhs; i++) used[i] = 0;
   lhsused = 0;
@@ -3482,6 +3487,48 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
     rp->line = rp->ruleline;
   }
 
+
+  if( rp->lhsalias==0 ){
+    /* There is no LHS value symbol. */
+    lhsdirect = 1;
+  }else if( rp->nrhs==0 ){
+    /* If there are no RHS symbols, then writing directly to the LHS is ok */
+    lhsdirect = 1;
+  }else if( rp->rhsalias[0]==0 ){
+    /* The left-most RHS symbol has not value.  LHS direct is ok.  But
+    ** we have to call the distructor on the RHS symbol first. */
+    lhsdirect = 1;
+    if( has_destructor(rp->rhs[0],lemp) ){
+      append_str(0,0,0,0);
+      append_str("  yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0,
+                 rp->rhs[0]->index,1-rp->nrhs);
+      rp->codePrefix = Strsafe(append_str(0,0,0,0));
+    }
+  }else if( strcmp(rp->lhsalias,rp->rhsalias[0])==0 ){
+    /* The LHS symbol and the left-most RHS symbol are the same, so 
+    ** direct writing is allowed */
+    lhsdirect = 1;
+    lhsused = 1;
+    used[0] = 1;
+    if( rp->lhs->dtnum!=rp->rhs[0]->dtnum ){
+      ErrorMsg(lemp->filename,rp->ruleline,
+        "%s(%s) and %s(%s) share the same label but have "
+        "different datatypes.",
+        rp->lhs->name, rp->lhsalias, rp->rhs[0]->name, rp->rhsalias[0]);
+      lemp->errorcnt++;
+    }    
+  }else{
+    lhsdirect = 0;
+  }
+  if( lhsdirect ){
+    sprintf(zLhs, "yymsp[%d].minor.yy%d",1-rp->nrhs,rp->lhs->dtnum);
+  }else{
+    append_str(0,0,0,0);
+    append_str("  YYMINORTYPE yylhsminor;\n", 0, 0, 0);
+    rp->codePrefix = Strsafe(append_str(0,0,0,0));
+    sprintf(zLhs, "yylhsminor.yy%d",rp->lhs->dtnum);
+  }
+
   append_str(0,0,0,0);
 
   /* This const cast is wrong but harmless, if we're careful. */
@@ -3492,7 +3539,7 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
       saved = *xp;
       *xp = 0;
       if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){
-        append_str("yygotominor.yy%d",0,rp->lhs->dtnum,0);
+        append_str(zLhs,0,0,0);
         cp = xp;
         lhsused = 1;
       }else{
@@ -3523,6 +3570,11 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
     append_str(cp, 1, 0, 0);
   } /* End loop */
 
+  /* Main code generation completed */
+  cp = append_str(0,0,0,0);
+  if( cp && cp[0] ) rp->code = Strsafe(cp);
+  append_str(0,0,0,0);
+
   /* Check to make sure the LHS has been used */
   if( rp->lhsalias && !lhsused ){
     ErrorMsg(lemp->filename,rp->ruleline,
@@ -3531,27 +3583,53 @@ PRIVATE void translate_code(struct lemon *lemp, struct rule *rp){
     lemp->errorcnt++;
   }
 
-  /* Generate destructor code for RHS symbols which are not used in the
-  ** reduce code */
+  /* Generate destructor code for RHS minor values which are not referenced.
+  ** Generate error messages for unused labels and duplicate labels.
+  */
   for(i=0; i<rp->nrhs; i++){
-    if( rp->rhsalias[i] && !used[i] ){
-      ErrorMsg(lemp->filename,rp->ruleline,
-        "Label %s for \"%s(%s)\" is never used.",
-        rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
-      lemp->errorcnt++;
-    }else if( rp->rhsalias[i]==0 ){
-      if( has_destructor(rp->rhs[i],lemp) ){
-        append_str("  yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0,
-           rp->rhs[i]->index,i-rp->nrhs+1);
-      }else{
-        /* No destructor defined for this term */
+    if( rp->rhsalias[i] ){
+      if( i>0 ){
+        int j;
+        if( rp->lhsalias && strcmp(rp->lhsalias,rp->rhsalias[i])==0 ){
+          ErrorMsg(lemp->filename,rp->ruleline,
+            "%s(%s) has the same label as the LHS but is not the left-most "
+            "symbol on the RHS.",
+            rp->rhs[i]->name, rp->rhsalias);
+          lemp->errorcnt++;
+        }
+        for(j=0; j<i; j++){
+          if( rp->rhsalias[j] && strcmp(rp->rhsalias[j],rp->rhsalias[i])==0 ){
+            ErrorMsg(lemp->filename,rp->ruleline,
+              "Label %s used for multiple symbols on the RHS of a rule.",
+              rp->rhsalias[i]);
+            lemp->errorcnt++;
+            break;
+          }
+        }
       }
+      if( !used[i] ){
+        ErrorMsg(lemp->filename,rp->ruleline,
+          "Label %s for \"%s(%s)\" is never used.",
+          rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
+        lemp->errorcnt++;
+      }
+    }else if( i>0 && has_destructor(rp->rhs[i],lemp) ){
+      append_str("  yy_destructor(yypParser,%d,&yymsp[%d].minor);\n", 0,
+         rp->rhs[i]->index,i-rp->nrhs+1);
     }
   }
-  if( rp->code ){
-    cp = append_str(0,0,0,0);
-    rp->code = Strsafe(cp?cp:"");
+
+  /* If unable to write LHS values directly into the stack, write the
+  ** saved LHS value now. */
+  if( lhsdirect==0 ){
+    append_str("  yymsp[%d].minor.yy%d = ", 0, 1-rp->nrhs, rp->lhs->dtnum);
+    append_str(zLhs, 0, 0, 0);
+    append_str(";\n", 0, 0, 0);
   }
+
+  /* Suffix code generation complete */
+  cp = append_str(0,0,0,0);
+  if( cp ) rp->codeSuffix = Strsafe(cp);
 }
 
 /* 
@@ -3566,6 +3644,12 @@ PRIVATE void emit_code(
 ){
  const char *cp;
 
+ /* Setup code prior to the #line directive */
+ if( rp->codePrefix && rp->codePrefix[0] ){
+   fprintf(out, "{%s", rp->codePrefix);
+   for(cp=rp->codePrefix; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
+ }
+
  /* Generate code to do the reduce action */
  if( rp->code ){
    if( !lemp->nolinenosflag ){
@@ -3573,15 +3657,23 @@ PRIVATE void emit_code(
      tplt_linedir(out,rp->line,lemp->filename);
    }
    fprintf(out,"{%s",rp->code);
-   for(cp=rp->code; *cp; cp++){
-     if( *cp=='\n' ) (*lineno)++;
-   } /* End loop */
+   for(cp=rp->code; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
    fprintf(out,"}\n"); (*lineno)++;
    if( !lemp->nolinenosflag ){
      (*lineno)++;
      tplt_linedir(out,*lineno,lemp->outname);
    }
- } /* End if( rp->code ) */
+ }
+
+ /* Generate breakdown code that occurs after the #line directive */
+ if( rp->codeSuffix && rp->codeSuffix[0] ){
+   fprintf(out, "%s", rp->codeSuffix);
+   for(cp=rp->codeSuffix; *cp; cp++){ if( *cp=='\n' ) (*lineno)++; }
+ }
+
+ if( rp->codePrefix ){
+   fprintf(out, "}\n"); (*lineno)++;
+ }
 
  return;
 }
index c5b65d645d456c53bb9c93201355cc4420472243..0f25d7603791205695b1b8bd79d19b92186c9087 100644 (file)
@@ -614,7 +614,6 @@ static void yy_reduce(
 ){
   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;
@@ -677,7 +676,6 @@ static void yy_reduce(
     yymsp -= yysize-1;
     yymsp->stateno = (YYACTIONTYPE)yyact;
     yymsp->major = (YYCODETYPE)yygoto;
-    yymsp->minor = yygotominor;
     yyTraceShift(yypParser, yyact);
   }else{
     assert( yyact == YY_ACCEPT_ACTION );