1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* based on ap_expr_parse.y from mod_ssl */ 18 19/* _________________________________________________________________ 20** 21** Expression Parser 22** _________________________________________________________________ 23*/ 24 25%pure-parser 26%error-verbose 27%defines 28%lex-param { void *yyscanner } 29%parse-param { ap_expr_parse_ctx_t *ctx } 30 31%{ 32#include "util_expr_private.h" 33%} 34 35%union { 36 char *cpVal; 37 ap_expr_t *exVal; 38 int num; 39} 40 41%token T_TRUE 42%token T_FALSE 43 44%token T_EXPR_BOOL 45%token T_EXPR_STRING 46 47%token <cpVal> T_ERROR 48 49%token <cpVal> T_DIGIT 50%token <cpVal> T_ID 51%token <cpVal> T_STRING 52%token <cpVal> T_REGEX 53%token <cpVal> T_REGEX_I 54%token <num> T_REGEX_BACKREF 55%token <cpVal> T_OP_UNARY 56%token <cpVal> T_OP_BINARY 57 58%token T_STR_BEGIN 59%token T_STR_END 60%token T_VAR_BEGIN 61%token T_VAR_END 62 63%token T_OP_EQ 64%token T_OP_NE 65%token T_OP_LT 66%token T_OP_LE 67%token T_OP_GT 68%token T_OP_GE 69%token T_OP_REG 70%token T_OP_NRE 71%token T_OP_IN 72%token T_OP_STR_EQ 73%token T_OP_STR_NE 74%token T_OP_STR_LT 75%token T_OP_STR_LE 76%token T_OP_STR_GT 77%token T_OP_STR_GE 78%token T_OP_CONCAT 79 80%token T_OP_OR 81%token T_OP_AND 82%token T_OP_NOT 83 84%right T_OP_OR 85%right T_OP_AND 86%right T_OP_NOT 87%right T_OP_CONCAT 88 89%type <exVal> expr 90%type <exVal> comparison 91%type <exVal> strfunccall 92%type <exVal> lstfunccall 93%type <exVal> regex 94%type <exVal> words 95%type <exVal> wordlist 96%type <exVal> word 97%type <exVal> string 98%type <exVal> strpart 99%type <exVal> var 100%type <exVal> backref 101 102%{ 103#include "util_expr_private.h" 104#define yyscanner ctx->scanner 105 106int ap_expr_yylex(YYSTYPE *lvalp, void *scanner); 107%} 108 109 110%% 111 112root : T_EXPR_BOOL expr { ctx->expr = $2; } 113 | T_EXPR_STRING string { ctx->expr = $2; } 114 | T_ERROR { YYABORT; } 115 ; 116 117expr : T_TRUE { $$ = ap_expr_make(op_True, NULL, NULL, ctx); } 118 | T_FALSE { $$ = ap_expr_make(op_False, NULL, NULL, ctx); } 119 | T_OP_NOT expr { $$ = ap_expr_make(op_Not, $2, NULL, ctx); } 120 | expr T_OP_OR expr { $$ = ap_expr_make(op_Or, $1, $3, ctx); } 121 | expr T_OP_AND expr { $$ = ap_expr_make(op_And, $1, $3, ctx); } 122 | comparison { $$ = ap_expr_make(op_Comp, $1, NULL, ctx); } 123 | T_OP_UNARY word { $$ = ap_expr_unary_op_make( $1, $2, ctx); } 124 | word T_OP_BINARY word { $$ = ap_expr_binary_op_make($2, $1, $3, ctx); } 125 | '(' expr ')' { $$ = $2; } 126 | T_ERROR { YYABORT; } 127 ; 128 129comparison: word T_OP_EQ word { $$ = ap_expr_make(op_EQ, $1, $3, ctx); } 130 | word T_OP_NE word { $$ = ap_expr_make(op_NE, $1, $3, ctx); } 131 | word T_OP_LT word { $$ = ap_expr_make(op_LT, $1, $3, ctx); } 132 | word T_OP_LE word { $$ = ap_expr_make(op_LE, $1, $3, ctx); } 133 | word T_OP_GT word { $$ = ap_expr_make(op_GT, $1, $3, ctx); } 134 | word T_OP_GE word { $$ = ap_expr_make(op_GE, $1, $3, ctx); } 135 | word T_OP_STR_EQ word { $$ = ap_expr_make(op_STR_EQ, $1, $3, ctx); } 136 | word T_OP_STR_NE word { $$ = ap_expr_make(op_STR_NE, $1, $3, ctx); } 137 | word T_OP_STR_LT word { $$ = ap_expr_make(op_STR_LT, $1, $3, ctx); } 138 | word T_OP_STR_LE word { $$ = ap_expr_make(op_STR_LE, $1, $3, ctx); } 139 | word T_OP_STR_GT word { $$ = ap_expr_make(op_STR_GT, $1, $3, ctx); } 140 | word T_OP_STR_GE word { $$ = ap_expr_make(op_STR_GE, $1, $3, ctx); } 141 | word T_OP_IN wordlist { $$ = ap_expr_make(op_IN, $1, $3, ctx); } 142 | word T_OP_REG regex { $$ = ap_expr_make(op_REG, $1, $3, ctx); } 143 | word T_OP_NRE regex { $$ = ap_expr_make(op_NRE, $1, $3, ctx); } 144 ; 145 146wordlist : lstfunccall { $$ = $1; } 147 | '{' words '}' { $$ = $2; } 148 ; 149 150words : word { $$ = ap_expr_make(op_ListElement, $1, NULL, ctx); } 151 | words ',' word { $$ = ap_expr_make(op_ListElement, $3, $1, ctx); } 152 ; 153 154string : string strpart { $$ = ap_expr_make(op_Concat, $1, $2, ctx); } 155 | strpart { $$ = $1; } 156 | T_ERROR { YYABORT; } 157 ; 158 159strpart : T_STRING { $$ = ap_expr_make(op_String, $1, NULL, ctx); } 160 | var { $$ = $1; } 161 | backref { $$ = $1; } 162 ; 163 164var : T_VAR_BEGIN T_ID T_VAR_END { $$ = ap_expr_var_make($2, ctx); } 165 | T_VAR_BEGIN T_ID ':' string T_VAR_END { $$ = ap_expr_str_func_make($2, $4, ctx); } 166 ; 167 168word : T_DIGIT { $$ = ap_expr_make(op_Digit, $1, NULL, ctx); } 169 | word T_OP_CONCAT word { $$ = ap_expr_make(op_Concat, $1, $3, ctx); } 170 | var { $$ = $1; } 171 | backref { $$ = $1; } 172 | strfunccall { $$ = $1; } 173 | T_STR_BEGIN string T_STR_END { $$ = $2; } 174 | T_STR_BEGIN T_STR_END { $$ = ap_expr_make(op_String, "", NULL, ctx); } 175 ; 176 177regex : T_REGEX { 178 ap_regex_t *regex; 179 if ((regex = ap_pregcomp(ctx->pool, $1, 180 AP_REG_EXTENDED|AP_REG_NOSUB)) == NULL) { 181 ctx->error = "Failed to compile regular expression"; 182 YYERROR; 183 } 184 $$ = ap_expr_make(op_Regex, regex, NULL, ctx); 185 } 186 | T_REGEX_I { 187 ap_regex_t *regex; 188 if ((regex = ap_pregcomp(ctx->pool, $1, 189 AP_REG_EXTENDED|AP_REG_NOSUB|AP_REG_ICASE)) == NULL) { 190 ctx->error = "Failed to compile regular expression"; 191 YYERROR; 192 } 193 $$ = ap_expr_make(op_Regex, regex, NULL, ctx); 194 } 195 ; 196 197backref : T_REGEX_BACKREF { 198 int *n = apr_palloc(ctx->pool, sizeof(int)); 199 *n = $1; 200 $$ = ap_expr_make(op_RegexBackref, n, NULL, ctx); 201 } 202 ; 203 204lstfunccall : T_ID '(' word ')' { $$ = ap_expr_list_func_make($1, $3, ctx); } 205 ; 206 207strfunccall : T_ID '(' word ')' { $$ = ap_expr_str_func_make($1, $3, ctx); } 208 ; 209 210%% 211 212void yyerror(ap_expr_parse_ctx_t *ctx, const char *s) 213{ 214 /* s is allocated on the stack */ 215 ctx->error = apr_pstrdup(ctx->ptemp, s); 216} 217 218