]> mj.ucw.cz Git - umpf.git/blobdiff - cond.y
print parse tree
[umpf.git] / cond.y
diff --git a/cond.y b/cond.y
index d5b293413053b19b2d8d71ac13fdc8a65025369b..e69668b30b7fc2a94264b545b21c3e4bf1cfe781 100644 (file)
--- a/cond.y
+++ b/cond.y
 #include <string.h>
 #include <pcre.h>
 
+#include "lex.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;
 
 %}
 
 %union {
-       int b;  
        int n;
        char* str;
+       struct tree* tr;        
 }
 
 %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 KW_PIPE KW_MAIL KW_COPY
+%token '(' ')' '{' '}' ';'
+%nonassoc KW_IF
+%nonassoc KW_ELSE
 %left ARROW
-%left EQ NEQ GE LE '<' '>' RE NRE
+%left <n> EQ NEQ GE LE '<' '>' RE NRE
+%left '='
+%left '.'
 %left '+' '-' 
 %left '*' '/'
-%left '|' '&' '^'
-%left '!'
-%left '=' 
-%type <b> boo
+%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> cif
+%type <tr> cond
+%type <n> rop 
 
 %%
-input: /* empty */
-       | input line
+input: /* empty */     { $$ = input_tree = NULL; }
+       | command input {       $$ = tree_malloc(ST_BLOCK); 
+                               $$->pt.block.head = $1;
+                               $$->pt.block.tail = $2;
+
+                               input_tree = $$;
+                       } 
 ;
 
-line:  '\n'
-       | boo '\n'              { printf("%s\n",$1?"true":"false"); }
-       | error '\n'            { yyerrok; }
+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}
+               
+       
 ;
 
-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 }
+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 = $5;
+                               }
+       | KW_IF cond command    { 
+                                       $$ = tree_malloc(ST_IF);
+                                       $$->pt.tif.c = $2;
+                                       $$->pt.tif.i = $3;
+                                       $$->pt.tif.e = NULL;
+                               }
+;
+
+cond:  '!' cond {
+                               $$ = tree_malloc(ST_COND);
+                               $$->pt.cond.left = $2;  
+                               $$->pt.cond.right = NULL;       
+                               $$->pt.cond.op = $1;    
+
+               }
+       | cond '|' cond {
+                               $$ = tree_malloc(ST_COND);
+                               $$->pt.cond.left = $1;  
+                               $$->pt.cond.right = $3; 
+                               $$->pt.cond.op = $2;    
+
+                       }
+       | cond '&' cond {
+                               $$ = tree_malloc(ST_COND);
+                               $$->pt.cond.left = $1;  
+                               $$->pt.cond.right = $3; 
+                               $$->pt.cond.op = $2;    
+
+                       }
+       | cond '^' cond {
+                               $$ = tree_malloc(ST_COND);
+                               $$->pt.cond.left = $1;  
+                               $$->pt.cond.right = $3; 
+                               $$->pt.cond.op = $2;    
+
+                       }
+       | '(' cond ')' { $$ = $2; }
+       | ass_right rop ass_right       {
+                                               $$ = tree_malloc(ST_COND);
+                                               $$->pt.cond.left = $1;  
+                                               $$->pt.cond.right = $3; 
+                                               $$->pt.cond.op = $2;    
+                                       }
 ;
 
+rop:   '>'
+       | '<'
+       | EQ
+       | NEQ
+       | LE
+       | GE
+       | RE
+       | NRE
 ;
+
+ass:
+       VAR '=' ass_right       {
+                                       $$ = 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.right = $3;
+                               }
+;
+
+ass_right:     NUM     { 
+                               $$ = tree_malloc(ST_LEAF);
+                               $$->pt.leaf.type = L_NUM;
+                               $$->pt.leaf.value.n = $1;
+                       }
+               | VAR   {
+                               $$ = tree_malloc(ST_LEAF);
+                               $$->pt.leaf.type = L_VAR;
+                               $$->pt.leaf.value.s = $1;
+                       }
+               | CONST {
+                               $$ = tree_malloc(ST_LEAF);
+                               $$->pt.leaf.type = L_CONST;
+                               $$->pt.leaf.value.s = $1;
+                       }
+
+;
+
 %%
 
-#include <ctype.h>
-#include <stdlib.h>
+struct tree* 
+tree_malloc(int type)
+{
+       struct tree* temp;
+       temp = xmalloc(sizeof (struct tree));
+       temp->st=type;
 
-#define BUFSIZE 4096
+       return temp;
+}
 
 int 
 regex_cmp(char* s, char* r)
@@ -77,206 +238,99 @@ regex_cmp(char* s, char* r)
        const char* error;
        int ovector[OVECCOUNT];
        
-       brum=pcre_compile(r,0,&error,&erroroffset,NULL);
+       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);
-       
+       int res = pcre_exec(brum,NULL,s,strlen(s),0,0,ovector,OVECCOUNT);
        pcre_free(brum);
 
        return res;
 }
 
-char*
-get_string_out(char delim)
+void
+yyerror (char const *s)
 {
-       int last = delim; 
-       int i = 0;
-       char* s;
-       int c;
-
-       if (!(s = malloc(BUFSIZE))){
-               puts("Low memory");
-               exit(0);
-       }
-
-       while ((c = getchar()) != delim || last == '\\'){
-               if (last=='\\' && c != delim)
-                       s[i-1] = c;
-               else {          
-                       s[i] = c;
-                       i++;
-               }
-               last = c;
-               if (i >= BUFSIZE-1)
-                       break;
-       }       
-       s[i] = '\0';
-
-       return s;
+       fprintf (stderr, "%s\n", s);
 }
 
-int
-safe_unget(char c)
+void
+print_ind(int num, char c)
 {
-       if (c==EOF)
-               return 0;
+       int i;
 
-       ungetc(c,stdin);
-       return 1;
+       for (i = 0; i < num; i++){
+               putchar(c);
+       }
 }
 
-int
-yylex(void)
+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 c, last;
-       
-       while ((c = getchar ()) == ' ' || c == '\t');
-       
-       if (c == '"'){
-               last = '"';
-               yylval.str = get_string_out('"');
-               return CONST;   
-       }
-
-       if (c == '\''){
-               last = '\'';
-               yylval.str = get_string_out('\'');
-               return CONST;   
-       }
-
-       if (c == '/'){
-               last = '/';
-               yylval.str = get_string_out('/');       
-               return REGEX;   
-       }
-
-       if (isdigit(c)){
-               ungetc(c,stdin);
-               scanf("%d",&yylval.n);
-               return NUM;
-       }
-
-       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 '<';
-               }
-       }
-
-       if (c == '>'){
-               if ((c = getchar ()) == '=')
-                       return GE;
-               else {
-                       safe_unget(c);
-                       return '>'; 
-               } 
-       }
-
-       if (c == '='){
-               if ((c = getchar ()) == '=')
-                       return EQ;
-               else {
-                       safe_unget(c);
-                       return '='; 
-               }
-       }
-
-       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 '-';
-               }
-       }
-
-       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 VAR;
-       }
-
-       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;
 }
 
-void
-yyerror (char const *s)
-{
-       fprintf (stderr, "%s\n", s);
-}
 
 int
 main(void)
 {
-//     yydebug=1;
-       return yyparse ();
+       yydebug=1;
+       yyparse ();
+
+       print_tree(input_tree,0);
+       return 0;
 }