1 /* Bison file for rsyslog config format v2 (RainerScript).
2  * Please note: this file introduces the new config format, but maintains
3  * backward compatibility. In order to do so, the grammar is not 100% clean,
4  * but IMHO still sufficiently easy both to understand for programmers
5  * maitaining the code as well as users writing the config file. Users are,
6  * of course, encouraged to use new constructs only. But it needs to be noted
7  * that some of the legacy constructs (specifically the in-front-of-action
8  * PRI filter) are very hard to beat in ease of use, at least for simpler
9  * cases.
10  *
11  * Copyright 2011-2020 Rainer Gerhards and Adiscon GmbH.
12  *
13  * This file is part of the rsyslog runtime library.
14  *
15  * Licensed under the Apache License, Version 2.0 (the "License");
16  * you may not use this file except in compliance with the License.
17  * You may obtain a copy of the License at
18  *
19  *       http://www.apache.org/licenses/LICENSE-2.0
20  *       -or-
21  *       see COPYING.ASL20 in the source distribution
22  *
23  * Unless required by applicable law or agreed to in writing, software
24  * distributed under the License is distributed on an "AS IS" BASIS,
25  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26  * See the License for the specific language governing permissions and
27  * limitations under the License.
28  */
29 %{
30 #define IN_GRAMMAR_Y /* tell parserif.h not to redefine things! */
31 
32 #include "config.h"
33 #include <stdio.h>
34 #include <libestr.h>
35 #include "rainerscript.h"
36 #include "parserif.h"
37 #define YYDEBUG 1
38 extern int yylineno;
39 extern char *yytext;
40 
41 /* keep compile rule clean of errors */
42 extern int yylex(void);
43 extern int yyerror(const char*);
44 %}
45 
46 %union {
47 	char *s;
48 	long long n;
49 	es_str_t *estr;
50 	enum cnfobjType objType;
51 	struct cnfobj *obj;
52 	struct cnfstmt *stmt;
53 	struct nvlst *nvlst;
54 	struct objlst *objlst;
55 	struct cnfexpr *expr;
56 	struct cnfarray *arr;
57 	struct cnffunc *func;
58 	struct cnffuncexists *exists;
59 	struct cnffparamlst *fparams;
60 	struct cnfitr *itr;
61 }
62 
63 %token <estr> NAME
64 %token <estr> FUNC
65 %token <objType> BEGINOBJ
66 %token ENDOBJ
67 %token BEGIN_INCLUDE
68 %token BEGIN_ACTION
69 %token BEGIN_PROPERTY
70 %token BEGIN_CONSTANT
71 %token BEGIN_TPL
72 %token BEGIN_RULESET
73 %token STOP
74 %token SET
75 %token RESET
76 %token UNSET
77 %token CONTINUE
78 %token EXISTS
79 %token <cnfstmt> CALL
80 %token <cnfstmt> CALL_INDIRECT
81 %token <s> LEGACY_ACTION
82 %token <s> LEGACY_RULESET
83 %token <s> PRIFILT
84 %token <s> PROPFILT
85 %token <s> BSD_TAG_SELECTOR
86 %token <s> BSD_HOST_SELECTOR
87 %token <s> RELOAD_LOOKUP_TABLE_PROCEDURE
88 %token IF
89 %token THEN
90 %token ELSE
91 %token FOREACH
92 %token ITERATOR_ASSIGNMENT
93 %token DO
94 %token OR
95 %token AND
96 %token NOT
97 %token <s> VAR
98 %token <estr> STRING
99 %token <n> NUMBER
100 %token CMP_EQ
101 %token CMP_NE
102 %token CMP_LE
103 %token CMP_GE
104 %token CMP_LT
105 %token CMP_GT
106 %token CMP_CONTAINS
107 %token CMP_CONTAINSI
108 %token CMP_STARTSWITH
109 %token CMP_STARTSWITHI
110 
111 %type <nvlst> nv nvlst value
112 %type <obj> obj property constant
113 %type <objlst> propconst
114 %type <expr> expr
115 %type <stmt> stmt s_act actlst block script
116 %type <itr> iterator_decl
117 %type <fparams> fparams
118 %type <arr> array arrayelt
119 
120 %left AND OR
121 %left CMP_EQ CMP_NE CMP_LE CMP_GE CMP_LT CMP_GT CMP_CONTAINS CMP_CONTAINSI CMP_STARTSWITH CMP_STARTSWITHI
122 %left '+' '-' '&'
123 %left '*' '/' '%'
124 %nonassoc UMINUS NOT
125 
126 %expect 1 /* dangling else */
127 /* If more erors show up, Use "bison -v grammar.y" if more conflicts arise and
128  * check grammar.output for were exactly these conflicts exits.
129  */
130 %%
131 /* note: we use left recursion below, because that saves stack space AND
132  * offers the right sequence so that we can submit the top-layer objects
133  * one by one.
134  */
135 conf:	/* empty (to end recursion) */
136 	| conf obj			{ cnfDoObj($2); }
137 	| conf stmt			{ cnfDoScript($2); }
138 	| conf LEGACY_RULESET		{ cnfDoCfsysline($2); }
139 	| conf BSD_TAG_SELECTOR		{ cnfDoBSDTag($2); }
140 	| conf BSD_HOST_SELECTOR	{ cnfDoBSDHost($2); }
141 include:  BEGIN_INCLUDE nvlst ENDOBJ	{ includeProcessCnf($2); }
142 obj:	  BEGINOBJ nvlst ENDOBJ 	{ $$ = cnfobjNew($1, $2); }
143         | BEGIN_TPL nvlst ENDOBJ	{ $$ = cnfobjNew(CNFOBJ_TPL, $2); }
144         | BEGIN_TPL nvlst ENDOBJ '{' propconst '}'
145 					{ $$ = cnfobjNew(CNFOBJ_TPL, $2);
146 					  $$->subobjs = $5;
147 					}
148         | BEGIN_RULESET nvlst ENDOBJ '{' script '}'
149 					{ $$ = cnfobjNew(CNFOBJ_RULESET, $2);
150 					  $$->script = $5;
151 					}
152         | BEGIN_RULESET nvlst ENDOBJ '{' '}'
153 					{ $$ = cnfobjNew(CNFOBJ_RULESET, $2);
154 					  $$->script = NULL;
155 					}
156 propconst:				{ $$ = NULL; }
157 	| propconst property		{ $$ = objlstAdd($1, $2); }
158 	| propconst constant		{ $$ = objlstAdd($1, $2); }
159 property: BEGIN_PROPERTY nvlst ENDOBJ	{ $$ = cnfobjNew(CNFOBJ_PROPERTY, $2); }
160 constant: BEGIN_CONSTANT nvlst ENDOBJ	{ $$ = cnfobjNew(CNFOBJ_CONSTANT, $2); }
161 nvlst:					{ $$ = NULL; }
162 	| nvlst nv 			{ $2->next = $1; $$ = $2; }
163 nv:	NAME '=' value 			{ $$ = nvlstSetName($3, $1); }
164 value:	  STRING			{ $$ = nvlstNewStr($1); }
165 	| array				{ $$ = nvlstNewArray($1); }
166 script:	  stmt				{ $$ = $1; }
167 	| script stmt			{ $$ = scriptAddStmt($1, $2); }
168 stmt:	  actlst			{ $$ = $1; }
169 	| IF expr THEN block 		{ $$ = cnfstmtNew(S_IF);
170 					  $$->d.s_if.expr = $2;
171 					  $$->d.s_if.t_then = $4;
172 					  $$->d.s_if.t_else = NULL; }
173 	| IF expr THEN block ELSE block	{ $$ = cnfstmtNew(S_IF);
174 					  $$->d.s_if.expr = $2;
175 					  $$->d.s_if.t_then = $4;
176 					  $$->d.s_if.t_else = $6; }
177 	| FOREACH iterator_decl DO block { $$ = cnfstmtNew(S_FOREACH);
178 					  $$->d.s_foreach.iter = $2;
179 					  $$->d.s_foreach.body = $4;}
180 	| RESET VAR '=' expr ';'	{ $$ = cnfstmtNewSet($2, $4, 1); }
181 	| SET VAR '=' expr ';'		{ $$ = cnfstmtNewSet($2, $4, 0); }
182 	| UNSET VAR ';'			{ $$ = cnfstmtNewUnset($2); }
183 	| PRIFILT block			{ $$ = cnfstmtNewPRIFILT($1, $2); }
184 	| PROPFILT block		{ $$ = cnfstmtNewPROPFILT($1, $2); }
185 	| RELOAD_LOOKUP_TABLE_PROCEDURE '(' fparams ')' { $$ = cnfstmtNewReloadLookupTable($3);}
186 	| include			{ $$ = NULL; }
187 	| BEGINOBJ			{ $$ = NULL; parser_errmsg("declarative object '%s' not permitted in action block [stmt]", yytext);}
188 block:    stmt				{ $$ = $1; }
189 	| '{' script '}'		{ $$ = $2; }
190 actlst:	  s_act				{ $$ = $1; }
191 	| actlst '&' s_act 		{ $$ = scriptAddStmt($1, $3); }
192 /* s_act are actions and action-like statements */
193 s_act:	  BEGIN_ACTION nvlst ENDOBJ	{ $$ = cnfstmtNewAct($2); }
194 	| LEGACY_ACTION			{ $$ = cnfstmtNewLegaAct($1); }
195 	| STOP				{ $$ = cnfstmtNew(S_STOP); }
196 	| CALL NAME			{ $$ = cnfstmtNewCall($2); }
197 	| CALL_INDIRECT expr ';'	{ $$ = cnfstmtNew(S_CALL_INDIRECT);
198 					  $$->d.s_call_ind.expr = $2;
199 					}
200 	| CONTINUE			{ $$ = cnfstmtNewContinue(); }
201 expr:	  expr AND expr			{ $$ = cnfexprNew(AND, $1, $3); }
202 	| expr OR expr			{ $$ = cnfexprNew(OR, $1, $3); }
203 	| NOT expr			{ $$ = cnfexprNew(NOT, NULL, $2); }
204 	| expr CMP_EQ expr		{ $$ = cnfexprNew(CMP_EQ, $1, $3); }
205 	| expr CMP_NE expr		{ $$ = cnfexprNew(CMP_NE, $1, $3); }
206 	| expr CMP_LE expr		{ $$ = cnfexprNew(CMP_LE, $1, $3); }
207 	| expr CMP_GE expr		{ $$ = cnfexprNew(CMP_GE, $1, $3); }
208 	| expr CMP_LT expr		{ $$ = cnfexprNew(CMP_LT, $1, $3); }
209 	| expr CMP_GT expr		{ $$ = cnfexprNew(CMP_GT, $1, $3); }
210 	| expr CMP_CONTAINS expr	{ $$ = cnfexprNew(CMP_CONTAINS, $1, $3); }
211 	| expr CMP_CONTAINSI expr	{ $$ = cnfexprNew(CMP_CONTAINSI, $1, $3); }
212 	| expr CMP_STARTSWITH expr	{ $$ = cnfexprNew(CMP_STARTSWITH, $1, $3); }
213 	| expr CMP_STARTSWITHI expr	{ $$ = cnfexprNew(CMP_STARTSWITHI, $1, $3); }
214 	| expr '&' expr			{ $$ = cnfexprNew('&', $1, $3); }
215 	| expr '+' expr			{ $$ = cnfexprNew('+', $1, $3); }
216 	| expr '-' expr			{ $$ = cnfexprNew('-', $1, $3); }
217 	| expr '*' expr			{ $$ = cnfexprNew('*', $1, $3); }
218 	| expr '/' expr			{ $$ = cnfexprNew('/', $1, $3); }
219 	| expr '%' expr			{ $$ = cnfexprNew('%', $1, $3); }
220 	| '(' expr ')'			{ $$ = $2; }
221 	| '-' expr %prec UMINUS		{ $$ = cnfexprNew('M', NULL, $2); }
222 	| EXISTS '(' VAR ')'		{ $$ = (struct cnfexpr*) cnffuncexistsNew($3); }
223 	| FUNC '(' ')'			{ $$ = (struct cnfexpr*) cnffuncNew($1, NULL); }
224 	| FUNC '(' fparams ')'		{ $$ = (struct cnfexpr*) cnffuncNew($1, $3); }
225 	| NUMBER			{ $$ = (struct cnfexpr*) cnfnumvalNew($1); }
226 	| STRING			{ $$ = (struct cnfexpr*) cnfstringvalNew($1); }
227 	| VAR				{ $$ = (struct cnfexpr*) cnfvarNew($1); }
228 	| array				{ $$ = (struct cnfexpr*) $1; }
229 fparams:  expr				{ $$ = cnffparamlstNew($1, NULL); }
230 	| expr ',' fparams		{ $$ = cnffparamlstNew($1, $3); }
231 array:	 '[' arrayelt ']'		{ $$ = $2; }
232 iterator_decl:  '(' VAR ITERATOR_ASSIGNMENT expr ')'	{ $$ = cnfNewIterator($2, $4); }
233 arrayelt: STRING			{ $$ = cnfarrayNew($1); }
234 	| arrayelt ',' STRING		{ $$ = cnfarrayAdd($1, $3); }
235 
236 %%
237 /*
238 int yyerror(char *s)
239 {
240 	printf("parse failure on or before line %d: %s\n", yylineno, s);
241 	return 0;
242 }
243 */
244