%{ #include #include #include ; enum op { String, Query, Star, Plus, Or, And, Class, Dot, Exc } ; typedef union Node Node; struct String { enum op type; char *string; }; struct Query { enum op type; Node *children[1]; }; struct Star { enum op type; Node *children[1]; }; struct Plus { enum op type; Node *children[1]; }; struct Or { enum op type; Node *children[2]; }; struct And { enum op type; Node *children[2]; }; struct Class { enum op type; char *stringValue; int len; }; struct Dot { enum op type;}; struct Exc { enum op type; Node *children[1]; }; union Node { enum op type; struct String String; struct Query Query; struct Star Star; struct Plus Plus; struct Or Or; struct And And; struct Class Class; struct Dot Dot; struct Exc Exc; }; Node *mkString(char *s) { Node *node= calloc(1, sizeof(struct String)); node->type= String; node->String.string= strdup(s); return node; } Node *mkQuery(Node *n) { Node *node= calloc(1, sizeof(struct Query)); node->type= Query; node->Query.children[0]= n; return node; } Node *mkOr(Node *node1, Node *node2) { Node *node= calloc(1, sizeof(struct Or)); node->Or.children[0]= node1; node->Or.children[1]= node2; return node; } Node *mkAnd(Node *node1, Node *node2) { Node *node= calloc(1, sizeof(struct And)); node->And.children[0]= node1; node->And.children[1]= node2; return node; } Node *mkStar(Node *n) { Node *node= calloc(1, sizeof(struct Star)); node->type= Star; node->Star.children[0]= n; return node; } Node *mkClass(char* str) { Node *node= calloc(1, sizeof(struct Class)); node->Class.stringValue= str; node->Class.len=strlen(str); return node; } Node *mkPlus(Node *n) { Node *node= calloc(1, sizeof(struct Plus)); node->type= Plus; node->Plus.children[0]= n; return node; } Node *mkDot() { Node *node= calloc(1, sizeof(struct Dot)); node->type= Dot; return node; } Node *mkExc(Node *n) { Node *node= calloc(1, sizeof(struct Exc)); node->type= Exc; node->Exc.children[0]= n; return node; } void print(Node *node) { switch (node->type) { case String: printf("\"%s\"", node->String.string); return; case Query: print(node->Query.children[0]); printf("?"); return; case Star: print(node->Query.children[0]); printf("*"); return; case Plus: print(node->Query.children[0]); printf("+"); return; case Or: print(node->Or.children[0]); print(node->Or.children[1]); printf("Or"); return; case And: print(node->And.children[0]); print(node->And.children[1]); printf("And"); return; case Class: printf("Class"); printf("\"%s\"", node->Class.stringValue); return; case Dot: printf("Dot"); return; case Exc: printf("!"); print(node->Exc.children[0]); return; } abort(); } void println(Node *node) { print(node); printf("\n"); } #define YYSTYPE Node * YYSTYPE yylval = 0; %} start = - o:or { yylval = o } or = a:and "|" - o:or { $$ = mkOr(o, a) } | a:and { $$ = a } and = p:prefix a:and { $$ = mkAnd(p, a) } | p:prefix { $$ = p } prefix = "!"- p : postfix {$$ = mkExc(p)} | p: postfix {$$ = p} postfix = s:atom ( "?" - { s = mkQuery(s) } | "*" - { s = mkStar(s) } | "+" - { s = mkPlus(s) } )? { $$ = s} atom = string | class | dot string = '"' < [^"]* > '"' { $$ = mkString(yytext) } - class = '[' <[]*> ']' { $$=mkClass(yytext) } - dot = '.' {$$=mkDot()} - - = space* space = [ \t] | '\n' '\r'* | '\r' '\n'* %% int main(int argc, char **argv) { while (yyparse()) { println(yylval); } return 0; (void)yySet; (void)yyPop; (void)yyPush; (void)yyAccept; (void)yymatchDot; (void)yymatchString; (void)yymatchChar; }