xref: /linux/tools/perf/util/parse-events.y (revision 84caba70d09c20638ee1ecdd24e0932520ad63fe)
1 %define api.pure full
2 %parse-param {void *_parse_state}
3 %parse-param {void *scanner}
4 %lex-param {void* scanner}
5 %locations
6 
7 %{
8 
9 #define YYDEBUG 1
10 
11 #include <errno.h>
12 #include <fnmatch.h>
13 #include <stdio.h>
14 #include <linux/compiler.h>
15 #include <linux/types.h>
16 #include <linux/zalloc.h>
17 #include "pmu.h"
18 #include "pmus.h"
19 #include "evsel.h"
20 #include "parse-events.h"
21 #include "parse-events-bison.h"
22 
23 int parse_events_lex(YYSTYPE * yylval_param, YYLTYPE * yylloc_param , void *yyscanner);
24 void parse_events_error(YYLTYPE *loc, void *parse_state, void *scanner, char const *msg);
25 
26 #define PE_ABORT(val) \
27 do { \
28 	if (val == -ENOMEM) \
29 		YYNOMEM; \
30 	YYABORT; \
31 } while (0)
32 
33 static struct list_head* alloc_list(void)
34 {
35 	struct list_head *list;
36 
37 	list = malloc(sizeof(*list));
38 	if (!list)
39 		return NULL;
40 
41 	INIT_LIST_HEAD(list);
42 	return list;
43 }
44 
45 static void free_list_evsel(struct list_head* list_evsel)
46 {
47 	struct evsel *evsel, *tmp;
48 
49 	list_for_each_entry_safe(evsel, tmp, list_evsel, core.node) {
50 		list_del_init(&evsel->core.node);
51 		evsel__delete(evsel);
52 	}
53 	free(list_evsel);
54 }
55 
56 %}
57 
58 %token PE_START_EVENTS PE_START_TERMS
59 %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_TERM
60 %token PE_VALUE_SYM_TOOL
61 %token PE_EVENT_NAME
62 %token PE_RAW PE_NAME
63 %token PE_BPF_OBJECT PE_BPF_SOURCE
64 %token PE_MODIFIER_EVENT PE_MODIFIER_BP PE_BP_COLON PE_BP_SLASH
65 %token PE_LEGACY_CACHE
66 %token PE_PREFIX_MEM
67 %token PE_ERROR
68 %token PE_DRV_CFG_TERM
69 %token PE_TERM_HW
70 %type <num> PE_VALUE
71 %type <num> PE_VALUE_SYM_HW
72 %type <num> PE_VALUE_SYM_SW
73 %type <num> PE_VALUE_SYM_TOOL
74 %type <num> PE_TERM
75 %type <num> value_sym
76 %type <str> PE_RAW
77 %type <str> PE_NAME
78 %type <str> PE_BPF_OBJECT
79 %type <str> PE_BPF_SOURCE
80 %type <str> PE_LEGACY_CACHE
81 %type <str> PE_MODIFIER_EVENT
82 %type <str> PE_MODIFIER_BP
83 %type <str> PE_EVENT_NAME
84 %type <str> PE_DRV_CFG_TERM
85 %type <str> name_or_raw name_or_legacy
86 %destructor { free ($$); } <str>
87 %type <term> event_term
88 %destructor { parse_events_term__delete ($$); } <term>
89 %type <list_terms> event_config
90 %type <list_terms> opt_event_config
91 %type <list_terms> opt_pmu_config
92 %destructor { parse_events_terms__delete ($$); } <list_terms>
93 %type <list_evsel> event_pmu
94 %type <list_evsel> event_legacy_symbol
95 %type <list_evsel> event_legacy_cache
96 %type <list_evsel> event_legacy_mem
97 %type <list_evsel> event_legacy_tracepoint
98 %type <list_evsel> event_legacy_numeric
99 %type <list_evsel> event_legacy_raw
100 %type <list_evsel> event_bpf_file
101 %type <list_evsel> event_def
102 %type <list_evsel> event_mod
103 %type <list_evsel> event_name
104 %type <list_evsel> event
105 %type <list_evsel> events
106 %type <list_evsel> group_def
107 %type <list_evsel> group
108 %type <list_evsel> groups
109 %destructor { free_list_evsel ($$); } <list_evsel>
110 %type <tracepoint_name> tracepoint_name
111 %type <hardware_term> PE_TERM_HW
112 %destructor { free ($$.str); } <hardware_term>
113 
114 %union
115 {
116 	char *str;
117 	u64 num;
118 	struct list_head *list_evsel;
119 	struct list_head *list_terms;
120 	struct parse_events_term *term;
121 	struct tracepoint_name {
122 		char *sys;
123 		char *event;
124 	} tracepoint_name;
125 	struct hardware_term {
126 		char *str;
127 		u64 num;
128 	} hardware_term;
129 }
130 %%
131 
132 start:
133 PE_START_EVENTS start_events
134 |
135 PE_START_TERMS  start_terms
136 
137 start_events: groups
138 {
139 	struct parse_events_state *parse_state = _parse_state;
140 
141 	/* frees $1 */
142 	parse_events_update_lists($1, &parse_state->list);
143 }
144 
145 groups:
146 groups ',' group
147 {
148 	struct list_head *list  = $1;
149 	struct list_head *group = $3;
150 
151 	/* frees $3 */
152 	parse_events_update_lists(group, list);
153 	$$ = list;
154 }
155 |
156 groups ',' event
157 {
158 	struct list_head *list  = $1;
159 	struct list_head *event = $3;
160 
161 	/* frees $3 */
162 	parse_events_update_lists(event, list);
163 	$$ = list;
164 }
165 |
166 group
167 |
168 event
169 
170 group:
171 group_def ':' PE_MODIFIER_EVENT
172 {
173 	struct list_head *list = $1;
174 	int err;
175 
176 	err = parse_events__modifier_group(list, $3);
177 	free($3);
178 	if (err) {
179 		struct parse_events_state *parse_state = _parse_state;
180 		struct parse_events_error *error = parse_state->error;
181 
182 		parse_events_error__handle(error, @3.first_column,
183 					   strdup("Bad modifier"), NULL);
184 		free_list_evsel(list);
185 		YYABORT;
186 	}
187 	$$ = list;
188 }
189 |
190 group_def
191 
192 group_def:
193 PE_NAME '{' events '}'
194 {
195 	struct list_head *list = $3;
196 
197 	/* Takes ownership of $1. */
198 	parse_events__set_leader($1, list);
199 	$$ = list;
200 }
201 |
202 '{' events '}'
203 {
204 	struct list_head *list = $2;
205 
206 	parse_events__set_leader(NULL, list);
207 	$$ = list;
208 }
209 
210 events:
211 events ',' event
212 {
213 	struct list_head *event = $3;
214 	struct list_head *list  = $1;
215 
216 	/* frees $3 */
217 	parse_events_update_lists(event, list);
218 	$$ = list;
219 }
220 |
221 event
222 
223 event: event_mod
224 
225 event_mod:
226 event_name PE_MODIFIER_EVENT
227 {
228 	struct list_head *list = $1;
229 	int err;
230 
231 	/*
232 	 * Apply modifier on all events added by single event definition
233 	 * (there could be more events added for multiple tracepoint
234 	 * definitions via '*?'.
235 	 */
236 	err = parse_events__modifier_event(list, $2, false);
237 	free($2);
238 	if (err) {
239 		struct parse_events_state *parse_state = _parse_state;
240 		struct parse_events_error *error = parse_state->error;
241 
242 		parse_events_error__handle(error, @2.first_column,
243 					   strdup("Bad modifier"), NULL);
244 		free_list_evsel(list);
245 		YYABORT;
246 	}
247 	$$ = list;
248 }
249 |
250 event_name
251 
252 event_name:
253 PE_EVENT_NAME event_def
254 {
255 	int err;
256 
257 	err = parse_events_name($2, $1);
258 	free($1);
259 	if (err) {
260 		free_list_evsel($2);
261 		YYNOMEM;
262 	}
263 	$$ = $2;
264 }
265 |
266 event_def
267 
268 event_def: event_pmu |
269 	   event_legacy_symbol |
270 	   event_legacy_cache sep_dc |
271 	   event_legacy_mem sep_dc |
272 	   event_legacy_tracepoint sep_dc |
273 	   event_legacy_numeric sep_dc |
274 	   event_legacy_raw sep_dc |
275 	   event_bpf_file
276 
277 event_pmu:
278 PE_NAME opt_pmu_config
279 {
280 	struct parse_events_state *parse_state = _parse_state;
281 	struct list_head *list = NULL, *orig_terms = NULL, *terms= NULL;
282 	char *pattern = NULL;
283 
284 #define CLEANUP						\
285 	do {						\
286 		parse_events_terms__delete($2);		\
287 		parse_events_terms__delete(orig_terms);	\
288 		free(list);				\
289 		free($1);				\
290 		free(pattern);				\
291 	} while(0)
292 
293 	if (parse_events_copy_term_list($2, &orig_terms)) {
294 		CLEANUP;
295 		YYNOMEM;
296 	}
297 
298 	list = alloc_list();
299 	if (!list) {
300 		CLEANUP;
301 		YYNOMEM;
302 	}
303 	/* Attempt to add to list assuming $1 is a PMU name. */
304 	if (parse_events_add_pmu(parse_state, list, $1, $2, /*auto_merge_stats=*/false, &@1)) {
305 		struct perf_pmu *pmu = NULL;
306 		int ok = 0;
307 
308 		/* Failure to add, try wildcard expansion of $1 as a PMU name. */
309 		if (asprintf(&pattern, "%s*", $1) < 0) {
310 			CLEANUP;
311 			YYNOMEM;
312 		}
313 
314 		while ((pmu = perf_pmus__scan(pmu)) != NULL) {
315 			char *name = pmu->name;
316 
317 			if (parse_events__filter_pmu(parse_state, pmu))
318 				continue;
319 
320 			if (!strncmp(name, "uncore_", 7) &&
321 			    strncmp($1, "uncore_", 7))
322 				name += 7;
323 			if (!perf_pmu__match(pattern, name, $1) ||
324 			    !perf_pmu__match(pattern, pmu->alias_name, $1)) {
325 				bool auto_merge_stats = perf_pmu__auto_merge_stats(pmu);
326 
327 				if (parse_events_copy_term_list(orig_terms, &terms)) {
328 					CLEANUP;
329 					YYNOMEM;
330 				}
331 				if (!parse_events_add_pmu(parse_state, list, pmu->name, terms,
332 							  auto_merge_stats, &@1)) {
333 					ok++;
334 					parse_state->wild_card_pmus = true;
335 				}
336 				parse_events_terms__delete(terms);
337 			}
338 		}
339 
340 		if (!ok) {
341 			/* Failure to add, assume $1 is an event name. */
342 			zfree(&list);
343 			ok = !parse_events_multi_pmu_add(parse_state, $1, $2, &list, &@1);
344 			$2 = NULL;
345 		}
346 		if (!ok) {
347 			struct parse_events_error *error = parse_state->error;
348 			char *help;
349 
350 			if (asprintf(&help, "Unabled to find PMU or event on a PMU of '%s'", $1) < 0)
351 				help = NULL;
352 			parse_events_error__handle(error, @1.first_column,
353 						   strdup("Bad event or PMU"),
354 						   help);
355 			CLEANUP;
356 			YYABORT;
357 		}
358 	}
359 	$$ = list;
360 	list = NULL;
361 	CLEANUP;
362 #undef CLEANUP
363 }
364 |
365 PE_NAME sep_dc
366 {
367 	struct list_head *list;
368 	int err;
369 
370 	err = parse_events_multi_pmu_add(_parse_state, $1, NULL, &list, &@1);
371 	if (err < 0) {
372 		struct parse_events_state *parse_state = _parse_state;
373 		struct parse_events_error *error = parse_state->error;
374 		char *help;
375 
376 		if (asprintf(&help, "Unabled to find PMU or event on a PMU of '%s'", $1) < 0)
377 			help = NULL;
378 		parse_events_error__handle(error, @1.first_column, strdup("Bad event name"), help);
379 		free($1);
380 		PE_ABORT(err);
381 	}
382 	free($1);
383 	$$ = list;
384 }
385 
386 value_sym:
387 PE_VALUE_SYM_HW
388 |
389 PE_VALUE_SYM_SW
390 
391 event_legacy_symbol:
392 value_sym '/' event_config '/'
393 {
394 	struct list_head *list;
395 	int type = $1 >> 16;
396 	int config = $1 & 255;
397 	int err;
398 	bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
399 
400 	list = alloc_list();
401 	if (!list)
402 		YYNOMEM;
403 	err = parse_events_add_numeric(_parse_state, list, type, config, $3, wildcard);
404 	parse_events_terms__delete($3);
405 	if (err) {
406 		free_list_evsel(list);
407 		PE_ABORT(err);
408 	}
409 	$$ = list;
410 }
411 |
412 value_sym sep_slash_slash_dc
413 {
414 	struct list_head *list;
415 	int type = $1 >> 16;
416 	int config = $1 & 255;
417 	bool wildcard = (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE);
418 	int err;
419 
420 	list = alloc_list();
421 	if (!list)
422 		YYNOMEM;
423 	err = parse_events_add_numeric(_parse_state, list, type, config, /*head_config=*/NULL, wildcard);
424 	if (err)
425 		PE_ABORT(err);
426 	$$ = list;
427 }
428 |
429 PE_VALUE_SYM_TOOL sep_slash_slash_dc
430 {
431 	struct list_head *list;
432 	int err;
433 
434 	list = alloc_list();
435 	if (!list)
436 		YYNOMEM;
437 	err = parse_events_add_tool(_parse_state, list, $1);
438 	if (err)
439 		YYNOMEM;
440 	$$ = list;
441 }
442 
443 event_legacy_cache:
444 PE_LEGACY_CACHE opt_event_config
445 {
446 	struct parse_events_state *parse_state = _parse_state;
447 	struct list_head *list;
448 	int err;
449 
450 	list = alloc_list();
451 	if (!list)
452 		YYNOMEM;
453 
454 	err = parse_events_add_cache(list, &parse_state->idx, $1, parse_state, $2);
455 
456 	parse_events_terms__delete($2);
457 	free($1);
458 	if (err) {
459 		free_list_evsel(list);
460 		PE_ABORT(err);
461 	}
462 	$$ = list;
463 }
464 
465 event_legacy_mem:
466 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
467 {
468 	struct list_head *list;
469 	int err;
470 
471 	list = alloc_list();
472 	if (!list)
473 		YYNOMEM;
474 
475 	err = parse_events_add_breakpoint(_parse_state, list,
476 					  $2, $6, $4, $7);
477 	parse_events_terms__delete($7);
478 	free($6);
479 	if (err) {
480 		free(list);
481 		PE_ABORT(err);
482 	}
483 	$$ = list;
484 }
485 |
486 PE_PREFIX_MEM PE_VALUE PE_BP_SLASH PE_VALUE opt_event_config
487 {
488 	struct list_head *list;
489 	int err;
490 
491 	list = alloc_list();
492 	if (!list)
493 		YYNOMEM;
494 
495 	err = parse_events_add_breakpoint(_parse_state, list,
496 					  $2, NULL, $4, $5);
497 	parse_events_terms__delete($5);
498 	if (err) {
499 		free(list);
500 		PE_ABORT(err);
501 	}
502 	$$ = list;
503 }
504 |
505 PE_PREFIX_MEM PE_VALUE PE_BP_COLON PE_MODIFIER_BP opt_event_config
506 {
507 	struct list_head *list;
508 	int err;
509 
510 	list = alloc_list();
511 	if (!list)
512 		YYNOMEM;
513 
514 	err = parse_events_add_breakpoint(_parse_state, list,
515 					  $2, $4, 0, $5);
516 	parse_events_terms__delete($5);
517 	free($4);
518 	if (err) {
519 		free(list);
520 		PE_ABORT(err);
521 	}
522 	$$ = list;
523 }
524 |
525 PE_PREFIX_MEM PE_VALUE opt_event_config
526 {
527 	struct list_head *list;
528 	int err;
529 
530 	list = alloc_list();
531 	if (!list)
532 		YYNOMEM;
533 	err = parse_events_add_breakpoint(_parse_state, list,
534 					  $2, NULL, 0, $3);
535 	parse_events_terms__delete($3);
536 	if (err) {
537 		free(list);
538 		PE_ABORT(err);
539 	}
540 	$$ = list;
541 }
542 
543 event_legacy_tracepoint:
544 tracepoint_name opt_event_config
545 {
546 	struct parse_events_state *parse_state = _parse_state;
547 	struct parse_events_error *error = parse_state->error;
548 	struct list_head *list;
549 	int err;
550 
551 	list = alloc_list();
552 	if (!list)
553 		YYNOMEM;
554 	if (error)
555 		error->idx = @1.first_column;
556 
557 	err = parse_events_add_tracepoint(list, &parse_state->idx, $1.sys, $1.event,
558 					error, $2, &@1);
559 
560 	parse_events_terms__delete($2);
561 	free($1.sys);
562 	free($1.event);
563 	if (err) {
564 		free(list);
565 		PE_ABORT(err);
566 	}
567 	$$ = list;
568 }
569 
570 tracepoint_name:
571 PE_NAME ':' PE_NAME
572 {
573 	struct tracepoint_name tracepoint = {$1, $3};
574 
575 	$$ = tracepoint;
576 }
577 
578 event_legacy_numeric:
579 PE_VALUE ':' PE_VALUE opt_event_config
580 {
581 	struct list_head *list;
582 	int err;
583 
584 	list = alloc_list();
585 	if (!list)
586 		YYNOMEM;
587 	err = parse_events_add_numeric(_parse_state, list, (u32)$1, $3, $4,
588 				       /*wildcard=*/false);
589 	parse_events_terms__delete($4);
590 	if (err) {
591 		free(list);
592 		PE_ABORT(err);
593 	}
594 	$$ = list;
595 }
596 
597 event_legacy_raw:
598 PE_RAW opt_event_config
599 {
600 	struct list_head *list;
601 	int err;
602 	u64 num;
603 
604 	list = alloc_list();
605 	if (!list)
606 		YYNOMEM;
607 	errno = 0;
608 	num = strtoull($1 + 1, NULL, 16);
609 	/* Given the lexer will only give [a-fA-F0-9]+ a failure here should be impossible. */
610 	if (errno)
611 		YYABORT;
612 	free($1);
613 	err = parse_events_add_numeric(_parse_state, list, PERF_TYPE_RAW, num, $2,
614 				       /*wildcard=*/false);
615 	parse_events_terms__delete($2);
616 	if (err) {
617 		free(list);
618 		PE_ABORT(err);
619 	}
620 	$$ = list;
621 }
622 
623 event_bpf_file:
624 PE_BPF_OBJECT opt_event_config
625 {
626 	struct parse_events_state *parse_state = _parse_state;
627 	struct list_head *list;
628 	int err;
629 
630 	list = alloc_list();
631 	if (!list)
632 		YYNOMEM;
633 	err = parse_events_load_bpf(parse_state, list, $1, false, $2, &@1);
634 	parse_events_terms__delete($2);
635 	free($1);
636 	if (err) {
637 		free(list);
638 		PE_ABORT(err);
639 	}
640 	$$ = list;
641 }
642 |
643 PE_BPF_SOURCE opt_event_config
644 {
645 	struct list_head *list;
646 	int err;
647 
648 	list = alloc_list();
649 	if (!list)
650 		YYNOMEM;
651 	err = parse_events_load_bpf(_parse_state, list, $1, true, $2, &@1);
652 	parse_events_terms__delete($2);
653 	if (err) {
654 		free(list);
655 		PE_ABORT(err);
656 	}
657 	$$ = list;
658 }
659 
660 opt_event_config:
661 '/' event_config '/'
662 {
663 	$$ = $2;
664 }
665 |
666 '/' '/'
667 {
668 	$$ = NULL;
669 }
670 |
671 {
672 	$$ = NULL;
673 }
674 
675 opt_pmu_config:
676 '/' event_config '/'
677 {
678 	$$ = $2;
679 }
680 |
681 '/' '/'
682 {
683 	$$ = NULL;
684 }
685 
686 start_terms: event_config
687 {
688 	struct parse_events_state *parse_state = _parse_state;
689 	if (parse_state->terms) {
690 		parse_events_terms__delete ($1);
691 		YYABORT;
692 	}
693 	parse_state->terms = $1;
694 }
695 
696 event_config:
697 event_config ',' event_term
698 {
699 	struct list_head *head = $1;
700 	struct parse_events_term *term = $3;
701 
702 	if (!head) {
703 		parse_events_term__delete(term);
704 		YYABORT;
705 	}
706 	list_add_tail(&term->list, head);
707 	$$ = $1;
708 }
709 |
710 event_term
711 {
712 	struct list_head *head = malloc(sizeof(*head));
713 	struct parse_events_term *term = $1;
714 
715 	if (!head)
716 		YYNOMEM;
717 	INIT_LIST_HEAD(head);
718 	list_add_tail(&term->list, head);
719 	$$ = head;
720 }
721 
722 name_or_raw: PE_RAW | PE_NAME | PE_LEGACY_CACHE
723 
724 name_or_legacy: PE_NAME | PE_LEGACY_CACHE
725 
726 event_term:
727 PE_RAW
728 {
729 	struct parse_events_term *term;
730 	int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_RAW,
731 					 strdup("raw"), $1, &@1, &@1);
732 
733 	if (err) {
734 		free($1);
735 		PE_ABORT(err);
736 	}
737 	$$ = term;
738 }
739 |
740 name_or_raw '=' name_or_legacy
741 {
742 	struct parse_events_term *term;
743 	int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER, $1, $3, &@1, &@3);
744 
745 	if (err) {
746 		free($1);
747 		free($3);
748 		PE_ABORT(err);
749 	}
750 	$$ = term;
751 }
752 |
753 name_or_raw '=' PE_VALUE
754 {
755 	struct parse_events_term *term;
756 	int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
757 					 $1, $3, false, &@1, &@3);
758 
759 	if (err) {
760 		free($1);
761 		PE_ABORT(err);
762 	}
763 	$$ = term;
764 }
765 |
766 name_or_raw '=' PE_TERM_HW
767 {
768 	struct parse_events_term *term;
769 	int err = parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
770 					 $1, $3.str, &@1, &@3);
771 
772 	if (err) {
773 		free($1);
774 		free($3.str);
775 		PE_ABORT(err);
776 	}
777 	$$ = term;
778 }
779 |
780 PE_LEGACY_CACHE
781 {
782 	struct parse_events_term *term;
783 	int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE,
784 					 $1, 1, true, &@1, NULL);
785 
786 	if (err) {
787 		free($1);
788 		PE_ABORT(err);
789 	}
790 	$$ = term;
791 }
792 |
793 PE_NAME
794 {
795 	struct parse_events_term *term;
796 	int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
797 					 $1, 1, true, &@1, NULL);
798 
799 	if (err) {
800 		free($1);
801 		PE_ABORT(err);
802 	}
803 	$$ = term;
804 }
805 |
806 PE_TERM_HW
807 {
808 	struct parse_events_term *term;
809 	int err = parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_HARDWARE,
810 					 $1.str, $1.num & 255, false, &@1, NULL);
811 
812 	if (err) {
813 		free($1.str);
814 		PE_ABORT(err);
815 	}
816 	$$ = term;
817 }
818 |
819 PE_TERM '=' name_or_legacy
820 {
821 	struct parse_events_term *term;
822 	int err = parse_events_term__str(&term, (int)$1, NULL, $3, &@1, &@3);
823 
824 	if (err) {
825 		free($3);
826 		PE_ABORT(err);
827 	}
828 	$$ = term;
829 }
830 |
831 PE_TERM '=' PE_TERM_HW
832 {
833 	struct parse_events_term *term;
834 	int err = parse_events_term__str(&term, (int)$1, NULL, $3.str, &@1, &@3);
835 
836 	if (err) {
837 		free($3.str);
838 		PE_ABORT(err);
839 	}
840 	$$ = term;
841 }
842 |
843 PE_TERM '=' PE_TERM
844 {
845 	struct parse_events_term *term;
846 	int err = parse_events_term__term(&term, (int)$1, (int)$3, &@1, &@3);
847 
848 	if (err)
849 		PE_ABORT(err);
850 
851 	$$ = term;
852 }
853 |
854 PE_TERM '=' PE_VALUE
855 {
856 	struct parse_events_term *term;
857 	int err = parse_events_term__num(&term, (int)$1, NULL, $3, false, &@1, &@3);
858 
859 	if (err)
860 		PE_ABORT(err);
861 
862 	$$ = term;
863 }
864 |
865 PE_TERM
866 {
867 	struct parse_events_term *term;
868 	int err = parse_events_term__num(&term, (int)$1, NULL, 1, true, &@1, NULL);
869 
870 	if (err)
871 		PE_ABORT(err);
872 
873 	$$ = term;
874 }
875 
876 sep_dc: ':' |
877 
878 sep_slash_slash_dc: '/' '/' | ':' |
879 
880 %%
881 
882 void parse_events_error(YYLTYPE *loc, void *parse_state,
883 			void *scanner __maybe_unused,
884 			char const *msg __maybe_unused)
885 {
886 	parse_events_evlist_error(parse_state, loc->last_column, "parser error");
887 }
888