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}