]> mj.ucw.cz Git - umpf.git/blob - cond.y
add arrow and .
[umpf.git] / cond.y
1 %{
2
3 #include <stdio.h>
4 #include <string.h>
5 #include <pcre.h>
6
7 #include "lex.h"
8
9 #define OVECCOUNT 3
10
11 int yylex (void);
12 void yyerror (char const *);
13
14 int regex_cmp(char* s, char* r);
15 struct tree* tree_malloc(int type);
16 void print_tree(struct tree* t, int ind);
17
18 struct tree {
19         enum {
20                 ST_IF,
21                 ST_COND,
22                 ST_BLOCK,
23                 ST_ASS,
24                 ST_LEAF,
25                 ST_EMPTY,
26                 ST_ARROW,
27                 ST_OP
28         } st;   /* subtree type */
29         union {
30                 struct {
31                         struct tree* c; /* condition */
32                         struct tree* i; /* if */
33                         struct tree* e; /* else */
34                 } tif;
35
36                 struct {
37                         int op;
38                         struct tree* left;
39                         struct tree* right;
40                 } cond; /* binary operator */
41
42                 struct {
43                         struct tree* head;
44                         struct tree* tail;
45                 } block;
46
47                 struct {
48                         struct tree* left;
49                         struct tree* right;
50                 } ass;
51
52                 struct {
53                         enum {
54                                 L_VAR,
55                                 L_CONST,
56                                 L_NUM
57                         } type;
58                         union {
59                                 char* s;
60                                 int n;
61                         } value;
62                 } leaf;
63
64                 struct {
65                         char* kw_left;
66                         char* kw_right; 
67                         struct tree* s;
68                 } arrow;
69
70                 struct {
71                         int op;
72                         struct tree* left;
73                         struct tree* right;
74                 } op;
75
76         } pt;
77 };
78
79 struct tree* input_tree;
80
81 %}
82
83 %error-verbose
84
85 %union {
86         int n;
87         char* str;
88         struct tree* tr;        
89 }
90
91 %token <str> CONST
92 %token <n> NUM
93 %token <str> VAR
94 %token <str> KW_PIPE KW_MAIL KW_COPY
95 %token '(' ')' '{' '}' ';'
96 %nonassoc KW_IF
97 %nonassoc KW_ELSE
98 %left ARROW
99 %left <n> EQ NEQ GE LE '<' '>' RE NRE
100 %left '='
101 %left '.'
102 %left '+' '-' 
103 %left '*' '/'
104 %left <n> '|'
105 %left <n> '^'
106 %left <n> '&'
107 %left <n> '!'
108 %type <tr> input 
109 %type <tr> command 
110 %type <tr> next 
111 %type <tr> ass 
112 %type <tr> ass_right 
113 %type <tr> cif
114 %type <tr> arrow 
115 %type <tr> cond
116 %type <n> rop 
117 %type <str> left
118 %type <str> right 
119 %type <tr> leaves 
120
121 %%
122 input:  /* empty */     { $$ = input_tree = NULL; }
123         | command input {       $$ = tree_malloc(ST_BLOCK); 
124                                 $$->pt.block.head = $1;
125                                 $$->pt.block.tail = $2;
126
127                                 input_tree = $$;
128                         } 
129 ;
130
131 command:         ';' { $$ = tree_malloc(ST_EMPTY); }
132                 | '{' command next '}'  {
133                                                 $$ = tree_malloc(ST_BLOCK); 
134                                                 $$->pt.block.head = $2;
135                                                 $$->pt.block.tail = $3; 
136                                         }
137                 | '{' '}' { $$ = tree_malloc(ST_EMPTY); }
138                 | cif
139                 | ass ';' { $$ = $1}
140                 | arrow ';' { $$ = $1}
141                 
142         
143 ;
144
145 next:   /* empty */ {$$ = NULL}
146         | command
147         
148
149 ;
150
151 cif:    KW_IF cond command KW_ELSE command      { 
152                                         $$ = tree_malloc(ST_IF);
153                                         $$->pt.tif.c = $2;
154                                         $$->pt.tif.i = $3;
155                                         $$->pt.tif.e = $5;
156                                 }
157         | KW_IF cond command    { 
158                                         $$ = tree_malloc(ST_IF);
159                                         $$->pt.tif.c = $2;
160                                         $$->pt.tif.i = $3;
161                                         $$->pt.tif.e = NULL;
162                                 }
163 ;
164
165 cond:   '!' cond {
166                                 $$ = tree_malloc(ST_COND);
167                                 $$->pt.cond.left = $2;  
168                                 $$->pt.cond.right = NULL;       
169                                 $$->pt.cond.op = $1;    
170
171                 }
172         | cond '|' cond {
173                                 $$ = tree_malloc(ST_COND);
174                                 $$->pt.cond.left = $1;  
175                                 $$->pt.cond.right = $3; 
176                                 $$->pt.cond.op = $2;    
177
178                         }
179         | cond '&' cond {
180                                 $$ = tree_malloc(ST_COND);
181                                 $$->pt.cond.left = $1;  
182                                 $$->pt.cond.right = $3; 
183                                 $$->pt.cond.op = $2;    
184
185                         }
186         | cond '^' cond {
187                                 $$ = tree_malloc(ST_COND);
188                                 $$->pt.cond.left = $1;  
189                                 $$->pt.cond.right = $3; 
190                                 $$->pt.cond.op = $2;    
191
192                         }
193         | '(' cond ')' { $$ = $2; }
194         | ass_right rop ass_right       {
195                                                 $$ = tree_malloc(ST_COND);
196                                                 $$->pt.cond.left = $1;  
197                                                 $$->pt.cond.right = $3; 
198                                                 $$->pt.cond.op = $2;    
199                                         }
200 ;
201
202 rop:    '>'
203         | '<'
204         | EQ
205         | NEQ
206         | LE
207         | GE
208         | RE
209         | NRE
210 ;
211
212 ass:
213         VAR '=' ass_right       {
214                                         $$ = tree_malloc(ST_ASS);
215
216                                         $$->pt.ass.left = tree_malloc(ST_LEAF);
217                                         $$->pt.ass.left->pt.leaf.type = L_VAR;
218                                         $$->pt.ass.left->pt.leaf.value.s = $1;
219
220                                         $$->pt.ass.right = $3;
221                                 }
222 ;
223
224 leaves:         NUM     { 
225                                 $$ = tree_malloc(ST_LEAF);
226                                 $$->pt.leaf.type = L_NUM;
227                                 $$->pt.leaf.value.n = $1;
228                         }
229                 | VAR   {
230                                 $$ = tree_malloc(ST_LEAF);
231                                 $$->pt.leaf.type = L_VAR;
232                                 $$->pt.leaf.value.s = $1;
233                         }
234                 | CONST { 
235                                 $$ = tree_malloc(ST_LEAF);
236                                 $$->pt.leaf.type = L_CONST;
237                                 $$->pt.leaf.value.s = $1;
238                         }
239 ;
240
241 arrow:  left ARROW right ass_right  {
242                                         $$ = tree_malloc(ST_ARROW);
243                                         $$->pt.arrow.s = $4;
244                                         $$->pt.arrow.kw_left = $1;
245                                         $$->pt.arrow.kw_right = $3;
246                                 }
247 ;
248
249 left:   /* empty */ {$$=NULL}
250         | KW_COPY { $$ = "copy" }
251
252 ;
253
254 right:  /* empty */ {$$ = NULL}
255         | KW_PIPE { $$ = "pipe" }
256         | KW_MAIL { $$ = "mail" }
257 ;
258
259 ass_right:      leaves
260                 | ass_right '.' ass_right       {
261                                         $$ = tree_malloc(ST_OP);
262                                         $$->pt.op.op = '.';
263                                         $$->pt.op.left = $1;    
264                                         $$->pt.op.right = $3;   
265                                 }
266 ;
267
268 %%
269
270 struct tree* 
271 tree_malloc(int type)
272 {
273         struct tree* temp;
274         temp = xmalloc(sizeof (struct tree));
275         temp->st=type;
276
277         return temp;
278 }
279
280 int 
281 regex_cmp(char* s, char* r)
282 {
283         pcre *brum;
284         int erroroffset;
285         const char* error;
286         int ovector[OVECCOUNT];
287         
288         brum = pcre_compile(r,0,&error,&erroroffset,NULL);
289         if (!brum)
290                 return -1;
291         
292         int res = pcre_exec(brum,NULL,s,strlen(s),0,0,ovector,OVECCOUNT);
293         pcre_free(brum);
294
295         return res;
296 }
297
298 void
299 yyerror (char const *s)
300 {
301         fprintf (stderr, "Line %d: %s\n", line, s);
302 }
303
304 void
305 print_ind(int num, char c)
306 {
307         int i;
308
309         for (i = 0; i < num; i++){
310                 putchar(c);
311         }
312 }
313
314 void
315 print_tree(struct tree* t, int ind)
316 {
317         if (!t)
318                 return; 
319
320         switch (t->st){
321                 case ST_IF:
322                         print_ind(ind,' ');
323                         puts("if");
324                         print_tree(t->pt.tif.c,ind+1);
325                         print_ind(ind,' ');
326                         puts("then");
327                         print_tree(t->pt.tif.i,ind+1);
328                         print_ind(ind,' ');
329                         puts("else");
330                         print_tree(t->pt.tif.e,ind+1);
331                         break;
332                 case ST_COND:
333 #define UPPER(a) ((a) >> 8)
334 #define LOWER(a) ((a) & 0xFF)
335                         print_tree(t->pt.cond.left, ind+1);
336                         print_ind(ind,' ');
337
338                         if (UPPER(t->pt.cond.op) > 0)
339                                 putchar(UPPER(t->pt.cond.op));
340                         putchar(LOWER(t->pt.cond.op));
341                         putchar('\n'); 
342                         print_tree(t->pt.cond.right, ind+1);    
343                         break;
344                 case ST_BLOCK:
345                         print_tree(t->pt.block.head,ind);
346                         print_tree(t->pt.block.tail,ind);
347                         break;
348                 case ST_ASS:
349                         print_tree(t->pt.ass.left, ind+1);
350                         print_ind(ind,' ');     
351                         puts("=");
352                         print_tree(t->pt.ass.right, ind+1);
353                         break;
354                 case ST_LEAF:
355                         print_ind(ind, ' ');
356                         switch (t->pt.leaf.type){
357                                 case L_VAR:
358                                         putchar('$');
359                                 case L_CONST:
360                                         puts(t->pt.leaf.value.s);
361                                         break;
362                                 case L_NUM:
363                                         printf("%d\n",t->pt.leaf.value.n);
364                                         break;
365                         }
366                         break;
367                 case ST_ARROW:
368                         if (t->pt.arrow.kw_left){
369                                 print_ind(ind+1, ' ');
370                                 puts(t->pt.arrow.kw_left);
371                         }
372                         print_ind(ind, ' ');
373                         printf("->\n");
374                         if (t->pt.arrow.kw_right){
375                                 print_ind(ind+1, ' ');
376                                 puts(t->pt.arrow.kw_right);
377                         }
378                         print_tree(t->pt.arrow.s,ind+1);
379                         break;
380                 case ST_OP:
381                         print_tree(t->pt.op.left, ind+1);
382                         print_ind(ind,' ');     
383                         putchar(t->pt.op.op);
384                         putchar('\n');
385                         print_tree(t->pt.op.right, ind+1);
386                         break;  
387                 case ST_EMPTY:
388                         break;  
389
390
391         }
392 }
393
394
395 int
396 main(void)
397 {
398 //      yydebug=1;
399         yyparse ();
400
401         print_tree(input_tree,0);
402         return 0;
403 }