fixes
[oweals/gnunet.git] / src / monkey / seaspider / org / gnunet / seaspider / ExpressionExtractorVisitor.java
1 package org.gnunet.seaspider;
2
3 import org.gnunet.seaspider.parser.nodes.ANDExpression;
4 import org.gnunet.seaspider.parser.nodes.AdditiveExpression;
5 import org.gnunet.seaspider.parser.nodes.ArgumentExpressionList;
6 import org.gnunet.seaspider.parser.nodes.AssignmentExpression;
7 import org.gnunet.seaspider.parser.nodes.AssignmentOperator;
8 import org.gnunet.seaspider.parser.nodes.CastExpression;
9 import org.gnunet.seaspider.parser.nodes.CompoundStatement;
10 import org.gnunet.seaspider.parser.nodes.ConditionalExpression;
11 import org.gnunet.seaspider.parser.nodes.ConstantExpression;
12 import org.gnunet.seaspider.parser.nodes.DoWhileStatement;
13 import org.gnunet.seaspider.parser.nodes.EqualityExpression;
14 import org.gnunet.seaspider.parser.nodes.ExclusiveORExpression;
15 import org.gnunet.seaspider.parser.nodes.Expression;
16 import org.gnunet.seaspider.parser.nodes.ExpressionStatement;
17 import org.gnunet.seaspider.parser.nodes.ForStatement;
18 import org.gnunet.seaspider.parser.nodes.FunctionDeclaration;
19 import org.gnunet.seaspider.parser.nodes.IfStatement;
20 import org.gnunet.seaspider.parser.nodes.InclusiveORExpression;
21 import org.gnunet.seaspider.parser.nodes.InitDeclarator;
22 import org.gnunet.seaspider.parser.nodes.InitDeclaratorList;
23 import org.gnunet.seaspider.parser.nodes.Initializer;
24 import org.gnunet.seaspider.parser.nodes.InitializerList;
25 import org.gnunet.seaspider.parser.nodes.JumpStatement;
26 import org.gnunet.seaspider.parser.nodes.LogicalANDExpression;
27 import org.gnunet.seaspider.parser.nodes.LogicalORExpression;
28 import org.gnunet.seaspider.parser.nodes.MultiplicativeExpression;
29 import org.gnunet.seaspider.parser.nodes.NodeChoice;
30 import org.gnunet.seaspider.parser.nodes.NodeSequence;
31 import org.gnunet.seaspider.parser.nodes.NodeToken;
32 import org.gnunet.seaspider.parser.nodes.ParameterDeclaration;
33 import org.gnunet.seaspider.parser.nodes.PostfixExpression;
34 import org.gnunet.seaspider.parser.nodes.PrimaryExpression;
35 import org.gnunet.seaspider.parser.nodes.RelationalExpression;
36 import org.gnunet.seaspider.parser.nodes.ShiftExpression;
37 import org.gnunet.seaspider.parser.nodes.StructOrUnionSpecifier;
38 import org.gnunet.seaspider.parser.nodes.SwitchStatement;
39 import org.gnunet.seaspider.parser.nodes.TranslationUnit;
40 import org.gnunet.seaspider.parser.nodes.TypeDeclaration;
41 import org.gnunet.seaspider.parser.nodes.UnaryExpression;
42 import org.gnunet.seaspider.parser.nodes.UnaryOperator;
43 import org.gnunet.seaspider.parser.nodes.VariableDeclaration;
44 import org.gnunet.seaspider.parser.nodes.WhileStatement;
45 import org.gnunet.seaspider.parser.visitors.DepthFirstVisitor;
46 import org.grothoff.LineNumberInfo;
47
48 /**
49  * @author grothoff
50  * 
51  */
52 public class ExpressionExtractorVisitor extends DepthFirstVisitor {
53
54         class ExpressionBuilder {
55                 String expression = "";
56
57                 void push(String token) {
58                         expression = expression + token;
59                 }
60
61                 void commit(int line) {
62                         ExpressionDatabaseHandler.insertIntoExpressionTable(filename,
63                                         expression, line, scope_end_line);
64                 }
65
66         }
67
68         final String filename;
69
70         ExpressionBuilder current_expression;
71
72         int scope_end_line;
73
74         boolean operator;
75
76         boolean skip_mode = true;
77
78         /**
79          * 
80          */
81         public ExpressionExtractorVisitor(String filename) {
82                 this.filename = filename;
83         }
84
85         public void visit(TranslationUnit n) {
86                 LineNumberInfo lin = LineNumberInfo.get(n);
87                 scope_end_line = lin.lineEnd;
88                 n.f0.accept(this);
89                 assert scope_end_line == lin.lineEnd;
90         }
91
92         public void visit(NodeToken n) {
93                 if (skip_mode)
94                         return;
95                 current_expression.push(n.tokenImage);
96         }
97
98         public void visit(StructOrUnionSpecifier n) {
99                 // do nothing -- skip!
100         }
101
102         public void visit(TypeDeclaration n) {
103                 // do nothing -- skip!
104         }
105
106         public void visit(InitDeclaratorList n) {
107                 assert skip_mode == true;
108                 super.visit (n);                
109                 assert skip_mode == true;
110         }
111         
112         public void visit(Initializer n) {
113                 assert skip_mode == true;
114                 super.visit (n);                
115                 assert skip_mode == true;
116         }
117
118         public void visit(InitializerList n) {
119                 assert skip_mode == true;
120                 super.visit (n);                
121                 assert skip_mode == true;
122         }
123         
124         public void visit(VariableDeclaration n) {
125                 assert skip_mode == true;
126                 super.visit (n);
127         }
128
129         public void visit(FunctionDeclaration n) {
130                 if (n.f5.which == 0)
131                         return; // no body
132                 int old_scope = scope_end_line;
133                 LineNumberInfo lin = LineNumberInfo.get(n);
134                 scope_end_line = lin.lineEnd;
135                 n.f3.accept(this);
136                 n.f5.accept(this);
137                 assert scope_end_line == lin.lineEnd;
138                 scope_end_line = old_scope;
139         }
140
141         public void visit(ParameterDeclaration n) {
142                 skip_mode = false;
143                 assert current_expression == null;
144                 current_expression = new ExpressionBuilder();
145                 n.f1.accept(this);
146                 LineNumberInfo lin = LineNumberInfo.get(n);
147                 current_expression.commit(lin.lineEnd);
148                 current_expression = null;
149                 skip_mode = true;
150         }
151
152         public void visit(InitDeclarator n) {
153                 skip_mode = false;
154                 assert current_expression == null;
155                 current_expression = new ExpressionBuilder();
156                 n.f0.accept(this);
157                 current_expression = null;
158                 skip_mode = true;
159                 n.f2.accept(this);
160         }
161
162         public void visit(ExpressionStatement n) {
163                 if (!n.f0.present())
164                         return;
165                 assert current_expression == null;
166                 skip_mode = false;
167                 current_expression = new ExpressionBuilder();
168                 n.f0.accept(this);
169                 LineNumberInfo lin = LineNumberInfo.get(n);
170                 current_expression.commit(lin.lineEnd);
171                 current_expression = null;
172                 skip_mode = true;
173         }
174
175         public void visit(CompoundStatement n) {
176                 assert current_expression == null;
177                 assert skip_mode == true;
178                 int old_end = scope_end_line;
179                 scope_end_line = n.f2.endLine;
180                 n.f1.accept(this);
181                 scope_end_line = old_end;
182         }
183
184         public void visit(SwitchStatement n) {
185                 assert current_expression == null;
186                 skip_mode = false;
187                 current_expression = new ExpressionBuilder();
188                 n.f2.accept(this);
189                 current_expression.commit(n.f0.endLine);
190                 skip_mode = true;
191                 current_expression = null;
192                 n.f4.accept(this);
193         }
194
195         public void visit(IfStatement n) {
196                 assert current_expression == null;
197                 skip_mode = false;
198                 current_expression = new ExpressionBuilder();
199                 n.f2.accept(this);
200                 current_expression.commit(n.f0.endLine);
201                 skip_mode = true;
202                 current_expression = null;
203                 n.f4.accept(this);
204                 n.f5.accept(this);
205         }
206
207         public void visit(WhileStatement n) {
208                 assert current_expression == null;
209                 skip_mode = false;
210                 current_expression = new ExpressionBuilder();
211                 n.f2.accept(this);
212                 current_expression.commit(n.f0.endLine);
213                 skip_mode = true;
214                 current_expression = null;
215                 n.f4.accept(this);
216         }
217
218         public void visit(DoWhileStatement n) {
219                 assert current_expression == null;
220                 skip_mode = false;
221                 current_expression = new ExpressionBuilder();
222                 n.f4.accept(this);
223                 current_expression.commit(n.f6.endLine);
224                 skip_mode = true;
225                 current_expression = null;
226                 n.f1.accept(this);
227         }
228
229         public void visit(ForStatement n) {
230                 assert current_expression == null;
231                 skip_mode = false;
232                 int old_scope = scope_end_line;
233                 LineNumberInfo lin = LineNumberInfo.get(n);
234                 scope_end_line = lin.lineEnd;
235                 if (n.f2.present()) {
236                         current_expression = new ExpressionBuilder();
237                         n.f2.accept(this);
238                         current_expression.commit(n.f3.endLine);
239                 }
240                 if (n.f4.present()) {
241                         current_expression = new ExpressionBuilder();
242                         n.f4.accept(this);
243                         current_expression.commit(n.f5.endLine);
244                 }
245                 if (n.f6.present()) {
246                         current_expression = new ExpressionBuilder();
247                         n.f6.accept(this);
248                         current_expression.commit(n.f7.endLine);
249                 }
250                 skip_mode = true;
251                 current_expression = null;
252                 n.f8.accept(this);
253                 scope_end_line = old_scope;
254         }
255
256         public void visit(JumpStatement n) {
257                 if (n.f0.which != 3)
258                         return;
259                 NodeSequence ns = (NodeSequence) n.f0.choice;
260                 assert current_expression == null;
261                 skip_mode = false;
262                 current_expression = new ExpressionBuilder();
263                 ns.elementAt(1).accept(this);
264                 LineNumberInfo lin = LineNumberInfo.get(n);
265                 current_expression.commit(lin.lineEnd);
266                 current_expression = null;
267                 skip_mode = true;
268         }
269
270         public void visit(Expression n) {
271                 ExpressionBuilder old = current_expression;
272                 current_expression = new ExpressionBuilder();
273                 n.f0.accept(this);
274                 for (int i = 0; i < n.f1.size(); i++) {
275                         NodeSequence ns = (NodeSequence) n.f1.elementAt(i);
276                         current_expression = new ExpressionBuilder();
277                         ns.elementAt(1).accept(this);
278                 }
279                 old.push(current_expression.expression);
280                 current_expression = old;
281         }
282
283         public void visit(AssignmentExpression n) {
284                 boolean old_mode = skip_mode;
285                 skip_mode = false;
286                 ExpressionBuilder old = current_expression;
287                 current_expression = new ExpressionBuilder();
288                 n.f0.accept(this);
289                 if (old != null) {
290                         old.push(current_expression.expression);
291                         LineNumberInfo lin = LineNumberInfo.get(n);
292                         old.commit(lin.lineEnd);
293                 }
294                 current_expression = old;
295                 skip_mode = old_mode;
296         }
297
298         public void visit(AssignmentOperator n) {
299                 operator = true;
300                 super.visit(n);
301                 operator = false;
302         }
303
304         public void visit(ConditionalExpression n) {
305                 ExpressionBuilder old = current_expression;
306                 current_expression = new ExpressionBuilder();
307                 n.f0.accept(this);
308                 old.push(current_expression.expression);
309                 if (n.f1.present()) {
310                         NodeSequence ns = (NodeSequence) n.f1.node;
311                         current_expression = new ExpressionBuilder();
312                         ns.elementAt(1).accept(this);
313                         old.push("?");
314                         old.push(current_expression.expression);
315                         current_expression = new ExpressionBuilder();
316                         ns.elementAt(3).accept(this);
317                         old.push(":");
318                         old.push(current_expression.expression);
319                         LineNumberInfo lin = LineNumberInfo.get(n);
320                         old.commit(lin.lineEnd);
321                 }
322                 current_expression = old;
323         }
324
325         public void visit(ConstantExpression n) {
326                 /* skip */
327         }
328
329         public void visit(LogicalORExpression n) {
330                 assert skip_mode == false;
331                 ExpressionBuilder old = current_expression;
332                 current_expression = new ExpressionBuilder();
333                 n.f0.accept(this);
334                 if (n.f1.present()) {
335                         operator = true;
336                         NodeSequence ns = (NodeSequence) n.f1.node;
337                         ns.nodes.get(0).accept(this);
338                         operator = false;
339                         ns.nodes.get(1).accept(this);
340                 }
341                 old.push(current_expression.expression);
342                 current_expression = old;
343         }
344
345         public void visit(LogicalANDExpression n) {
346                 assert skip_mode == false;
347                 ExpressionBuilder old = current_expression;
348                 current_expression = new ExpressionBuilder();
349                 n.f0.accept(this);
350                 if (n.f1.present()) {
351                         operator = true;
352                         NodeSequence ns = (NodeSequence) n.f1.node;
353                         ns.nodes.get(0).accept(this);
354                         operator = false;
355                         ns.nodes.get(1).accept(this);
356                 }
357                 old.push(current_expression.expression);
358                 current_expression = old;
359         }
360
361         public void visit(InclusiveORExpression n) {
362                 assert skip_mode == false;
363                 ExpressionBuilder old = current_expression;
364                 current_expression = new ExpressionBuilder();
365                 n.f0.accept(this);
366                 if (n.f1.present()) {
367                         operator = true;
368                         NodeSequence ns = (NodeSequence) n.f1.node;
369                         ns.nodes.get(0).accept(this);
370                         operator = false;
371                         ns.nodes.get(1).accept(this);
372                 }
373                 old.push(current_expression.expression);
374                 current_expression = old;
375         }
376
377         public void visit(ExclusiveORExpression n) {
378                 assert skip_mode == false;
379                 ExpressionBuilder old = current_expression;
380                 current_expression = new ExpressionBuilder();
381                 n.f0.accept(this);
382                 if (n.f1.present()) {
383                         operator = true;
384                         NodeSequence ns = (NodeSequence) n.f1.node;
385                         ns.nodes.get(0).accept(this);
386                         operator = false;
387                         ns.nodes.get(1).accept(this);
388                 }
389                 old.push(current_expression.expression);
390                 current_expression = old;
391         }
392
393         public void visit(ANDExpression n) {
394                 assert skip_mode == false;
395                 ExpressionBuilder old = current_expression;
396                 current_expression = new ExpressionBuilder();
397                 n.f0.accept(this);
398                 if (n.f1.present()) {
399                         operator = true;
400                         NodeSequence ns = (NodeSequence) n.f1.node;
401                         ns.nodes.get(0).accept(this);
402                         operator = false;
403                         ns.nodes.get(1).accept(this);
404                 }
405                 old.push(current_expression.expression);
406                 current_expression = old;
407         }
408
409         // Safey: this function was fixed to commit the right hand side, the
410         // other similar functions still need to be updated accordingly...
411         public void visit(EqualityExpression n) {
412                 assert skip_mode == false;
413                 ExpressionBuilder old = current_expression;
414                 current_expression = new ExpressionBuilder();
415                 n.f0.accept(this);
416                 if (n.f1.present()) {
417                         LineNumberInfo lin = LineNumberInfo.get(n);
418                         current_expression.commit(lin.lineEnd);                 
419                         operator = true;
420                         NodeSequence ns = (NodeSequence) n.f1.node;
421                         ns.nodes.get(0).accept(this);
422                         operator = false;
423                         old.push(current_expression.expression);
424                         current_expression = new ExpressionBuilder();
425                         ns.nodes.get(1).accept(this);
426                         current_expression.commit(lin.lineEnd);                 
427                 }
428                 old.push(current_expression.expression);
429                 current_expression = old;
430         }
431
432         public void visit(RelationalExpression n) {
433                 assert skip_mode == false;
434                 ExpressionBuilder old = current_expression;
435                 current_expression = new ExpressionBuilder();
436                 n.f0.accept(this);
437                 if (n.f1.present()) {
438                         operator = true;
439                         NodeSequence ns = (NodeSequence) n.f1.node;
440                         ns.nodes.get(0).accept(this);
441                         operator = false;
442                         ns.nodes.get(1).accept(this);
443                 }
444                 old.push(current_expression.expression);
445                 current_expression = old;
446         }
447
448         public void visit(ShiftExpression n) {
449                 assert skip_mode == false;
450                 ExpressionBuilder old = current_expression;
451                 current_expression = new ExpressionBuilder();
452                 n.f0.accept(this);
453                 if (n.f1.present()) {
454                         operator = true;
455                         NodeSequence ns = (NodeSequence) n.f1.node;
456                         ns.nodes.get(0).accept(this);
457                         operator = false;
458                         ns.nodes.get(1).accept(this);
459                 }
460                 old.push(current_expression.expression);
461                 current_expression = old;
462         }
463
464         public void visit(AdditiveExpression n) {
465                 assert skip_mode == false;
466                 ExpressionBuilder old = current_expression;
467                 current_expression = new ExpressionBuilder();
468                 n.f0.accept(this);
469                 if (n.f1.present()) {
470                         operator = true;
471                         NodeSequence ns = (NodeSequence) n.f1.node;
472                         ns.nodes.get(0).accept(this);
473                         operator = false;
474                         ns.nodes.get(1).accept(this);
475                 }
476                 old.push(current_expression.expression);
477                 current_expression = old;
478         }
479
480         public void visit(MultiplicativeExpression n) {
481                 assert skip_mode == false;
482                 ExpressionBuilder old = current_expression;
483                 current_expression = new ExpressionBuilder();
484                 n.f0.accept(this);
485                 if (n.f1.present()) {
486                         operator = true;
487                         NodeSequence ns = (NodeSequence) n.f1.node;
488                         ns.nodes.get(0).accept(this);
489                         operator = false;
490                         ns.nodes.get(1).accept(this);
491                 }
492                 old.push(current_expression.expression);
493                 current_expression = old;
494         }
495
496         public void visit(CastExpression n) {
497                 if (n.f0.which == 1) {
498                         n.f0.accept(this);
499                         return;
500                 }
501                 NodeSequence ns = (NodeSequence) n.f0.choice;
502                 ns.nodes.get(3).accept(this);
503         }
504
505         public void visit(UnaryExpression n) {
506                 if ((n.f0.which == 1) || (n.f0.which == 2)) {
507                         NodeSequence ns = (NodeSequence) n.f0.choice;
508                         ns.nodes.get(1).accept(this);
509                 } else
510                         n.f0.accept(this);
511
512         }
513
514         public void visit(UnaryOperator n) {
515                 operator = true;
516                 n.f0.accept(this);
517                 operator = false;
518         }
519
520         public void visit(PostfixExpression n) {
521                 n.f0.accept(this);
522                 for (int i = 0; i < n.f1.size(); i++) {
523                         NodeChoice nc = (NodeChoice) n.f1.elementAt(i);
524                         switch (nc.which) {
525                         case 0: // []
526                         {
527                                 ExpressionBuilder old = current_expression;
528                                 current_expression = new ExpressionBuilder();
529                                 NodeSequence ns = (NodeSequence) nc.choice;
530                                 ns.elementAt(1).accept(this);
531                                 LineNumberInfo lin = LineNumberInfo.get(n);
532                                 current_expression.commit(lin.colEnd);
533                                 old.push("[");
534                                 old.push(current_expression.expression);
535                                 old.push("]");
536                                 current_expression = old;
537                         }
538                         case 1: // ()
539                         {
540                                 ExpressionBuilder old = current_expression;
541                                 current_expression = new ExpressionBuilder();
542                                 NodeSequence ns = (NodeSequence) nc.choice;
543                                 ns.elementAt(1).accept(this);
544                                 old.push("(");
545                                 old.push(current_expression.expression);
546                                 old.push(")");
547                                 current_expression = old;
548                         }
549                                 break;
550                         case 2: // .
551                         case 3: // ->
552                         {
553                                 ExpressionBuilder old = current_expression;
554                                 LineNumberInfo lin = LineNumberInfo.get(n);
555                                 old.commit(lin.lineEnd);
556                                 current_expression = new ExpressionBuilder();
557                                 NodeSequence ns = (NodeSequence) nc.choice;
558                                 ns.elementAt(1).accept(this);
559                                 if (nc.which == 2)
560                                         old.push(".");
561                                 else
562                                         old.push("->");
563                                 old.push(current_expression.expression);
564                                 current_expression = old;
565                         }
566                                 break;
567                         case 4: // ++
568                         case 5: // --
569                                 /* skip */
570                                 break;
571                         default:
572                                 throw new Error("Oops!");
573                         }
574                 }
575         }
576
577         public void visit(PrimaryExpression n) {
578                 if (n.f0.which == 2) {
579                         ExpressionBuilder old = current_expression;
580                         current_expression = new ExpressionBuilder();
581                         NodeSequence ns = (NodeSequence) n.f0.choice;
582                         ns.elementAt(1).accept(this);
583                         old.push("(");
584                         old.push(current_expression.expression);
585                         old.push(")");
586                         LineNumberInfo lin = LineNumberInfo.get(n);
587                         old.commit(lin.lineEnd);
588                         current_expression = old;
589                 } else
590                         n.f0.accept(this);
591         }
592
593         public void visit(ArgumentExpressionList n) {
594                 ExpressionBuilder old = current_expression;
595                 current_expression = new ExpressionBuilder();
596                 n.f0.accept(this);
597                 old.push(current_expression.expression);
598                 for (int i = 0; i < n.f1.size(); i++) {
599                         NodeSequence ns = (NodeSequence) n.f1.elementAt(i);
600                         current_expression = new ExpressionBuilder();
601                         ns.elementAt(1).accept(this);
602                         old.push(",");
603                         old.push(current_expression.expression);
604                 }
605                 current_expression = old;
606         }
607
608 }