#include <stdio.h>
#include <string.h>
-#include <pcre.h>
+#include <ctype.h>
-#include "lex.h"
+#include "umpf.h"
-#define OVECCOUNT 3
-
-int yylex (void);
-void yyerror (char const *);
-
-int regex_cmp(char* s, char* r);
-struct tree* tree_malloc(int type);
-void print_tree(struct tree* t, int ind);
-
-struct tree {
- enum {
- ST_IF,
- ST_COND,
- ST_BLOCK,
- ST_ASS,
- ST_LEAF,
- ST_EMPTY
- } st; /* subtree type */
- union {
- struct {
- struct tree* c; /* condition */
- struct tree* i; /* if */
- struct tree* e; /* else */
- } tif;
-
- struct {
- int op;
- struct tree* left;
- struct tree* right;
- } cond; /* binary operator */
-
- struct {
- struct tree* head;
- struct tree* tail;
- } block;
-
- struct {
- struct tree* left;
- struct tree* right;
- } ass;
-
- struct {
- enum {
- L_VAR,
- L_CONST,
- L_NUM
- } type;
- union {
- char* s;
- int n;
- } value;
- } leaf;
-
- } pt;
-};
-
-struct tree* input_tree;
+static struct tree* tree_malloc(int type);
+static enum var_type get_var_type(char* var);
%}
+%error-verbose
%union {
int n;
%token <str> CONST
%token <n> NUM
%token <str> VAR
-%token KW_PIPE KW_MAIL KW_COPY
+%token <n> KW_DISCARD
+%token <n> KW_PIPE KW_MAIL KW_COPY KW_FILTER
%token '(' ')' '{' '}' ';'
%nonassoc KW_IF
%nonassoc KW_ELSE
%left ARROW
%left <n> EQ NEQ GE LE '<' '>' RE NRE
-%left '='
-%left '.'
-%left '+' '-'
-%left '*' '/'
+%left <n> '='
+%left <n> '.'
+%left <n> '+' '-'
+%left <n> '*' '/'
%left <n> '|'
%left <n> '^'
%left <n> '&'
-%left <n> '!'
+%right <n> '!'
+%left <n> NEG
+%type <tr> input_init
%type <tr> input
%type <tr> command
-%type <tr> next
%type <tr> ass
%type <tr> ass_right
+%type <tr> ass_right_p
%type <tr> cif
+%type <tr> arrow
%type <tr> cond
%type <n> rop
+%type <n> left
+%type <n> right
+%type <tr> leaves
%%
-input: /* empty */ { $$ = input_tree = NULL; }
+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;
-
- input_tree = $$;
}
;
command: ';' { $$ = tree_malloc(ST_EMPTY); }
- | '{' command next '}' {
+ | '{' command input '}' {
$$ = tree_malloc(ST_BLOCK);
$$->pt.block.head = $2;
$$->pt.block.tail = $3;
}
| '{' '}' { $$ = tree_malloc(ST_EMPTY); }
| cif
- | ass ';' { $$ = $1}
+ | ass ';' { $$ = $1; }
+ | arrow ';' { $$ = $1; }
-;
-
-next: /* empty */ {$$ = NULL}
- | command
-
-
;
cif: KW_IF cond command KW_ELSE command {
$$ = tree_malloc(ST_IF);
$$->pt.tif.c = $2;
$$->pt.tif.i = $3;
- $$->pt.tif.e = NULL;
+ $$->pt.tif.e = tree_malloc(ST_EMPTY);
}
;
cond: '!' cond {
$$ = tree_malloc(ST_COND);
$$->pt.cond.left = $2;
- $$->pt.cond.right = NULL;
+ $$->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; }
$$->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: '>'
;
ass:
- VAR '=' ass_right {
+ 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.s = $1;
-
+ $$->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;
}
;
-ass_right: NUM {
- $$ = tree_malloc(ST_LEAF);
- $$->pt.leaf.type = L_NUM;
- $$->pt.leaf.value.n = $1;
- }
- | VAR {
+leaves: VAR {
$$ = tree_malloc(ST_LEAF);
$$->pt.leaf.type = L_VAR;
- $$->pt.leaf.value.s = $1;
+ $$->pt.leaf.value = $1;
+ $$->pt.leaf.n = find_var($1, get_var_type($1), var_hash);
}
- | CONST {
+ | CONST {
$$ = tree_malloc(ST_LEAF);
$$->pt.leaf.type = L_CONST;
- $$->pt.leaf.value.s = $1;
+ $$->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;
+ }
;
%%
return temp;
}
-int
-regex_cmp(char* s, char* r)
+enum var_type
+get_var_type(char* var)
{
- pcre *brum;
- int erroroffset;
- const char* error;
- int ovector[OVECCOUNT];
-
- brum = pcre_compile(r,0,&error,&erroroffset,NULL);
- if (!brum)
- return -1;
-
- int res = pcre_exec(brum,NULL,s,strlen(s),0,0,ovector,OVECCOUNT);
- pcre_free(brum);
+ 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 res;
+ return VAR_INTERN;
}
void
yyerror (char const *s)
{
- fprintf (stderr, "%s\n", s);
-}
-
-void
-print_ind(int num, char c)
-{
- int i;
-
- for (i = 0; i < num; i++){
- putchar(c);
- }
-}
-
-void
-print_tree(struct tree* t, int ind)
-{
- if (!t)
- return;
-
- switch (t->st){
- case ST_IF:
- print_ind(ind,' ');
- puts("if");
- print_tree(t->pt.tif.c,ind+1);
- print_ind(ind,' ');
- puts("then");
- print_tree(t->pt.tif.i,ind+1);
- print_ind(ind,' ');
- puts("else");
- print_tree(t->pt.tif.e,ind+1);
- break;
- case ST_COND:
-#define UPPER(a) ((a) >> 8)
-#define LOWER(a) ((a) & 0xFF)
- print_tree(t->pt.cond.left, ind+1);
- print_ind(ind,' ');
-
- if (UPPER(t->pt.cond.op) > 0)
- putchar(UPPER(t->pt.cond.op));
- putchar(LOWER(t->pt.cond.op));
- putchar('\n');
- print_tree(t->pt.cond.right, ind+1);
- break;
- case ST_BLOCK:
- print_tree(t->pt.block.head,ind);
- print_tree(t->pt.block.tail,ind);
- break;
- case ST_ASS:
- print_tree(t->pt.ass.left, ind+1);
- print_ind(ind,' ');
- puts("=");
- print_tree(t->pt.ass.right, ind+1);
- break;
- case ST_LEAF:
- print_ind(ind, ' ');
- switch (t->pt.leaf.type){
- case L_VAR:
- putchar('$');
- case L_CONST:
- puts(t->pt.leaf.value.s);
- break;
- case L_NUM:
- printf("%d\n",t->pt.leaf.value.n);
- break;
- }
- break;
- case ST_EMPTY:
- break;
-
-
- }
-}
-
-
-int
-main(void)
-{
- yydebug=1;
- yyparse ();
-
- print_tree(input_tree,0);
- return 0;
+ fprintf (stderr, "Line %d: %s\n Saving your e-mail to default mailbox %s\n",
+ line, s, default_mailbox);
+ longjmp(env, 1);
}