#include <stdio.h>
#include <string.h>
-#include <pcre.h>
-
-#define OVECCOUNT 3
+#include <ctype.h>
-int yylex (void);
-void yyerror (char const *);
+#include "umpf.h"
-int regex_cmp(char* s, char* r);
+static struct tree* tree_malloc(int type);
+static enum var_type get_var_type(char* var);
%}
+%error-verbose
%union {
- int b;
int n;
char* str;
+ struct tree* tr;
}
+%right <n> '!'
%token <str> CONST
-%token <str> REGEX
-%token ERR
%token <n> NUM
%token <str> VAR
-%token KW_IF KW_ELSE KW_PIPE KW_MAIL KW_COPY
-%token '(' ')' '{' '}'
+%token <n> KW_DISCARD
+%token <n> 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 '='
-%type <b> boo
+%left <n> EQ NEQ GE LE '<' '>' RE NRE
+%left <n> '='
+%left <n> '.'
+%left <n> '+' '-'
+%left <n> '*' '/'
+%left <n> '|'
+%left <n> '^'
+%left <n> '&'
+%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 line
-;
-
-line: '\n'
- | boo '\n' { printf("%s\n",$1?"true":"false"); }
- | error '\n' { yyerrok; }
-;
+input: /* empty */ { $$ = input_tree = tree_malloc(ST_EMPTY); }
+ | command input { $$ = tree_malloc(ST_BLOCK);
+ $$->pt.block.head = $1;
+ $$->pt.block.tail = $2;
-boo: CONST EQ CONST { $$ = ! strcmp($1, $3); }
- | CONST NEQ CONST { $$ = !! strcmp($1, $3); }
- | CONST RE REGEX { $$ = regex_cmp($1,$3) >= 0 }
- | CONST NRE REGEX { $$ = regex_cmp($1,$3) < 0 }
- | NUM EQ NUM { $$ = $1 == $3 }
- | NUM NEQ NUM { $$ = $1 != $3 }
- | NUM GE NUM { $$ = $1 >= $3 }
- | NUM LE NUM { $$ = $1 <= $3 }
- | NUM '>' NUM { $$ = $1 > $3 }
- | NUM '<' NUM { $$ = $1 < $3 }
- | boo '|' boo { $$ = $1 || $3 }
- | boo '&' boo { $$ = $1 && $3 }
- | boo '^' boo { $$ = ($1 || $3) && !($1 && $3) }
- | '!' boo { $$ = ! $2 }
+ input_tree = $$;
+ }
;
+command: ';' { $$ = tree_malloc(ST_EMPTY); }
+ | '{' command next '}' {
+ $$ = tree_malloc(ST_BLOCK);
+ $$->pt.block.head = $2;
+ $$->pt.block.tail = $3;
+ }
+ | '{' '}' { $$ = tree_malloc(ST_EMPTY); }
+ | cif
+ | ass ';' { $$ = $1; }
+ | arrow ';' { $$ = $1; }
+
+
;
-%%
-
-#include <ctype.h>
-#include <stdlib.h>
-#define BUFSIZE 4096
-
-int
-regex_cmp(char* s, char* r)
-{
- 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);
+next: /* empty */ {$$ = tree_malloc(ST_EMPTY); }
+ | command
- pcre_free(brum);
- return res;
-}
+;
-char*
-get_string_out(char delim)
-{
- int last = delim;
- int i = 0;
- char* s;
- int c;
-
- if (!(s = malloc(BUFSIZE))){
- puts("Low memory");
- exit(0);
- }
+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);
+ }
+;
- while ((c = getchar()) != delim || last == '\\'){
- if (last=='\\' && c != delim)
- s[i-1] = c;
- else {
- s[i] = c;
- i++;
+cond: '!' cond {
+ $$ = tree_malloc(ST_COND);
+ $$->pt.cond.left = $2;
+ $$->pt.cond.right = NULL;
+ $$->pt.cond.op = $1;
+ $$->pt.cond.type = OP_BOOL;
}
- last = c;
- if (i >= BUFSIZE-1)
- break;
- }
- s[i] = '\0';
-
- return s;
-}
+ | 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;
+ }
+;
-int
-safe_unget(char c)
-{
- if (c==EOF)
- return 0;
+rop: '>'
+ | '<'
+ | EQ
+ | NEQ
+ | LE
+ | GE
+ | RE
+ | NRE
+;
- ungetc(c,stdin);
- return 1;
-}
+ass:
+ VAR '=' ass_right_p {
+ $$ = tree_malloc(ST_ASS);
-int
-yylex(void)
-{
-
- int c, last;
-
- while ((c = getchar ()) == ' ' || c == '\t');
-
- if (c == '"'){
- last = '"';
- yylval.str = get_string_out('"');
- return CONST;
- }
+ $$->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;
+ }
+;
- if (c == '\''){
- last = '\'';
- yylval.str = get_string_out('\'');
- return CONST;
- }
+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);
+ }
+;
- if (c == '/'){
- last = '/';
- yylval.str = get_string_out('/');
- return REGEX;
- }
+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;
+ }
+;
- if (isdigit(c)){
- ungetc(c,stdin);
- scanf("%d",&yylval.n);
- return NUM;
- }
+left: /* empty */ { $$ = K_EMPTY;}
+ | KW_COPY { $$ = K_COPY; }
- if (c == '!'){
- if ((c = getchar ()) == '=')
- return NEQ;
- else if (c == '~')
- return NRE;
- else {
- safe_unget(c);
- return '!';
- }
- }
+;
- if (c == '<'){
- if ((c = getchar ()) == '=')
- return LE;
- else {
- safe_unget(c);
- return '<';
- }
- }
+right: /* empty */ { $$ = K_EMPTY; }
+ | KW_PIPE { $$ = K_PIPE; }
+ | KW_MAIL { $$ = K_MAIL; }
+ | KW_FILTER { $$ = K_FILTER; }
+;
- if (c == '>'){
- if ((c = getchar ()) == '=')
- return GE;
- else {
- safe_unget(c);
- return '>';
- }
- }
+ass_right_p: '(' ass_right ')' {$$ = $2; }
+ | ass_right {$$ = $1; }
+;
- if (c == '='){
- if ((c = getchar ()) == '=')
- return EQ;
- else {
- safe_unget(c);
- return '=';
- }
- }
+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;
+ }
+;
- if (c == '~'){
- if ((c = getchar ()) == '~')
- return RE;
- else {
- safe_unget(c);
- return ERR;
- }
- }
+%%
- if (c == '-'){
- if ((c = getchar ()) == '>')
- return ARROW;
- else {
- safe_unget(c);
- return '-';
- }
- }
+struct tree*
+tree_malloc(int type)
+{
+ struct tree* temp;
+ temp = xmalloc(sizeof (struct tree));
+ temp->st=type;
- if (c == '$'){
- int i=0;
-
- if (!(yylval.str=malloc(BUFSIZE))){
- puts("Low memory");
- exit (0);
- }
-
- while (isalnum(c = getchar()) || c == '_' || c == '-'){
- yylval.str[i]=c;
- i++;
- if (i >= BUFSIZE)
- break;
- }
+ return temp;
+}
- return VAR;
+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;
- if (c == '\n' || c == '+' || c == '*' || c == '/' ||
- c == '(' || c == ')' || c == '{' || c == '}')
- return c;
-
-#define KLEN 10
-
- if (isalpha(c)){
- char buf[KLEN];
- int i=0;
-
- ungetc(c,stdin);
- while (isalpha(c = getchar()) && i<KLEN-1)
- buf[i++]=c;
- buf[i]=0;
-
- if (!strcmp(buf,"if"))
- return KW_IF;
- else if (!strcmp(buf,"else"))
- return KW_ELSE;
- else if (!strcmp(buf,"pipe"))
- return KW_COPY;
- else if (!strcmp(buf,"mail"))
- return KW_MAIL;
- else if (!strcmp(buf,"copy"))
- return KW_COPY;
- else
- return ERR;
- }
-
- if (c == EOF)
- return 0;
-
- return ERR;
+ return VAR_INTERN;
}
void
yyerror (char const *s)
{
- fprintf (stderr, "%s\n", s);
-}
-
-int
-main(void)
-{
-// yydebug=1;
- return yyparse ();
+ fprintf (stderr, "Line %d: %s\n Saving your e-mail to default mailbox %s\n",
+ line, s, default_mailbox);
+ longjmp(env, 1);
}