Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Lemon collapses common destructors and reduce actions into a single case. (CVS 1837) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
3c5aa850eeec5c75c5200a3707852cc5 |
User & Date: | drh 2004-07-20 14:06:52.000 |
Context
2004-07-20
| ||
18:23 | Simplify the where.c logic by flipping expression over so that the controlling variable is always on the left. (CVS 1838) (check-in: ec8bfa3891 user: drh tags: trunk) | |
14:06 | Lemon collapses common destructors and reduce actions into a single case. (CVS 1837) (check-in: 3c5aa850ee user: drh tags: trunk) | |
12:45 | Add the '%ifdef' capability to lemon. Other minor changes. (CVS 1836) (check-in: 522ff721cc user: drh tags: trunk) | |
Changes
Changes to src/os_unix.c.
︙ | ︙ | |||
57 58 59 60 61 62 63 | /* ** Include code that is common to all os_*.c files */ #include "os_common.h" | | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | /* ** Include code that is common to all os_*.c files */ #include "os_common.h" #if defined(THREADSAFE) && THREADSAFE && defined(__linux__) #define getpid pthread_self #endif /* ** Here is the dirt on POSIX advisory locks: ANSI STD 1003.1 (1996) ** section 6.5.2.2 lines 483 through 490 specify that when a process ** sets or clears a lock, that operation overrides any prior locks set |
︙ | ︙ |
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.130 2004/07/20 14:06:52 drh Exp $ */ %token_prefix TK_ %token_type {Token} %default_type {Token} %extra_argument {Parse *pParse} %syntax_error { if( pParse->zErrMsg==0 ){ |
︙ | ︙ | |||
827 828 829 830 831 832 833 | trigger_event(A) ::= UPDATE OF inscollist(X). {A.a = TK_UPDATE; A.b = X; } %type foreach_clause {int} foreach_clause(A) ::= . { A = TK_ROW; } foreach_clause(A) ::= FOR EACH ROW. { A = TK_ROW; } foreach_clause(A) ::= FOR EACH STATEMENT. { A = TK_STATEMENT; } | | | | | 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 | trigger_event(A) ::= UPDATE OF inscollist(X). {A.a = TK_UPDATE; A.b = X; } %type foreach_clause {int} foreach_clause(A) ::= . { A = TK_ROW; } foreach_clause(A) ::= FOR EACH ROW. { A = TK_ROW; } foreach_clause(A) ::= FOR EACH STATEMENT. { A = TK_STATEMENT; } %type when_clause {Expr*} when_clause(A) ::= . { A = 0; } when_clause(A) ::= WHEN expr(X). { A = X; } %type trigger_cmd_list {TriggerStep*} %destructor trigger_cmd_list {sqlite3DeleteTriggerStep($$);} trigger_cmd_list(A) ::= trigger_cmd(X) SEMI trigger_cmd_list(Y). { X->pNext = Y; A = X; } trigger_cmd_list(A) ::= . { A = 0; } %type trigger_cmd {TriggerStep*} %destructor trigger_cmd {sqlite3DeleteTriggerStep($$);} // UPDATE trigger_cmd(A) ::= UPDATE orconf(R) nm(X) SET setlist(Y) where_opt(Z). { A = sqlite3TriggerUpdateStep(&X, Y, Z, R); } // INSERT trigger_cmd(A) ::= insert_cmd(R) INTO nm(X) inscollist_opt(F) |
︙ | ︙ |
Changes to tool/lemon.c.
︙ | ︙ | |||
2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 | if( sp->type==TERMINAL ){ ret = lemp->tokendest!=0; }else{ ret = lemp->vardest!=0 || sp->destructor!=0; } return ret; } /* ** Generate code which executes when the rule "rp" is reduced. Write ** the code to "out". Make sure lineno stays up-to-date. */ PRIVATE void emit_code(out,rp,lemp,lineno) FILE *out; struct rule *rp; struct lemon *lemp; int *lineno; { | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < < < < < < > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 | if( sp->type==TERMINAL ){ ret = lemp->tokendest!=0; }else{ ret = lemp->vardest!=0 || sp->destructor!=0; } return ret; } /* ** Append text to a dynamically allocated string. If zText is 0 then ** reset the string to be empty again. Always return the complete text ** of the string (which is overwritten with each call). */ PRIVATE char *append_str(char *zText, int n, int p1, int p2){ static char *z = 0; static int alloced = 0; static int used = 0; int i, c; char zInt[40]; if( zText==0 ){ used = 0; return z; } if( n<=0 ) n = strlen(zText); if( n+sizeof(zInt)*2+used >= alloced ){ alloced = n + sizeof(zInt)*2 + used + 200; z = realloc(z, alloced); } if( z==0 ) return ""; while( n-- > 0 ){ c = *(zText++); if( c=='%' && zText[0]=='d' ){ sprintf(zInt, "%d", p1); p1 = p2; strcpy(&z[used], zInt); used += strlen(&z[used]); zText++; n--; }else{ z[used++] = c; } } z[used] = 0; return z; } /* ** zCode is a string that is the action associated with a rule. Expand ** the symbols in this string so that the refer to elements of the parser ** stack. Return a new string stored in space obtained from malloc. */ PRIVATE char *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 used[MAXRHS]; /* True for each RHS element which is used */ for(i=0; i<rp->nrhs; i++) used[i] = 0; lhsused = 0; append_str(0,0,0,0); for(cp=rp->code; *cp; cp++){ if( isalpha(*cp) && (cp==rp->code || (!isalnum(cp[-1]) && cp[-1]!='_')) ){ char saved; for(xp= &cp[1]; isalnum(*xp) || *xp=='_'; xp++); saved = *xp; *xp = 0; if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){ append_str("yygotominor.yy%d",-1,rp->lhs->dtnum,0); cp = xp; lhsused = 1; }else{ for(i=0; i<rp->nrhs; i++){ if( rp->rhsalias[i] && strcmp(cp,rp->rhsalias[i])==0 ){ append_str("yymsp[%d].minor.yy%d",-1, i-rp->nrhs+1,rp->rhs[i]->dtnum); cp = xp; used[i] = 1; break; } } } *xp = saved; } append_str(cp, 1, 0, 0); } /* End loop */ /* Check to make sure the LHS has been used */ if( rp->lhsalias && !lhsused ){ ErrorMsg(lemp->filename,rp->ruleline, "Label \"%s\" for \"%s(%s)\" is never used.", rp->lhsalias,rp->lhs->name,rp->lhsalias); lemp->errorcnt++; } /* Generate destructor code for RHS symbols which are not used in the ** reduce code */ 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(%d,&yymsp[%d].minor);\n", -1, rp->rhs[i]->index,i-rp->nrhs+1); }else{ /* No destructor defined for this term */ } } } cp = append_str(0,0,0,0); rp->code = Strsafe(cp); } /* ** Generate code which executes when the rule "rp" is reduced. Write ** the code to "out". Make sure lineno stays up-to-date. */ PRIVATE void emit_code(out,rp,lemp,lineno) FILE *out; struct rule *rp; struct lemon *lemp; int *lineno; { char *cp; int linecnt = 0; /* Generate code to do the reduce action */ if( rp->code ){ fprintf(out,"#line %d \"%s\"\n{",rp->line,lemp->filename); fprintf(out,"%s",rp->code); for(cp=rp->code; *cp; cp++){ if( *cp=='\n' ) linecnt++; } /* End loop */ (*lineno) += 3 + linecnt; fprintf(out,"}\n#line %d \"%s\"\n",*lineno,lemp->outname); } /* End if( rp->code ) */ return; } /* ** Print the definition of the union used for the parser's data stack. ** This union contains fields for every possible data type for tokens ** and nonterminals. In the process of computing and printing this |
︙ | ︙ | |||
3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 | fprintf(out," break;\n"); lineno++; } } for(i=0; i<lemp->nsymbol; i++){ struct symbol *sp = lemp->symbols[i]; if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue; fprintf(out," case %d:\n",sp->index); lineno++; emit_destructor_code(out,lemp->symbols[i],lemp,&lineno); fprintf(out," break;\n"); lineno++; } if( lemp->vardest ){ struct symbol *dflt_sp = 0; for(i=0; i<lemp->nsymbol; i++){ struct symbol *sp = lemp->symbols[i]; | > > > > > > > > > > > > | 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 | fprintf(out," break;\n"); lineno++; } } for(i=0; i<lemp->nsymbol; i++){ struct symbol *sp = lemp->symbols[i]; if( sp==0 || sp->type==TERMINAL || sp->destructor==0 ) continue; fprintf(out," case %d:\n",sp->index); lineno++; /* Combine duplicate destructors into a single case */ for(j=i+1; j<lemp->nsymbol; j++){ struct symbol *sp2 = lemp->symbols[j]; if( sp2 && sp2->type!=TERMINAL && sp2->destructor && sp2->dtnum==sp->dtnum && strcmp(sp->destructor,sp2->destructor)==0 ){ fprintf(out," case %d:\n",sp2->index); lineno++; sp2->destructor = 0; } } emit_destructor_code(out,lemp->symbols[i],lemp,&lineno); fprintf(out," break;\n"); lineno++; } if( lemp->vardest ){ struct symbol *dflt_sp = 0; for(i=0; i<lemp->nsymbol; i++){ struct symbol *sp = lemp->symbols[i]; |
︙ | ︙ | |||
3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 | for(rp=lemp->rule; rp; rp=rp->next){ 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); | > > > > > > > > > > > | 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 | for(rp=lemp->rule; rp; rp=rp->next){ 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){ if( rp->code ) translate_code(lemp, rp); } for(rp=lemp->rule; rp; rp=rp->next){ struct rule *rp2; if( rp->code==0 ) continue; fprintf(out," case %d:\n",rp->index); lineno++; for(rp2=rp->next; rp2; rp2=rp2->next){ if( rp2->code==rp->code ){ fprintf(out," case %d:\n",rp2->index); lineno++; rp2->code = 0; } } 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); |
︙ | ︙ |