%{ #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <string.h> #include "m_ematch.h" %} %locations %token-table %error-verbose %name-prefix "ematch_" %union { unsigned int i; struct bstr *b; struct ematch *e; } %{ extern int ematch_lex(void); extern void yyerror(const char *s); extern struct ematch *ematch_root; extern char *ematch_err; %} %token <i> ERROR %token <b> ATTRIBUTE %token <i> AND OR NOT %type <i> invert relation %type <e> match expr %type <b> args %right AND OR %start input %% input: /* empty */ | expr { ematch_root = $1; } | expr error { ematch_root = $1; YYACCEPT; } ; expr: match { $$ = $1; } | match relation expr { $1->relation = $2; $1->next = $3; $$ = $1; } ; match: invert ATTRIBUTE '(' args ')' { $2->next = $4; $$ = new_ematch($2, $1); if ($$ == NULL) YYABORT; } | invert '(' expr ')' { $$ = new_ematch(NULL, $1); if ($$ == NULL) YYABORT; $$->child = $3; } ; args: ATTRIBUTE { $$ = $1; } | ATTRIBUTE args { $1->next = $2; } ; relation: AND { $$ = TCF_EM_REL_AND; } | OR { $$ = TCF_EM_REL_OR; } ; invert: /* empty */ { $$ = 0; } | NOT { $$ = 1; } ; %% void yyerror(const char *s) { ematch_err = strdup(s); }