%{ #include #include #include ; enum op { String, Query, Star, Plus, Or, And } ; 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; }; 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; }; 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; } 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; } 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:postfix a:and { $$ = mkAnd(p, a) } | p:postfix { $$ = p } postfix = s:atom ( "?" - { s = mkQuery(s) } | "*" - { s = mkStar(s) } | "+" - { s = mkPlus(s) } )? { $$ = s} atom = string | class string = '"' < [^"]* > '"' { $$ = mkString(yytext) } - class = '[' <[]*> ']' { $$=mkClass(yytext) } - - = 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; }