/** * parser.y * * Copyright (C) 2003, 2004 Bojan Smojver, Rexursive * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licence as published by the Free * Software Foundation; either version 2 of the Licence, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licence for * more details. * * You should have received a copy of the GNU General Public Licence along * with this program; if not, write to the Free Software Foundation, Inc., 59 * Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as two special exceptions, Bojan Smojver, Rexursive, gives * permission to: * * 1. Link, both statically and dynamically, the code of this program with * Apache HTTP Server, Apache Portable Runtime and Apache Portable Runtime * Utility Library from Apache Software Foundation (or with modified versions * of the above, that use the same licence - Apache Software Licence 1.1, 2.0 * or any later version), and distribute linked combinations including the * program and the above software from Apache Software Foundation. You must * obey the GNU General Public Licence in all respects for all of the code * used other than Apache HTTP Server, Apache Portable Runtime and Apache * Portable Runtime Utility Library. * * 2. Dynamically link any shared library with this program at run-time, * through the interface of SpinApplication/SpinAppEntry or LoadModule * run-time configuration directives of Apache HTTP Server, as provided by * this program or Apache HTTP Server itself, regardless of licensing terms of * those shared libraries. You must obey the GNU General Public Licence in all * respects for all of the code used other than that of those shared * libraries. * * If you modify this file, you may extend these exceptions to your version of * the file, but you are not obligated to do so. If you do not wish to do so, * delete one or both of these exception statements from your version. * */ %{ #include "private.h" #define YYSTYPE rxv_spin_node_t* #define YYPARSE_PARAM scanner #define YYLEX_PARAM scanner #define EXTRA_TAIL (*(extra->tail+extra->depth+(*(extra->boff+extra->depth)))) #define EXTRA_TAIL_POS (*(extra->tail+extra->depth+1)) #define EXTRA_TAIL_NEG (*(extra->tail+extra->depth+1+RXV_SPIN_MAX_DEPTH)) rxv_spin_extra_t *yyget_extra(void *scanner); %} %pure_parser %defines %name_prefix="rxv_spin_" %error-verbose %token FOR %token IF %token ELSE %token END %token CRF /* command reference, inside #for or #if */ %token REF %token TXT %token ERR %% /* Grammar rules */ stmt: for_stmt | if_stmt | txt_stmt | ref_stmt | err_stmt | stmt for_stmt | stmt if_stmt | stmt txt_stmt | stmt ref_stmt | stmt err_stmt ; for_stmt: FOR '(' CRF ')' stmt END { rxv_spin_extra_t *extra=yyget_extra(scanner); if($3){ ($1->loop)->stmt=$5; if(!(extra->root || extra->depth)) extra->root=$1; if(EXTRA_TAIL) EXTRA_TAIL->next=$1; EXTRA_TAIL=$1; } EXTRA_TAIL_POS=EXTRA_TAIL_NEG=NULL; } ; if_stmt: IF '(' CRF ')' stmt END { rxv_spin_extra_t *extra=yyget_extra(scanner); if($3){ /* if or unless with a valid reference */ ($1->cond)->ref=($3->ref); if($1->cond->type){ /* unless */ ($1->cond)->pos=NULL; ($1->cond)->neg=$5; } else{ ($1->cond)->pos=$5; ($1->cond)->neg=NULL; } if(!(extra->root || extra->depth)) extra->root=$1; if(EXTRA_TAIL) EXTRA_TAIL->next=$1; EXTRA_TAIL=$1; } else if($1->cond->type){ /* unless with an impossible ref */ if(!(extra->root || extra->depth)) extra->root=$5; if(EXTRA_TAIL) EXTRA_TAIL->next=$5; EXTRA_TAIL=$5; } EXTRA_TAIL_POS=EXTRA_TAIL_NEG=NULL; } | IF '(' CRF ')' stmt ELSE END { rxv_spin_extra_t *extra=yyget_extra(scanner); if($3){ /* if or unless with a valid reference */ ($1->cond)->ref=($3->ref); if($1->cond->type){ /* unless */ ($1->cond)->pos=NULL; ($1->cond)->neg=$5; } else{ ($1->cond)->pos=$5; ($1->cond)->neg=NULL; } if(!(extra->root || extra->depth)) extra->root=$1; if(EXTRA_TAIL) EXTRA_TAIL->next=$1; EXTRA_TAIL=$1; } else if($1->cond->type){ /* unless with an impossible ref */ if(!(extra->root || extra->depth)) extra->root=$5; if(EXTRA_TAIL) EXTRA_TAIL->next=$5; EXTRA_TAIL=$5; } EXTRA_TAIL_POS=EXTRA_TAIL_NEG=NULL; } | IF '(' CRF ')' stmt ELSE stmt END { rxv_spin_extra_t *extra=yyget_extra(scanner); if($3){ /* if or unless with a valid reference */ ($1->cond)->ref=($3->ref); if($1->cond->type){ /* unless */ ($1->cond)->pos=$7; ($1->cond)->neg=$5; } else{ ($1->cond)->pos=$5; ($1->cond)->neg=$7; } if(!(extra->root || extra->depth)) extra->root=$1; if(EXTRA_TAIL) EXTRA_TAIL->next=$1; EXTRA_TAIL=$1; } else{ /* if or unless with an impossible reference */ if($1->cond->type){ /* unless */ if(!(extra->root || extra->depth)) extra->root=$5; if(EXTRA_TAIL) EXTRA_TAIL->next=$5; EXTRA_TAIL=$5; } else{ if(!(extra->root || extra->depth)) extra->root=$7; if(EXTRA_TAIL) EXTRA_TAIL->next=$7; EXTRA_TAIL=$7; } } EXTRA_TAIL_POS=EXTRA_TAIL_NEG=NULL; } | IF '(' CRF ')' ELSE stmt END { rxv_spin_extra_t *extra=yyget_extra(scanner); if($3){ /* if or unless with a valid reference */ ($1->cond)->ref=($3->ref); if($1->cond->type){ /* unless */ ($1->cond)->pos=$6; ($1->cond)->neg=NULL; } else{ ($1->cond)->pos=NULL; ($1->cond)->neg=$6; } if(!(extra->root || extra->depth)) extra->root=$1; if(EXTRA_TAIL) EXTRA_TAIL->next=$1; EXTRA_TAIL=$1; } else if(!$1->cond->type){ /* if with an impossible ref */ if(!(extra->root || extra->depth)) extra->root=$6; if(EXTRA_TAIL) EXTRA_TAIL->next=$6; EXTRA_TAIL=$6; } EXTRA_TAIL_POS=EXTRA_TAIL_NEG=NULL; } ; txt_stmt: TXT { rxv_spin_extra_t *extra=yyget_extra(scanner); if(!(extra->root || extra->depth)) extra->root=$1; if(EXTRA_TAIL) EXTRA_TAIL->next=$1; EXTRA_TAIL=$1; if(extra->iseof){ if(extra->depth){ yyerror("parse error, unexpected $end, expecting END"); YYERROR; } else{ YYACCEPT; } } } ; ref_stmt: REF { if($1){ rxv_spin_extra_t *extra=yyget_extra(scanner); if(!(extra->root || extra->depth)) extra->root=$1; if(EXTRA_TAIL) EXTRA_TAIL->next=$1; EXTRA_TAIL=$1; } } ; err_stmt: error { rxv_spin_extra_t *extra=yyget_extra(scanner); extra->error=apr_pstrcat(extra->tpool, extra->error?extra->error:"generic parse error", ": row:",apr_off_t_toa(extra->pool,extra->row), " col:",apr_off_t_toa(extra->pool,extra->col),NULL); return 1; } ; %% void yyerror(char *s){ char *time; if(!(time=malloc(APR_CTIME_LEN))) return; apr_ctime(time,apr_time_now()); fprintf(stderr,"[%s] [error] [spin parser] %s\n",time,s); fflush(stderr); free(time); }