/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following functions.
- yyparse
- componentserror
- yyerror
- syntax_error
- yywrap
- yy_input
- main
1 %{
2 /*
3 filename: components.y
4
5 description:
6 Defines the grammar for an RPSL component attribute. It was mostly
7 stolen from the IRRToolSet, simplified by removing ability to parse
8 things defined by a dictionary (we use XML for extensibility rather
9 than a dictionary).
10
11 notes:
12 Defines tokens for the associated lexer, components.l.
13 */
14 %}
15
16 %union {
17 char *sval;
18 }
19
20 %token OP_OR OP_AND OP_NOT OP_MS OP_EQUAL OP_APPEND OP_COMPARE
21 %token KEYW_ANY KEYW_PEERAS
22 %token ASPATH_POSTFIX
23 %token TKN_FLTRNAME TKN_ASNO TKN_RSNAME TKN_ASNAME TKN_PRFXV4 TKN_PRFXV4RNG
24 %token KEYW_ATOMIC
25 %token KEYW_PROTOCOL TKN_PROTOCOL
26 %token KEYW_IGP_COST KEYW_SELF KEYW_PREPEND KEYW_APPEND
27 %token KEYW_DELETE KEYW_CONTAINS
28 %token KEYW_INTERNET KEYW_NO_EXPORT KEYW_NO_ADVERTISE
29 %token TKN_PREF TKN_MED TKN_DPA TKN_ASPATH TKN_COMMUNITY
30 %token TKN_NEXT_HOP TKN_COST TKN_COMM_NO TKN_IPV4
31
32 %token <sval> TKN_INT
33
34 %{
35 #include <stdio.h>
36 #include <stdarg.h>
37 #include <stdlib.h>
38
39 int yyerror(const char *s);
40
41 /* defines for unit testing */
42 #ifdef UNIT_TEST
43 int main();
44 #endif /* UNIT_TEST */
45 %}
46
47 %%
/* [<][>][^][v][top][bottom][index][help] */
48
49 components: opt_atomic components_list
50 ;
51
52 opt_atomic:
53 | KEYW_ATOMIC
54 ;
55
56 components_list:
57 | filter
58 | components_list KEYW_PROTOCOL TKN_PROTOCOL filter
59 ;
60
61 filter: filter OP_OR filter_term
62 | filter filter_term %prec OP_OR
63 | filter_term
64 ;
65
66 filter_term : filter_term OP_AND filter_factor
67 | filter_factor
68 ;
69
70 filter_factor : OP_NOT filter_factor
71 | '(' filter ')'
72 | filter_operand
73 ;
74
75 filter_operand: KEYW_ANY
76 | '<' filter_aspath '>'
77 | rp_attribute
78 | TKN_FLTRNAME
79 | filter_prefix
80 ;
81
82 filter_prefix: filter_prefix_operand OP_MS
83 | filter_prefix_operand
84 ;
85
86 filter_prefix_operand: TKN_ASNO
87 | KEYW_PEERAS
88 | TKN_ASNAME
89 | TKN_RSNAME
90 | '{' opt_filter_prefix_list '}'
91 ;
92
93 opt_filter_prefix_list:
94 | filter_prefix_list
95 ;
96
97 filter_prefix_list: filter_prefix_list_prefix
98 | filter_prefix_list ',' filter_prefix_list_prefix
99 ;
100
101 filter_prefix_list_prefix: TKN_PRFXV4
102 | TKN_PRFXV4RNG
103 ;
104
105 filter_aspath: filter_aspath '|' filter_aspath_term
106 | filter_aspath_term
107 ;
108
109 filter_aspath_term: filter_aspath_term filter_aspath_closure
110 | filter_aspath_closure
111 ;
112
113 filter_aspath_closure: filter_aspath_closure '*'
114 | filter_aspath_closure '?'
115 | filter_aspath_closure '+'
116 | filter_aspath_closure ASPATH_POSTFIX
117 | filter_aspath_factor
118 ;
119
120 filter_aspath_factor: '^'
121 | '$'
122 | '(' filter_aspath ')'
123 | filter_aspath_no
124 ;
125
126 filter_aspath_no: TKN_ASNO
127 | KEYW_PEERAS
128 | TKN_ASNAME
129 | '.'
130 | '[' filter_aspath_range ']'
131 | '[' '^' filter_aspath_range ']'
132 ;
133
134 filter_aspath_range:
135 | filter_aspath_range TKN_ASNO
136 | filter_aspath_range KEYW_PEERAS
137 | filter_aspath_range '.'
138 | filter_aspath_range TKN_ASNO '-' TKN_ASNO
139 | filter_aspath_range TKN_ASNAME
140 ;
141
142 rp_attribute: pref
143 | med
144 | dpa
145 | aspath
146 | community
147 | next_hop
148 | cost
149 ;
150
151 pref: TKN_PREF OP_EQUAL TKN_INT {
152 long int val;
153 char *s, *p;
154 p = $3;
155 val = strtol(p, &s, 10);
156 if ((val < 0) || (val > 65535)) {
157 syntax_error("pref value \"%s\" is not between 0 and 65535", p);
158 }
159 }
160 ;
161
162 med: TKN_MED OP_EQUAL TKN_INT {
163 long int val;
164 char *s, *p;
165 p = $3;
166 val = strtol(p, &s, 10);
167 if ((val < 0) || (val > 65535)) {
168 syntax_error("med value \"%s\" is not between 0 and 65535", p);
169 }
170 }
171 | TKN_MED OP_EQUAL KEYW_IGP_COST
172 ;
173
174 dpa: TKN_DPA OP_EQUAL TKN_INT {
175 long int val;
176 char *s, *p;
177 p = $3;
178 val = strtol(p, &s, 10);
179 if ((val < 0) || (val > 65535)) {
180 syntax_error("dpa value \"%s\" is not between 0 and 65535", p);
181 }
182 }
183 ;
184
185 aspath: TKN_ASPATH '.' KEYW_PREPEND '(' asno_list ')'
186 ;
187
188 asno_list: TKN_ASNO
189 | asno_list ',' TKN_ASNO
190 ;
191
192 community: TKN_COMMUNITY OP_EQUAL community_list
193 | TKN_COMMUNITY OP_APPEND community_list
194 | TKN_COMMUNITY '.' KEYW_APPEND '(' community_elm_list ')'
195 | TKN_COMMUNITY '.' KEYW_DELETE '(' community_elm_list ')'
196 | TKN_COMMUNITY '.' KEYW_CONTAINS '(' community_elm_list ')'
197 | TKN_COMMUNITY '(' community_elm_list ')'
198 | TKN_COMMUNITY OP_COMPARE community_list
199 ;
200
201 community_list: '{' community_elm_list '}'
202 ;
203
204 community_elm_list: community_elm
205 | community_elm_list ',' community_elm
206 ;
207
208 community_elm: KEYW_INTERNET
209 | KEYW_NO_EXPORT
210 | KEYW_NO_ADVERTISE
211 | TKN_INT {
212 unsigned long int val;
213 char *s, *p;
214 p = $1;
215 val = strtoul(p, &s, 10);
216 if ((val < 1) || (val > 4294967295UL) || (*s != '\0')) {
217 syntax_error("community element \"%s\" is not between 1 and 4294967295",
218 p);
219 }
220 }
221 | TKN_COMM_NO
222 ;
223
224 next_hop: TKN_NEXT_HOP OP_EQUAL TKN_IPV4
225 | TKN_NEXT_HOP OP_EQUAL KEYW_SELF
226 ;
227
228 cost: TKN_COST OP_EQUAL TKN_INT {
229 long int val;
230 char *s, *p;
231 p = $3;
232 val = strtol(p, &s, 10);
233 if ((val < 0) || (val > 65535)) {
234 syntax_error("cost value \"%s\" is not between 0 and 65535", p);
235 }
236 }
237 ;
238
239 %%
240
241 /* define a unit test that simply returns "yes" or "no" for filter input */
242 #ifndef UNIT_TEST
243
244 #undef componentserror
245 #undef yyerror
246
247 int
248 componentserror (const char *s)
/* [<][>][^][v][top][bottom][index][help] */
249 {
250 yyerror(s);
251 return 0;
252 }
253 #else /* UNIT_TEST */
254
255 int parse_error_count;
256
257 /* parse error */
258 void
259 yyerror(const char *s)
/* [<][>][^][v][top][bottom][index][help] */
260 {
261 fputs(s, stderr);
262 putc('\n', stderr);
263 parse_error_count++;
264 }
265
266 /* syntax error */
267 void
268 syntax_error(const char *fmt, ...)
/* [<][>][^][v][top][bottom][index][help] */
269 {
270 va_list args;
271 char buf[1024];
272
273 va_start(args, fmt);
274 vsnprintf(buf, sizeof(buf), fmt, args);
275 va_end(args);
276 yyerror(buf);
277 }
278
279 int
280 yywrap()
/* [<][>][^][v][top][bottom][index][help] */
281 {
282 return 1;
283 }
284
285 /* taken from _lex & yacc_ p.157, by Levine, Mason, & Brown (corrected) */
286 char *myinputptr;
287 char *myinputlim;
288
289 #undef min
290 #define min(a, b) (((a) < (b)) ? (a) : (b))
291
292 void
293 yy_input(char *buf, int *result, int max_size)
/* [<][>][^][v][top][bottom][index][help] */
294 {
295 int n = min(max_size, myinputlim - myinputptr);
296
297 if (n > 0) {
298 memcpy(buf, myinputptr, n);
299 myinputptr += n;
300 }
301 *result = n;
302 }
303
304 /* program entry point */
305 int
306 main()
/* [<][>][^][v][top][bottom][index][help] */
307 {
308 char buf[4096];
309
310 setbuf(stdout, NULL);
311 for (;;) {
312 printf("filter> ");
313 if (gets(buf) == NULL) {
314 printf("\n");
315 return(0);
316 }
317 parse_error_count = 0;
318 myinputptr = buf;
319 myinputlim = buf + strlen(buf);
320 filterparse();
321 printf("%d parse errors\n", parse_error_count);
322 }
323 }
324 #endif /* UNIT_TEST */