small fixes for my last commit (async events)
[dyninst.git] / dyner / src / cmdline.y
1 %{
2 #if defined(i386_unknown_nt4_0)
3 #include <malloc.h>
4 #include <string.h>
5 #endif
6
7 #include "BPatch_thread.h"
8 #include "BPatch_image.h"
9 #include "BPatch_type.h"
10 #include "BPatch_snippet.h"
11 #include "breakpoint.h"
12
13 extern "C" {
14 void yyerror(char *s);
15 int yyparse(void);
16 }
17
18 extern BPatch_thread *appThread;
19 extern BPatch_image *appImage;
20
21 int yylex();
22
23 BPatch_snippet *parse_result;
24 parse_ret parse_type;
25
26 %}
27
28 %union {
29     int                                 ival;
30     char                                *sval;
31     BPatch_snippet                      *snippet;
32     BPatch_boolExpr                     *boolExpr;
33     BPatch_Vector<BPatch_snippet *>     *snippetList;
34     BPatch_funcCallExpr                 *funcCall;
35 };
36
37
38 %token <sval> IDENTIFIER STRING
39 %token <ival> NUMBER
40 %token _ERROR IF ELSE
41 %token PLUSPLUS MINUSMINUS
42
43 %left DOT DOLLAR
44 %left OR
45 %left AND
46 %left EQ NOT_EQ LESS_EQ GREATER_EQ
47 %left '+' '-'
48 %left '*' '/'
49 %left COMMA
50 %left ASSIGN
51 %left SEMI
52 %left START_BLOCK END_BLOCK
53
54 %type <boolExpr> bool_expression 
55 %type <snippet> arith_expression variable_expr statement inc_decr_expr
56 %type <snippet> param block
57 %type <snippetList> param_list statement_list
58 %type <funcCall> func_call
59
60
61 %%
62
63 start:
64     '(' bool_expression ')' 
65     {
66         parse_result = (BPatch_snippet *) $2;
67         parse_type = parsed_bool;
68     }
69     |
70     statement_list
71     { 
72         parse_result = new BPatch_sequence(*$1); 
73         parse_type = parsed_statement; 
74         delete $1;
75     }
76     ; 
77
78 statement_list: 
79     statement
80     { 
81         $$ = new BPatch_Vector<BPatch_snippet *>; 
82         $$->push_back($1);
83     }
84     | statement_list statement
85     {
86         $1->push_back($2);
87         $$ = $1;
88     }
89     ;
90
91 statement:
92     arith_expression SEMI
93     { 
94         $$ = $1; 
95     }
96     | IF '(' bool_expression ')' block 
97     {
98         $$ = new BPatch_ifExpr(*$3, *$5);
99         delete $3;
100         delete $5;
101     }
102     | IF '(' bool_expression ')' block ELSE block 
103     {
104         $$ = new BPatch_ifExpr(*$3, *$5, *$7);
105         delete $3;
106         delete $5;
107         delete $7;
108     }
109 ;
110
111 block: statement
112      | START_BLOCK statement_list END_BLOCK
113      {
114         $$ = new BPatch_sequence(*$2);
115         delete $2;
116      }
117 ;
118
119 func_call: IDENTIFIER '(' param_list ')'
120     { 
121       BPatch_Vector<BPatch_function *>bpfv;
122       if (NULL == appImage->findFunction($1, bpfv) || !bpfv.size()) {
123         printf("unable to find function %s\n", $1);
124         free($1);
125         return 1;
126       }
127       if (bpfv.size() > 1) {
128         printf("found %d references to  %s\n", bpfv.size(), $1);
129       }
130
131       BPatch_function *func = bpfv[0];
132         
133       if (!func) {
134         printf("unable to find function %s\n", $1);
135         free($1);
136         return 1;
137       }
138       
139       free($1);
140       $$ = new BPatch_funcCallExpr(*func, *$3); 
141     }
142     ;
143
144 param_list: 
145     {
146         //No parameters, return an empty vector
147         $$ = new BPatch_Vector<BPatch_snippet *>;
148     }
149     | param 
150     { 
151         $$ = new BPatch_Vector<BPatch_snippet *>; 
152         $$->push_back($1);
153     }
154     | param_list COMMA param
155     { 
156         $1->push_back($3); 
157         $$ = $1;
158     }
159     ;
160
161 param: arith_expression
162     |  STRING
163     { 
164         $$ = new BPatch_constExpr($1); 
165     }
166     ;
167     
168
169 bool_expression: arith_expression '<' arith_expression {
170         $$ = new BPatch_boolExpr(BPatch_lt, *$1, *$3);
171         delete $1;
172         delete $3;
173     }
174     |            arith_expression '>' arith_expression {
175         $$ = new BPatch_boolExpr(BPatch_gt, *$1, *$3);
176         delete $1;
177         delete $3;
178     }
179     |            arith_expression EQ arith_expression {
180         $$ = new BPatch_boolExpr(BPatch_eq, *$1, *$3);
181         delete $1;
182         delete $3;
183     }
184     |            arith_expression LESS_EQ arith_expression {
185         $$ = new BPatch_boolExpr(BPatch_le, *$1, *$3);
186         delete $1;
187         delete $3;
188     }
189     |            arith_expression GREATER_EQ arith_expression {
190         $$ = new BPatch_boolExpr(BPatch_ge, *$1, *$3);
191         delete $1;
192         delete $3;
193     }
194     |            arith_expression NOT_EQ arith_expression {
195         $$ = new BPatch_boolExpr(BPatch_ne, *$1, *$3);
196         delete $1;
197         delete $3;
198     }
199     |            bool_expression AND bool_expression  {
200         $$ = new BPatch_boolExpr(BPatch_and, *$1, *$3);
201         delete $1;
202         delete $3;
203     }
204     |            bool_expression OR bool_expression  {
205         $$ = new BPatch_boolExpr(BPatch_or, *$1, *$3);
206         delete $1;
207         delete $3;
208     }
209     ;
210
211 variable_expr:
212     IDENTIFIER {
213         BPatch_variableExpr *var = findVariable($1);
214         if (var == NULL) {
215             fprintf(stderr, "Cannot find variable: %s\n", $1);
216             free($1);
217             return 1;
218             $$ = NULL;
219         }
220         free($1);
221         $$ = var;
222     }
223     |
224     IDENTIFIER DOT IDENTIFIER {
225         bool foundField = false;
226
227         BPatch_variableExpr *var = findVariable($1);
228         if (var == NULL) {
229             fprintf(stderr, "Cannot find variable: %s\n", $1);
230             free($1);
231             return 1;
232         }
233
234         BPatch_Vector<BPatch_variableExpr *> *vars = var->getComponents();
235         if (!vars) {
236             fprintf(stderr, "is not an aggregate type: %s\n", $1);
237             free($1);
238             return 1;
239         }
240         for (unsigned int i=0; i < vars->size(); i++) {
241             if (!strcmp($3, (*vars)[i]->getName())) {
242                 $$ = (*vars)[i];
243                 foundField = true;
244             }
245         }
246
247         if (!foundField) {
248             fprintf(stderr, "%s is not a field of %s\n", $3, $1);
249             free($1);
250             return 1;
251         }
252
253         free($1);
254     }
255     | DOLLAR NUMBER {
256         if (($2 < 0) || ($2 >= 8)) {
257              printf("parameter %d is not valid\n", $2);
258              return 1;
259         }
260         $$ = new BPatch_paramExpr($2);
261     }
262     ;
263
264 arith_expression: 
265     variable_expr
266     |  NUMBER     { $$ = new BPatch_constExpr($1); }
267     |            arith_expression '*' arith_expression  {
268         $$ = new BPatch_arithExpr(BPatch_times, *$1, *$3);
269         delete $1;
270         delete $3;
271     }
272     |
273     func_call { $$ = $1; }
274     |
275     variable_expr ASSIGN arith_expression {
276             $$ = new BPatch_arithExpr(BPatch_assign, *$1, *$3);
277             if ($1) delete $1;
278             if ($3) delete $3;
279     }
280
281     |            arith_expression '/' arith_expression  {
282         $$ = new BPatch_arithExpr(BPatch_divide, *$1, *$3);
283         delete $1;
284         delete $3;
285     }
286     |            arith_expression '+' arith_expression  {
287         $$ = new BPatch_arithExpr(BPatch_plus, *$1, *$3);
288         delete $1;
289         delete $3;
290     }
291     |            arith_expression '-' arith_expression  {
292         $$ = new BPatch_arithExpr(BPatch_minus, *$1, *$3);
293         delete $1;
294         delete $3;
295     }
296     |            '(' arith_expression ')' {
297         $$ = $2;
298     }
299     |  inc_decr_expr {
300         $$ = $1;
301     }
302     ;
303
304 inc_decr_expr:
305     variable_expr PLUSPLUS {
306         $$ = new BPatch_arithExpr(BPatch_assign, *$1, BPatch_arithExpr(BPatch_plus, 
307                         *$1, BPatch_constExpr(1)));
308     }
309     | PLUSPLUS variable_expr {
310         $$ = new BPatch_arithExpr(BPatch_assign, *$2, BPatch_arithExpr(BPatch_plus, 
311                         *$2, BPatch_constExpr(1)));
312     }
313     | variable_expr MINUSMINUS {
314         $$ = new BPatch_arithExpr(BPatch_assign, *$1, BPatch_arithExpr(BPatch_minus, 
315                         *$1, BPatch_constExpr(1)));
316     }
317     | MINUSMINUS variable_expr {
318         $$ = new BPatch_arithExpr(BPatch_assign, *$2, BPatch_arithExpr(BPatch_minus, 
319                         *$2, BPatch_constExpr(1)));
320     }
321     ;
322
323 %%
324
325
326 #if 0 // For testing the parser independently
327 extern "C" void set_lex_input(char *str);
328
329 main(int argc, char *argv[])
330 {
331     int ret;
332
333     char str[512];
334     printf("here> ");
335     gets(str);
336
337     set_lex_input(str);
338
339     ret = yyparse();
340
341     printf("Returned: %d\n", ret);
342 }
343 #endif
344
345 void yyerror(char *s)
346 {
347     fprintf(stderr, "Error on command line: %s\n",s);
348 }