001package jtb.cparser.customvisitor;
002
003import jtb.cparser.syntaxtree.*;
004import jtb.cparser.visitor.*;
005import java.util.*;
006
007public class Converter extends DepthFirstVisitor {
008
009  public ArrayList<String> actualStrings;
010  public ArrayList<String> stringArrays;
011  private boolean matrixAccess = false;
012  private boolean reorder = false;
013  private NestedArrayChecker nestChecker= new NestedArrayChecker();
014  private boolean shouldConvert = true;
015  private Vector<Node> toBringToFront = new Vector<Node>();
016  private int nestedIndents = 0;
017
018  public void visit(PostfixExpression n) {
019    if (isInParentheses(n)) {
020      handleParenthesesExpression(n);
021      return;
022    }
023    if (isMatrixAccess(n)) {
024      handleMatrixAccess(n);
025      return;
026    }
027    if (isArrayAccess(n)) {
028      handleArrayAccess(n);
029      return;
030    }
031    if (isFunctionCall(n)) {
032      handleFunctionCall(n);
033      return;
034    }
035  }
036
037
038
039  public boolean isInParentheses(PostfixExpression n) {
040    return (n.f0.f0.choice instanceof NodeSequence);
041  }
042
043  public void handleParenthesesExpression(PostfixExpression n) {
044    visit((Expression)((NodeSequence)n.f0.f0.choice).nodes.get(1));
045  }
046
047
048  public boolean isMatrixAccess(PostfixExpression n) {
049    if (n.f1.nodes.size() == 2) {
050      NodeChoice first = (NodeChoice) n.f1.nodes.get(0);
051      NodeChoice second = (NodeChoice) n.f1.nodes.get(1);
052      if (first.choice instanceof NodeSequence
053          && second.choice instanceof NodeSequence) {
054        return (isArrayAccess((NodeSequence) first.choice) &&
055                isArrayAccess((NodeSequence) second.choice));
056      }
057    }
058    return false;
059  }
060
061    public void handleMatrixAccess(PostfixExpression n) {
062    nestedIndents++;
063    NodeChoice first = (NodeChoice) n.f1.nodes.get(0);
064    NodeChoice second = (NodeChoice) n.f1.nodes.get(1);
065    NodeSequence seq1 = (NodeSequence) first.choice;
066    NodeSequence seq2 = (NodeSequence) second.choice;
067    if (containsArrayAccess((Expression)seq1.nodes.get(1)) ||
068        containsArrayAccess((Expression)seq2.nodes.get(1))) {
069      shouldConvert = false;
070      super.visit(n);
071      if (nestedIndents == 1) {
072        shouldConvert = true;
073      }
074      convertMatrixExpression(n, seq1.nodes, seq2.nodes);
075      if (nestedIndents == 1) {
076        seq1.nodes.addAll(0, toBringToFront);
077        toBringToFront.clear();
078      }
079    }
080    else if (reorder) {
081      convertMatrixExpression(n, seq1.nodes, seq2.nodes);
082      seq1.nodes.addAll(0, toBringToFront);
083      toBringToFront.clear();
084    }
085    else {
086      convertMatrixExpression(n, seq1.nodes, seq2.nodes);
087    }
088    nestedIndents--;
089  }
090
091  public void  convertMatrixExpression(PostfixExpression n, Vector<Node> nodes1, Vector<Node> nodes2) {
092    NodeToken nameToken = (NodeToken) n.f0.f0.choice;
093    String nameString = nameToken.tokenImage;
094    String lengthString = "length";
095    if (isStringArray(nameString)) {
096      lengthString = "length()";
097      convertToStringAccess(nodes2);
098    }
099    if (shouldConvert) {
100      nameToken.tokenImage = "";
101      nodes1.remove(0);
102      nodes1.remove(1);
103      nodes1.add(1, new NodeToken(">=0 && "));
104      nodes1.add(2, nodes1.get(0));
105      nodes1.add(3, new NodeToken("<" + nameString + ".length && "));
106      nodes1.add(4, nodes2.get(1));
107      nodes1.add(5, new NodeToken(">=0 && "));
108      nodes1.add(6, nodes2.get(1));
109      nodes1.add(7, new NodeToken("<" + nameString + "["));
110      nodes1.add(8, nodes1.get(0));
111      nodes1.add(9, new NodeToken("]." + lengthString +  " && "));
112      nodes1.add(10, new NodeToken(nameString));
113      nodes1.add(11, new NodeToken("["));
114      nodes1.add(12, nodes1.get(0));
115      nodes1.add(13, new NodeToken("]"));
116      nodes1.addAll(nodes2);
117      nodes2.clear();
118    }
119    else {
120      toBringToFront.add(nodes1.get(1));
121      toBringToFront.add(new NodeToken(">=0 && "));
122      toBringToFront.add(nodes1.get(1));
123      toBringToFront.add(new NodeToken("<" + nameString + ".length && "));
124      toBringToFront.add(nodes2.get(1));
125      toBringToFront.add(new NodeToken("<" + nameString + "["));
126      toBringToFront.add(nodes1.get(1));
127      toBringToFront.add(new NodeToken("]." + lengthString +  " && "));
128      toBringToFront.add(nodes2.get(1));
129      toBringToFront.add(new NodeToken(">= 0 && "));
130    }
131  }
132
133
134  private void convertToStringAccess(Vector<Node> v) {
135    // remove the [ and ]
136    v.remove(0);
137    v.remove(1);
138    v.add(0, new NodeToken(".charAt("));
139    v.add(new NodeToken(")"));
140  }
141
142
143  public boolean isArrayAccess(PostfixExpression n) {
144    if (n.f1.nodes.size() > 0) {
145      NodeChoice choice = (NodeChoice) n.f1.nodes.get(0);
146      if (choice.choice instanceof NodeSequence) {
147        NodeSequence seq = (NodeSequence) choice.choice;
148        return (isArrayAccess(seq));
149      }
150    }
151    return false;
152  }
153
154  private boolean isArrayAccess(NodeSequence seq) {
155    return (seq.nodes.size() == 3 && seq.nodes.get(0).toString().equals("[") &&
156            seq.nodes.get(2).toString().equals("]"));
157  }
158
159  public void handleArrayAccess(PostfixExpression n) {
160    nestedIndents++;
161    NodeChoice choice = (NodeChoice) n.f1.nodes.get(0);
162    if (choice.choice instanceof NodeSequence) {
163      NodeSequence seq = (NodeSequence) choice.choice;
164      Expression p = (Expression)(seq.nodes.get(1));
165      if (containsArrayAccess(p)) {
166        shouldConvert = false;
167        super.visit(p);
168        if (nestedIndents == 1) {
169          shouldConvert = true;
170        }
171        convertArrayExpression(n, seq.nodes, 0);
172        if (nestedIndents == 1) {
173          seq.nodes.addAll(0, toBringToFront);
174          toBringToFront.clear();
175        }
176      }
177      else if (reorder) {
178        convertArrayExpression(n, seq.nodes, 0);
179        seq.nodes.addAll(0, toBringToFront);
180        toBringToFront.clear();
181      }
182      else {
183        convertArrayExpression(n, seq.nodes, 0);
184      }
185    }
186    nestedIndents--;
187  }
188
189    public void convertArrayExpression(PostfixExpression n, Vector<Node> nodes, int i) {
190    if ((n.f0.f0.choice instanceof NodeToken)) {
191      String name = n.f0.f0.choice.toString();
192      if (shouldConvert) {
193        ((NodeToken)n.f0.f0.choice).tokenImage = "";
194        nodes.add(0, nodes.get(1));
195        nodes.add(1, new NodeToken("<" + name+ ".length && "));
196        nodes.add(2, nodes.get(3));
197        nodes.add(3, new NodeToken(">=0 && "));
198        nodes.add(4, new NodeToken(name));
199        if (isString(name)) {
200          NodeToken lengthAppend = (NodeToken) nodes.get(1);
201          lengthAppend.tokenImage = ("<" + name+ ".length() && ");
202          NodeToken token = (NodeToken) n.f0.f0.choice;
203          token.tokenImage =  "";
204          nodes.add(5, new NodeToken(".charAt((int)"));
205          nodes.remove(6);
206          NodeToken close = (NodeToken) nodes.get(7);
207          close.tokenImage = ")";
208        }
209      } else {
210        int index = 1;
211        if (isString(name)) {
212          nodes.add(0, new NodeToken(name));
213          NodeToken token = (NodeToken) n.f0.f0.choice;
214          token.tokenImage =  "";
215          nodes.add(1, new NodeToken(".charAt((int)"));
216          nodes.remove(2);
217          NodeToken close = (NodeToken) nodes.get(3);
218          close.tokenImage = ")";
219          index = 2;
220        }
221        String lengthString = (isString(name))?".length()":".length";
222
223        toBringToFront.add(nodes.get(index));
224        toBringToFront.add(new NodeToken("<" + name+ lengthString + " && "));
225        toBringToFront.add(nodes.get(index));
226        toBringToFront.add(new NodeToken(">=0 && "));
227      }
228    }
229  }
230
231
232
233  public boolean isFunctionCall(PostfixExpression n) {
234    if (n.f1.nodes.size() > 0) {
235      NodeChoice choice = (NodeChoice) n.f1.nodes.get(0);
236      if (choice.choice instanceof NodeSequence) {
237        NodeSequence seq = (NodeSequence) choice.choice;
238        return (isFunctionCall(seq));
239      }
240    }
241    return false;
242  }
243
244  public boolean isFunctionCall(NodeSequence seq) {
245    return (seq.nodes.size() == 3 && seq.nodes.get(0).toString().equals("(") &&
246            seq.nodes.get(2).toString().equals(")"));
247  }
248
249  public void handleFunctionCall(PostfixExpression n) {
250    NodeToken token = (NodeToken) n.f0.f0.choice;
251    NodeChoice choice = (NodeChoice) n.f1.nodes.get(0);
252    NodeSequence seq = (NodeSequence) choice.choice;
253    if (token.tokenImage.equals("strlen")) {
254      NodeOptional opt = (NodeOptional) seq.nodes.get(1);
255      ArrayList<Node> l = extractArgumentNames((ArgumentExpressionList)opt.node);
256      token.tokenImage =  "";
257      seq.nodes.remove(1);
258      seq.nodes.add(0, new NodeToken(".length"));
259      seq.nodes.add(0, l.get(0));
260    }
261  }
262
263  public boolean isStringArray(String n) {
264    return stringArrays.contains(n.trim());
265  }
266
267  public boolean isString(String name) {
268    return actualStrings.contains(name.trim());
269  }
270
271
272  private ArrayList<Node> extractArgumentNames(ArgumentExpressionList ael) {
273    ArrayList<Node> assigns = new ArrayList<Node>();
274    if (ael!=null) {
275      assigns.add(ael.f0);
276      if (ael.f1.nodes.size() > 0) {
277        for (int i = 0; i < ael.f1.nodes.size(); i++) {
278          NodeSequence curr = (NodeSequence)ael.f1.nodes.get(i);
279          for (int j = 0; j < curr.nodes.size(); j++) {
280            if (j%2 == 1) {
281              assigns.add(curr.nodes.get(j));
282            }
283          }
284        }
285      }
286    }
287    extractNamesAssignmentExpressions(assigns);
288    return assigns;
289  }
290
291
292  private ArrayList<Node> extractNamesAssignmentExpressions(ArrayList<Node> assigns) {
293    for (int i = 0; i < assigns.size(); i++) {
294      AssignmentExpression curr = (AssignmentExpression)assigns.get(i);
295      Node n = ((UnaryExpression)((ConditionalExpression)curr.f0.choice).f0.f0.f0.f0.f0.f0.f0.f0.f0.f0.f0.f0.choice).f0.choice;
296      Node temp  = ((PostfixExpression)n).f0.f0.choice;
297      assigns.remove(i);
298      if ((temp instanceof NodeToken)) {
299        assigns.add(temp);
300      }
301
302    }
303    return assigns;
304  }
305
306
307
308
309
310
311  public void visit(RelationalExpression n) {
312    boolean first = containsArrayAccess(n.f0);
313    boolean second = containsArrayAccess(n.f1);
314    if (!first && !second) {
315      n.f0.accept(this);
316      n.f1.accept(this);
317    }
318    else if (first && !second) {
319      n.f0.accept(this);
320      n.f1.accept(this);
321    }
322    else if (!first && second) {
323      NodeSequence seq = (NodeSequence) n.f1.node;
324      super.visit(n.f1);
325      seq.nodes.add(2, n.f0);
326      seq.nodes.add(1, seq.nodes.remove(0));
327      n.f0 = null;
328    }
329    else  {
330      shouldConvert = false;
331      n.f1.accept(this);
332      shouldConvert = true;
333      reorder = true;
334      n.f0.accept(this);
335      reorder = false;
336    }
337  }
338
339
340  public void visit(EqualityExpression n) {
341    boolean first = containsArrayAccess(n.f0);
342    boolean second = containsArrayAccess(n.f1);
343    if (!first && !second) {
344      n.f0.accept(this);
345      n.f1.accept(this);
346    }
347    else if (first && !second) {
348      n.f0.accept(this);
349      n.f1.accept(this);
350    }
351    else if (!first && second) {
352      NodeSequence seq = (NodeSequence) n.f1.node;
353      super.visit(n.f1);
354      seq.nodes.add(2, n.f0);
355      seq.nodes.add(1, seq.nodes.remove(0));
356      n.f0 = null;
357    }
358    else  {
359      shouldConvert = false;
360      n.f1.accept(this);
361      shouldConvert = true;
362      reorder = true;
363      n.f0.accept(this);
364      reorder = false;
365
366    }
367  }
368
369  public void visit(LogicalANDExpression n) {
370    // put parentheses around each subexpression
371    if (n!=null &&n.f1 != null && n.f1.node instanceof NodeSequence) {
372      Vector<Node> nodes = ((NodeSequence) n.f1.node).nodes;
373      if (nodes.get(0).toString().equals("&&")) {
374        nodes.add(0, new NodeToken("("));
375        nodes.add(1, n.f0);
376        nodes.add(2, new NodeToken(")"));
377        nodes.add(4, new NodeToken("("));
378        nodes.add(new NodeToken(")"));
379        n.f0 = null;
380        n.f1.accept(this);
381        return;
382      }
383    }
384    n.f0.accept(this);
385    n.f1.accept(this);
386  }
387
388  public void visit(LogicalORExpression n) {
389    // put parentheses around each subexpression
390    if (n != null && n.f1.node instanceof NodeSequence) {
391      Vector<Node> nodes = ((NodeSequence) n.f1.node).nodes;
392      if (nodes.get(0).toString().equals("||")) {
393        nodes.add(0, new NodeToken("("));
394        nodes.add(1, n.f0);
395        nodes.add(2, new NodeToken(")"));
396        nodes.add(4, new NodeToken("("));
397        nodes.add(new NodeToken(")"));
398        n.f0 = null;
399        n.f1.accept(this);
400        return;
401      }
402    }
403    n.f0.accept(this);
404    n.f1.accept(this);
405  }
406
407  public boolean containsArrayAccess(Expression n) {
408    return nestChecker.containsArrayAccess(n);
409  }
410
411  public boolean containsArrayAccess(ShiftExpression n) {
412    return nestChecker.containsArrayAccess(n);
413  }
414
415  public boolean containsArrayAccess(RelationalExpression n) {
416    return nestChecker.containsArrayAccess(n);
417  }
418
419  public boolean containsArrayAccess(NodeOptional n) {
420    return nestChecker.containsArrayAccess(n);
421  }
422
423  class NestedArrayChecker extends DepthFirstVisitor {
424
425    private boolean isNested = false;
426    public boolean containsArrayAccess(Expression n) {
427      isNested = false;
428      super.visit(n);
429      return isNested;
430    }
431
432    public boolean containsArrayAccess(RelationalExpression n) {
433      isNested = false;
434      super.visit(n);
435      return isNested;
436    }
437
438    public boolean containsArrayAccess(NodeOptional n) {
439      isNested = false;
440      super.visit(n);
441      return isNested;
442    }
443
444    public boolean containsArrayAccess(ShiftExpression n) {
445      isNested = false;
446      super.visit(n);
447      return isNested;
448    }
449
450    public void visit(PostfixExpression n) {
451      if (isArrayAccess(n) || isMatrixAccess(n)) {
452        isNested = true;
453      }
454    }
455  }
456
457
458}