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