%{ #include #include #include #include "umpf.h" static struct tree* tree_malloc(int type); static enum var_type get_var_type(char* var); %} %error-verbose %union { int n; char* str; struct tree* tr; } %token CONST %token NUM %token VAR %token KW_DISCARD %token KW_PIPE KW_MAIL KW_COPY KW_FILTER %token '(' ')' '{' '}' ';' %nonassoc KW_IF %nonassoc KW_ELSE %left ARROW %left EQ NEQ GE LE '<' '>' RE NRE %left '=' %left '.' %left '+' '-' %left '*' '/' %left '|' %left '^' %left '&' %right '!' %left NEG %type input_init %type input %type command %type ass %type ass_right %type ass_right_p %type cif %type arrow %type cond %type rop %type left %type right %type leaves %% input_init: input {input_tree = $$} ; input: /* empty */ { $$ = tree_malloc(ST_EMPTY); } | command input { $$ = tree_malloc(ST_BLOCK); $$->pt.block.head = $1; $$->pt.block.tail = $2; } ; command: ';' { $$ = tree_malloc(ST_EMPTY); } | '{' command input '}' { $$ = tree_malloc(ST_BLOCK); $$->pt.block.head = $2; $$->pt.block.tail = $3; } | '{' '}' { $$ = tree_malloc(ST_EMPTY); } | cif | ass ';' { $$ = $1; } | arrow ';' { $$ = $1; } ; cif: KW_IF cond command KW_ELSE command { $$ = tree_malloc(ST_IF); $$->pt.tif.c = $2; $$->pt.tif.i = $3; $$->pt.tif.e = $5; } | KW_IF cond command { $$ = tree_malloc(ST_IF); $$->pt.tif.c = $2; $$->pt.tif.i = $3; $$->pt.tif.e = tree_malloc(ST_EMPTY); } ; cond: '!' cond { $$ = tree_malloc(ST_COND); $$->pt.cond.left = $2; $$->pt.cond.right = NULL; $$->pt.cond.op = $1; $$->pt.cond.type = OP_BOOL; } | cond '|' cond { $$ = tree_malloc(ST_COND); $$->pt.cond.left = $1; $$->pt.cond.right = $3; $$->pt.cond.op = $2; $$->pt.cond.type = OP_BOOL; } | cond '&' cond { $$ = tree_malloc(ST_COND); $$->pt.cond.left = $1; $$->pt.cond.right = $3; $$->pt.cond.op = $2; $$->pt.cond.type = OP_BOOL; } | cond '^' cond { $$ = tree_malloc(ST_COND); $$->pt.cond.left = $1; $$->pt.cond.right = $3; $$->pt.cond.op = $2; $$->pt.cond.type = OP_BOOL; } | '(' cond ')' { $$ = $2; } | ass_right rop ass_right { $$ = tree_malloc(ST_COND); $$->pt.cond.left = $1; $$->pt.cond.right = $3; $$->pt.cond.op = $2; $$->pt.cond.type = OP_REL; } | ass_right { $$ = tree_malloc(ST_COND); $$->pt.cond.left = $1; $$->pt.cond.type = JUST_BOOL; } ; rop: '>' | '<' | EQ | NEQ | LE | GE | RE | NRE ; ass: VAR '=' ass_right_p { $$ = tree_malloc(ST_ASS); $$->pt.ass.left = tree_malloc(ST_LEAF); $$->pt.ass.left->pt.leaf.type = L_VAR; $$->pt.ass.left->pt.leaf.value = $1; $$->pt.ass.left->pt.leaf.n = find_var($1, get_var_type($1), var_hash); $$->pt.ass.right = $3; } ; leaves: VAR { $$ = tree_malloc(ST_LEAF); $$->pt.leaf.type = L_VAR; $$->pt.leaf.value = $1; $$->pt.leaf.n = find_var($1, get_var_type($1), var_hash); } | CONST { $$ = tree_malloc(ST_LEAF); $$->pt.leaf.type = L_CONST; $$->pt.leaf.value = $1; $$->pt.leaf.n = store_const($1); } ; arrow: left ARROW right ass_right { $$ = tree_malloc(ST_ARROW); $$->pt.arrow.s = $4; $$->pt.arrow.left = $1; $$->pt.arrow.right = $3; } | left ARROW KW_DISCARD { //FIXME: actually left does not make sense here $$ = tree_malloc(ST_ARROW); $$->pt.arrow.s = NULL; $$->pt.arrow.left = K_EMPTY; $$->pt.arrow.right = K_DISCARD; } ; left: /* empty */ { $$ = K_EMPTY;} | KW_COPY { $$ = K_COPY; } ; right: /* empty */ { $$ = K_EMPTY; } | KW_PIPE { $$ = K_PIPE; } | KW_MAIL { $$ = K_MAIL; } | KW_FILTER { $$ = K_FILTER; } ; ass_right_p: '(' ass_right ')' {$$ = $2; } | ass_right {$$ = $1; } ; ass_right: leaves | ass_right '.' ass_right { $$ = tree_malloc(ST_OP); $$->pt.op.op = $2; $$->pt.op.left = $1; $$->pt.op.right = $3; } | ass_right '+' ass_right { $$ = tree_malloc(ST_OP); $$->pt.op.op = $2; $$->pt.op.left = $1; $$->pt.op.right = $3; } | ass_right '-' ass_right { $$ = tree_malloc(ST_OP); $$->pt.op.op = $2; $$->pt.op.left = $1; $$->pt.op.right = $3; } | ass_right '*' ass_right { $$ = tree_malloc(ST_OP); $$->pt.op.op = $2; $$->pt.op.left = $1; $$->pt.op.right = $3; } | ass_right '/' ass_right { $$ = tree_malloc(ST_OP); $$->pt.op.op = $2; $$->pt.op.left = $1; $$->pt.op.right = $3; } | '-' ass_right %prec NEG { $$ = tree_malloc(ST_OP); $$->pt.op.op = $1; $$->pt.op.left = tree_malloc(ST_LEAF); $$->pt.op.left->pt.leaf.type = L_CONST; $$->pt.op.left->pt.leaf.value = "0"; $$->pt.op.left->pt.leaf.n = store_const("0"); $$->pt.op.right = $2; } ; %% struct tree* tree_malloc(int type) { struct tree* temp; temp = xmalloc(sizeof (struct tree)); temp->st=type; return temp; } enum var_type get_var_type(char* var) { int upper = 0; int lower = 0; if (islower(*var)) return VAR_USER; while (*var) { if (isupper(*var)) upper++; if (islower(*var)) lower++; var++; } if (upper && lower) return VAR_HEADER; return VAR_INTERN; } void yyerror (char const *s) { fprintf (stderr, "Line %d: %s\n Saving your e-mail to default mailbox %s\n", line, s, default_mailbox); longjmp(env, 1); }