]> granicus.if.org Git - apache/blob - server/util_expr_parse.y
Fix alignment in a <highlight> block.
[apache] / server / util_expr_parse.y
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                      "true"
42 %token  T_FALSE                     "false"
43
44 %token  T_EXPR_BOOL                 "boolean expression"
45 %token  T_EXPR_STRING               "string expression"
46
47 %token  <cpVal> T_ERROR             "error token"
48
49 %token  <cpVal> T_DIGIT             "number"
50 %token  <cpVal> T_ID                "identifier"
51 %token  <cpVal> T_STRING            "string literal"
52
53 %token          T_REGEX             "start of matching regex"
54 %token          T_REGSUB            "start of substitution regex"
55 %token  <cpVal> T_REG_MATCH         "pattern of the regex"
56 %token  <cpVal> T_REG_SUBST         "substitution of the regex"
57 %token  <cpVal> T_REG_FLAGS         "pattern flags of the regex"
58 %token  <num>   T_BACKREF           "regex back reference"
59
60 %token  <cpVal> T_OP_UNARY          "unary operator"
61 %token  <cpVal> T_OP_BINARY         "binary operator"
62
63 %token  T_STR_BEGIN                 "start of string"
64 %token  T_STR_END                   "end of string"
65 %token  T_VAR_BEGIN                 "start of variable name"
66 %token  T_VAR_END                   "end of variable name"
67 %token  T_VAREXP_BEGIN              "start of variable expression"
68 %token  T_VAREXP_END                "end of variable expression"
69
70 %token  T_OP_EQ                     "integer equal"
71 %token  T_OP_NE                     "integer not equal"
72 %token  T_OP_LT                     "integer less than"
73 %token  T_OP_LE                     "integer less or equal"
74 %token  T_OP_GT                     "integer greater than"
75 %token  T_OP_GE                     "integer greater or equal"
76 %token  T_OP_REG                    "regex match"
77 %token  T_OP_NRE                    "regex non-match"
78 %token  T_OP_IN                     "contained in"
79 %token  T_OP_STR_EQ                 "string equal"
80 %token  T_OP_STR_NE                 "string not equal"
81 %token  T_OP_STR_LT                 "string less than"
82 %token  T_OP_STR_LE                 "string less or equal"
83 %token  T_OP_STR_GT                 "string greater than"
84 %token  T_OP_STR_GE                 "string greater or equal"
85
86 %token  T_OP_CONCAT                 "string concatenation"
87
88 %token  T_OP_JOIN                   "join operator"
89 %token  T_OP_SPLIT                  "split operator"
90 %token  T_OP_SUB                    "substitute operator"
91
92 %token  T_OP_OR                     "logical or"
93 %token  T_OP_AND                    "logical and"
94 %token  T_OP_NOT                    "logical not"
95
96 %left   T_OP_OR
97 %left   T_OP_AND
98 %right  T_OP_NOT
99 %right  T_OP_CONCAT
100
101 %type   <exVal>   cond              "condition"
102 %type   <exVal>   comp              "comparison"
103 %type   <exVal>   strfunc           "string function"
104 %type   <exVal>   listfunc          "list function"
105 %type   <exVal>   list              "list"
106 %type   <exVal>   words             "words"
107 %type   <exVal>   word              "word"
108 %type   <exVal>   string            "string"
109 %type   <exVal>   substr            "substring"
110 %type   <exVal>   var               "variable"
111 %type   <exVal>   regex             "match regex"
112 %type   <exVal>   regsub            "substitution regex"
113 %type   <exVal>   regany            "any regex"
114 %type   <exVal>   split             "split"
115 %type   <exVal>   join              "join"
116 %type   <exVal>   sub               "sub"
117
118 %{
119 #include "util_expr_private.h"
120 #define yyscanner ctx->scanner
121
122 int ap_expr_yylex(YYSTYPE *lvalp, void *scanner);
123 %}
124
125
126 %%
127
128 expr      : T_EXPR_STRING string         { ctx->expr = $2; }
129           | T_EXPR_BOOL   cond           { ctx->expr = $2; }
130           | T_ERROR                      { YYABORT; }
131           ;
132
133 string    : substr                       { $$ = $1; }
134           | string substr                { $$ = ap_expr_concat_make($1, $2, ctx); }
135           | T_ERROR                      { YYABORT; }
136           ;
137
138 cond      : T_TRUE                       { $$ = ap_expr_make(op_True,        NULL, NULL, ctx); }
139           | T_FALSE                      { $$ = ap_expr_make(op_False,       NULL, NULL, ctx); }
140           | T_OP_NOT cond                { $$ = ap_expr_make(op_Not,         $2,   NULL, ctx); }
141           | cond T_OP_OR cond            { $$ = ap_expr_make(op_Or,          $1,   $3,   ctx); }
142           | cond T_OP_AND cond           { $$ = ap_expr_make(op_And,         $1,   $3,   ctx); }
143           | comp                         { $$ = ap_expr_make(op_Comp,        $1,   NULL, ctx); }
144           | T_OP_UNARY word              { $$ = ap_expr_unary_op_make(       $1,   $2,   ctx); }
145           | word T_OP_BINARY word        { $$ = ap_expr_binary_op_make($2,   $1,   $3,   ctx); }
146           | '(' cond ')'                 { $$ = $2; }
147           | T_ERROR                      { YYABORT; }
148           ;
149
150 comp      : word T_OP_EQ word            { $$ = ap_expr_make(op_EQ,      $1, $3, ctx); }
151           | word T_OP_NE word            { $$ = ap_expr_make(op_NE,      $1, $3, ctx); }
152           | word T_OP_LT word            { $$ = ap_expr_make(op_LT,      $1, $3, ctx); }
153           | word T_OP_LE word            { $$ = ap_expr_make(op_LE,      $1, $3, ctx); }
154           | word T_OP_GT word            { $$ = ap_expr_make(op_GT,      $1, $3, ctx); }
155           | word T_OP_GE word            { $$ = ap_expr_make(op_GE,      $1, $3, ctx); }
156           | word T_OP_STR_EQ word        { $$ = ap_expr_make(op_STR_EQ,  $1, $3, ctx); }
157           | word T_OP_STR_NE word        { $$ = ap_expr_make(op_STR_NE,  $1, $3, ctx); }
158           | word T_OP_STR_LT word        { $$ = ap_expr_make(op_STR_LT,  $1, $3, ctx); }
159           | word T_OP_STR_LE word        { $$ = ap_expr_make(op_STR_LE,  $1, $3, ctx); }
160           | word T_OP_STR_GT word        { $$ = ap_expr_make(op_STR_GT,  $1, $3, ctx); }
161           | word T_OP_STR_GE word        { $$ = ap_expr_make(op_STR_GE,  $1, $3, ctx); }
162           | word T_OP_REG regex          { $$ = ap_expr_make(op_REG,     $1, $3, ctx); }
163           | word T_OP_NRE regex          { $$ = ap_expr_make(op_NRE,     $1, $3, ctx); }
164           | word T_OP_IN list            { $$ = ap_expr_make(op_IN,      $1, $3, ctx); }
165           ;
166
167 word      : T_DIGIT                      { $$ = ap_expr_make(op_Digit,  $1, NULL, ctx); }
168           | T_STR_BEGIN T_STR_END        { $$ = ap_expr_make(op_String, "", NULL, ctx); }
169           | T_STR_BEGIN string T_STR_END { $$ = $2; }
170           | word T_OP_CONCAT word        { $$ = ap_expr_make(op_Concat, $1, $3,   ctx); }
171           | var                          { $$ = $1; }
172           | sub                          { $$ = $1; }
173           | join                         { $$ = $1; }
174           | strfunc                      { $$ = $1; }
175           | '(' word ')'                 { $$ = $2; }
176           ;
177
178 list      : split                        { $$ = $1; }
179           | listfunc                     { $$ = $1; }
180           | '{' words '}'                { $$ = $2; }
181           | '(' list ')'                 { $$ = $2; }
182           ;
183
184 substr    : T_STRING                     { $$ = ap_expr_make(op_String, $1, NULL, ctx); }
185           | var                          { $$ = $1; }
186           ;
187
188 var       : T_VAR_BEGIN T_ID T_VAR_END            { $$ = ap_expr_var_make($2, ctx); }
189           | T_VAR_BEGIN T_ID ':' string T_VAR_END { $$ = ap_expr_str_func_make($2, $4, ctx); }
190           | T_VAREXP_BEGIN cond T_VAREXP_END      { $$ = ap_expr_make(op_Bool, $2, NULL, ctx); }
191           | T_VAREXP_BEGIN word T_VAREXP_END      { $$ = ap_expr_make(op_Word, $2, NULL, ctx); }
192           | T_BACKREF                             { $$ = ap_expr_backref_make($1, ctx); }
193           ;
194
195 strfunc   : T_ID '(' word ')'            { $$ = ap_expr_str_func_make($1, $3, ctx); }
196           | T_ID '(' words ')'           { $$ = ap_expr_str_func_make($1, $3, ctx); }
197           ;
198
199 listfunc  : T_ID '(' word ')'            { $$ = ap_expr_list_func_make($1, $3, ctx); }
200        /* | T_ID '(' words ')'           { $$ = ap_expr_list_func_make($1, $3, ctx); } */
201           ;
202
203 sub       : T_OP_SUB     regsub ',' word     { $$ = ap_expr_make(op_Sub, $4, $2, ctx); }
204           | T_OP_SUB '(' regsub ',' word ')' { $$ = ap_expr_make(op_Sub, $5, $3, ctx); }
205           ;
206
207 join      : T_OP_JOIN     list              { $$ = ap_expr_make(op_Join, $2, NULL, ctx); }
208           | T_OP_JOIN '(' list ')'          { $$ = ap_expr_make(op_Join, $3, NULL, ctx); }
209           | T_OP_JOIN     list ',' word     { $$ = ap_expr_make(op_Join, $2, $4,   ctx); }
210           | T_OP_JOIN '(' list ',' word ')' { $$ = ap_expr_make(op_Join, $3, $5,   ctx); }
211           ;
212
213 split     : T_OP_SPLIT     regany ',' list     { $$ = ap_expr_make(op_Split, $4, $2, ctx); }
214           | T_OP_SPLIT '(' regany ',' list ')' { $$ = ap_expr_make(op_Split, $5, $3, ctx); }
215           | T_OP_SPLIT     regany ',' word     { $$ = ap_expr_make(op_Split, $4, $2, ctx); }
216           | T_OP_SPLIT '(' regany ',' word ')' { $$ = ap_expr_make(op_Split, $5, $3, ctx); }
217           ;
218
219 words     : word                         { $$ = ap_expr_make(op_ListElement, $1, NULL, ctx); }
220           | word ',' words               { $$ = ap_expr_make(op_ListElement, $1, $3,   ctx); }
221           ;
222
223 regex     : T_REGEX T_REG_MATCH T_REG_FLAGS {
224                 ap_expr_t *e = ap_expr_regex_make($2, NULL, $3, ctx);
225                 if (!e) {
226                     ctx->error = "Failed to compile regular expression";
227                     YYERROR;
228                 }
229                 $$ = e;
230             }
231           ;
232 regsub    : T_REGSUB T_REG_MATCH string T_REG_FLAGS {
233                 ap_expr_t *e = ap_expr_regex_make($2, $3, $4, ctx);
234                 if (!e) {
235                     ctx->error = "Failed to compile regular expression";
236                     YYERROR;
237                 }
238                 $$ = e;
239             }
240           ;
241 regany    : regex   { $$ = $1; }
242           | regsub  { $$ = $1; }
243           ;
244
245 %%
246
247 void yyerror(ap_expr_parse_ctx_t *ctx, const char *s)
248 {
249     /* s is allocated on the stack */
250     ctx->error = apr_pstrdup(ctx->ptemp, s);
251 }
252