00001 package edu.ksu.cis.bandera.abstraction.specification;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 import java.util.*;
00036 import java.io.*;
00037 import edu.ksu.cis.bandera.abstraction.*;
00038 import edu.ksu.cis.bandera.abstraction.specification.node.*;
00039 import edu.ksu.cis.bandera.abstraction.specification.lexer.*;
00040 import edu.ksu.cis.bandera.abstraction.specification.parser.*;
00041 import edu.ksu.cis.bandera.abstraction.specification.analysis.*;
00042 public class AbstractionGenerator extends DepthFirstAdapter {
00043 private static final String lineSeparator = System.getProperty("line.separator");
00044 private static final Hashtable opNameTable = new Hashtable();
00045 static {
00046 opNameTable.put("+", "add");
00047 opNameTable.put("-", "sub");
00048 opNameTable.put("*", "mul");
00049 opNameTable.put("/", "div");
00050 opNameTable.put("%", "rem");
00051 opNameTable.put("==", "eq");
00052 opNameTable.put("!=", "ne");
00053 opNameTable.put(">=", "ge");
00054 opNameTable.put("<=", "le");
00055 opNameTable.put(">", "gt");
00056 opNameTable.put("<", "lt");
00057 }
00058
00059 private Vector errors = new Vector();
00060 private Vector warnings = new Vector();
00061 private String type;
00062
00063
00064 private StringBuffer buffer;
00065 private Node node;
00066 private String superTypeName;
00067 private String packageName;
00068 private String abstractionName;
00069 private Vector tokenSet;
00070 private HashSet one2oneSet;
00071 private Collection tempCollection;
00072 private String[] fields;
00073 private Vector absFunctions;
00074 private String paramAbsFunction;
00075 private boolean foundAnyAbstractDef;
00076 private boolean isTest;
00077 private Hashtable opTable;
00078 private Vector currentOp;
00079 private int[][] opLeftRight;
00080 private int[][] opLeftResult;
00081 private int[][] opRightResult;
00082 private HashSet possibleArguments;
00083
00084
00085
00086
00087 public AbstractionGenerator(Reader reader) {
00088 try {
00089 node = new Parser(new Lexer(new PushbackReader(reader))).parse();
00090 } catch (Exception e) {
00091 errors.add("Error occured when generating abstraction: \"" + e.getMessage() + "\"");
00092 }
00093 }
00094
00095
00096
00097
00098 public void caseAAbstractFunction(AAbstractFunction node) {
00099 paramAbsFunction = node.getId().toString().trim();
00100 {
00101 Object temp[] = node.getAbstractDef().toArray();
00102 for (int i = 0; i < temp.length; i++) {
00103 ((PAbstractDef) temp[i]).apply(this);
00104 }
00105 }
00106 }
00107
00108
00109
00110
00111 public void caseAAnyAbstractDef(AAnyAbstractDef node) {
00112 if (foundAnyAbstractDef) {
00113 warnings.add("Found '_' before '" + node.toString() + "' at line " + node.getSemicolon().getLine() + ". Ignored...");
00114 } else {
00115 foundAnyAbstractDef = true;
00116 String token = node.getId().toString().trim();
00117 if (tokenSet.contains(token)) {
00118 absFunctions.add("if (n == n) return " + token + ";");
00119 } else {
00120 warnings.add("Invalid token '" + token + "' at line " + node.getSemicolon().getLine() + ". Ignored...");
00121 }
00122 }
00123 }
00124
00125
00126
00127
00128 public void caseAAnyPattern(AAnyPattern node) {
00129 if (possibleArguments.size() == 0) {
00130 warnings.add("Unnecessary " + (isTest? "test" : "operator") + " pattern '" + node.toString() + "' at line " + node.getSemicolon().getLine() + ". Ignored...");
00131 return;
00132 }
00133 tempCollection = new HashSet();
00134 node.getTokenTokenSet().apply(this);
00135 int result = 0;
00136 if (isTest) {
00137 boolean hasTrue = tempCollection.remove("TRUE");
00138 boolean hasFalse = tempCollection.remove("FALSE");
00139 for (Iterator i = tempCollection.iterator(); i.hasNext();) {
00140 warnings.add("Invalid token '" + i.next() + "' at line " + node.getSemicolon().getLine() + ". Ignored...");
00141 }
00142 if (hasTrue && hasFalse) {
00143 result = Abstraction.TRUE_OR_FALSE;
00144 currentOp.add("if (left$ == left$) return Abstraction.choose();");
00145 } else
00146 if (hasTrue) {
00147 result = Abstraction.TRUE;
00148 currentOp.add("if (left$ == left$) return true;");
00149 } else
00150 if (hasFalse) {
00151 result = Abstraction.FALSE;
00152 currentOp.add("if (left$ == left$) return false;");
00153 } else {
00154 warnings.add("Invalid test pattern definition at line " + node.getSemicolon().getLine() + ". Ignored...");
00155 return;
00156 }
00157 } else {
00158 int size = 0;
00159 int lastIndex = -1;
00160 for (Iterator i = tempCollection.iterator(); i.hasNext();) {
00161 String token = (String) i.next();
00162 int index = tokenSet.indexOf(token);
00163 if (index != -1) {
00164 result += (1 << index);
00165 lastIndex = index;
00166 size++;
00167 } else {
00168 warnings.add("Invalid token '" + token + "' at line " + node.getSemicolon().getLine() + ". Ignored...");
00169 }
00170 }
00171 if (size == 1) {
00172 currentOp.add("if (left$ == left$) return " + tokenSet.elementAt(lastIndex) + ";");
00173 } else
00174 if (size > 1) {
00175 currentOp.add("if (left$ == left$) return Abstraction.choose(" + getExpandedString(result) + ");");
00176 } else {
00177 warnings.add("Invalid test pattern definition at line " + node.getSemicolon().getLine() + ". Ignored...");
00178 return;
00179 }
00180 }
00181 for (Iterator i = possibleArguments.iterator(); i.hasNext();) {
00182 String tuple = (String) i.next();
00183 int index = tuple.indexOf(":");
00184 int leftArg = tokenSet.indexOf(tuple.substring(0, index));
00185 int rightArg = tokenSet.indexOf(tuple.substring(index + 1));
00186 opLeftResult[leftArg][result] |= (1 << rightArg);
00187 opLeftRight[leftArg][rightArg] = result;
00188 opRightResult[rightArg][result] |= (1 << leftArg);
00189 }
00190 possibleArguments.clear();
00191 }
00192
00193
00194
00195
00196 public void caseADefaultToken(ADefaultToken node) {
00197 String defaultToken = node.getId().toString().trim();
00198 if (tokenSet.remove(defaultToken)) {
00199 tokenSet.insertElementAt(defaultToken, 0);
00200 } else {
00201 errors.add("Invalid default token '" + defaultToken + "' at line " + node.getSemicolon().getLine());
00202 }
00203 }
00204
00205
00206
00207
00208 public void caseAExpAbstractDef(AExpAbstractDef node) {
00209 if (foundAnyAbstractDef) {
00210 warnings.add("Found '_' before '" + node.toString() + "' at line " + node.getSemicolon().getLine() + ". Ignored...");
00211 } else {
00212 node.getExp().apply(this);
00213 String token = node.getId().toString().trim();
00214 if (tokenSet.contains(token)) {
00215 absFunctions.add("if (" + node.getExp().toString().trim() + ") return " + token + ";");
00216 } else {
00217 warnings.add("Invalid token '" + token + "' at line " + node.getSemicolon().getLine() + ". Ignored...");
00218 }
00219 }
00220 }
00221
00222
00223
00224
00225 public void caseAIdIdList(AIdIdList node) {
00226 TId tid = node.getId();
00227 String token = tid.toString().trim();
00228 if (tempCollection.contains(token)) {
00229 warnings.add("Duplicate occurence of token '" + token + "' at line " + tid.getLine() + ". Ignored...");
00230 } else {
00231 tempCollection.add(token);
00232 }
00233 }
00234
00235
00236
00237
00238 public void caseAIdPrimaryExp(AIdPrimaryExp node) {
00239 String n = node.getId().toString().trim();
00240 if (!n.equals(paramAbsFunction)) {
00241 errors.add("Variable '" + n + "' is undefined at line " + node.getId().getLine());
00242 }
00243 }
00244
00245
00246
00247
00248 public void caseAIdsIdList(AIdsIdList node) {
00249 node.getIdList().apply(this);
00250 TId tid = node.getId();
00251 String token = tid.toString().trim();
00252 if (tempCollection.contains(token)) {
00253 warnings.add("Duplicate occurence of token '" + token + "' at line " + tid.getLine() + ". Ignored...");
00254 } else {
00255 tempCollection.add(token);
00256 }
00257 }
00258
00259
00260
00261
00262 public void caseAIntegralType(AIntegralType node) {
00263 superTypeName = "IntegralAbstraction";
00264 type = "integral";
00265 }
00266
00267
00268
00269
00270 public void caseAOperator(AOperator node) {
00271 String op = node.getOp().toString().trim();
00272 currentOp = new Vector();
00273 opLeftRight = new int[fields.length][fields.length];
00274 opLeftResult = new int[fields.length][1 << fields.length];
00275 opRightResult = new int[fields.length][1 << fields.length];
00276 isTest = false;
00277 createPossibleArguments();
00278
00279
00280
00281
00282
00283
00284
00285
00286 {
00287 Object temp[] = node.getPattern().toArray();
00288 for (int i = 0; i < temp.length; i++) {
00289 ((PPattern) temp[i]).apply(this);
00290 }
00291 }
00292 opTable.put(op, new Object[] { opLeftResult, currentOp, opLeftRight, opRightResult });
00293 if (possibleArguments.size() > 0)
00294 warnings.add("Cases " + possibleArguments + " are not handled in " + abstractionName + "." + opNameTable.get(op));
00295 }
00296
00297
00298
00299
00300 public void caseAPatternPattern(APatternPattern node) {
00301 if (possibleArguments.size() == 0) {
00302 warnings.add("Unnecessary " + (isTest ? "test" : "operator") + " pattern '" + node.toString() + "' at line " + node.getSemicolon().getLine() + ". Ignored...");
00303 return;
00304 }
00305 tempCollection = new HashSet();
00306 node.getTokenTokenSet().apply(this);
00307 int result = 0;
00308 int lastIndex = -1;
00309 boolean useChoose = false;
00310
00311 HashSet otherToken = new HashSet();
00312 if (isTest) {
00313 boolean hasTrue = tempCollection.remove("TRUE");
00314 boolean hasFalse = tempCollection.remove("FALSE");
00315 for (Iterator i = tempCollection.iterator(); i.hasNext();) {
00316 warnings.add("Invalid token '" + i.next() + "' at line " + node.getSemicolon().getLine() + ". Ignored...");
00317 }
00318 if (hasTrue && hasFalse) {
00319 result = Abstraction.TRUE_OR_FALSE;
00320 useChoose = true;
00321
00322
00323 } else
00324 if (hasTrue) {
00325 result = Abstraction.TRUE;
00326
00327 } else
00328 if (hasFalse) {
00329 result = Abstraction.FALSE;
00330
00331 } else {
00332 warnings.add("Invalid test pattern definition (does not return TRUE/FALSE/T) at line " + node.getSemicolon().getLine() + ". Ignored...");
00333 return;
00334 }
00335 } else {
00336 int size = 0;
00337 for (Iterator i = tempCollection.iterator(); i.hasNext();) {
00338 String token = (String) i.next();
00339 int index = tokenSet.indexOf(token);
00340 if (index != -1) {
00341 result += (1 << index);
00342 lastIndex = index;
00343 size++;
00344
00345 } else {
00346 otherToken.add(token);
00347 }
00348 }
00349 if (size > 1) {
00350 useChoose = true;
00351 }
00352 }
00353 String rid = node.getRId().toString().trim();
00354 String lid = node.getLId().toString().trim();
00355 int caseNo = 0;
00356 if ("_".equals(lid)) {
00357 if ("_".equals(rid)) {
00358 new AAnyPattern(new TAny(), node.getRightarrow(), node.getTokenTokenSet(), node.getSemicolon()).apply(this);
00359 } else
00360 if (tokenSet.contains(rid)) {
00361 int index = tokenSet.indexOf(rid);
00362 boolean necessary = false;
00363 for (int i = 0; i < fields.length; i++) {
00364 if (possibleArguments.remove(fields[i] + ":" + fields[index])) {
00365 necessary = true;
00366 opLeftResult[i][result] |= (1 << index);
00367 opLeftRight[i][index] = result;
00368 opRightResult[index][result] |= (1 << i);
00369 }
00370 }
00371 if (necessary) {
00372 if (isTest) {
00373 switch (result) {
00374 case Abstraction.FALSE:
00375 currentOp.add("if (right$ == " + rid + ") return false;");
00376 break;
00377 case Abstraction.TRUE:
00378 currentOp.add("if (right$ == " + rid + ") return true;");
00379 break;
00380 case Abstraction.TRUE_OR_FALSE:
00381 currentOp.add("if (right$ == " + rid + ") return Abstraction.choose();");
00382 break;
00383 default: throw new RuntimeException();
00384 }
00385 } else {
00386 for (Iterator i = otherToken.iterator(); i.hasNext();) {
00387 warnings.add("Invalid token '" + i.next() + "' at line " + node.getSemicolon().getLine() + ". Ignored...");
00388 }
00389 if (result == 0) {
00390 warnings.add("Invalid operator pattern definition (no valid result) at line " + node.getSemicolon().getLine() + ". Ignored...");
00391 return;
00392 }
00393 if (useChoose) {
00394 currentOp.add("if (right$ == " + rid + ") return Abstraction.choose(" + getExpandedString(result) + ");");
00395 } else {
00396 currentOp.add("if (right$ == " + rid + ") return " + fields[lastIndex] + ";");
00397 }
00398 }
00399 } else {
00400 warnings.add("Unnecessary " + (isTest ? "test" : "operator") + " pattern '" + node.toString() + "' at line " + node.getSemicolon().getLine() + ". Ignored...");
00401 return;
00402 }
00403 } else {
00404 warnings.add("Invalid " + (isTest ? "test" : "operator") + " pattern definition (mixing Wild and Var) at line " + node.getSemicolon().getLine() + ". Ignored...");
00405 }
00406 } else
00407 if ("_".equals(rid)) {
00408 if (tokenSet.contains(lid)) {
00409 int index = tokenSet.indexOf(lid);
00410 boolean necessary = false;
00411 for (int i = 0; i < fields.length; i++) {
00412 if (possibleArguments.remove(fields[index] + ":" + fields[i])) {
00413 necessary = true;
00414 opLeftResult[index][result] |= (1 << i);
00415 opLeftRight[index][i] = result;
00416 opRightResult[i][result] |= (1 << index);
00417 }
00418 }
00419 if (necessary) {
00420 if (isTest) {
00421 switch (result) {
00422 case Abstraction.FALSE:
00423 currentOp.add("if (left$ == " + lid + ") return false;");
00424 break;
00425 case Abstraction.TRUE:
00426 currentOp.add("if (left$ == " + lid + ") return true;");
00427 break;
00428 case Abstraction.TRUE_OR_FALSE:
00429 currentOp.add("if (left$ == " + lid + ") return Abstraction.choose(); // [TRUE, FALSE]");
00430 break;
00431 default: throw new RuntimeException();
00432 }
00433 } else {
00434 if (useChoose) {
00435 currentOp.add("if (left$ == " + lid + ") return Abstraction.choose(" + getExpandedString(result) + ");");
00436 } else {
00437 currentOp.add("if (left$ == " + lid + ") return " + fields[lastIndex] + ";");
00438 }
00439 }
00440 } else {
00441 warnings.add("Unnecessary " + (isTest ? "test" : "operator") + " pattern '" + node.toString() + "' at line " + node.getSemicolon().getLine() + ". Ignored...");
00442 return;
00443 }
00444 } else {
00445 warnings.add("Invalid " + (isTest ? "test" : "operator") + " pattern definition (mixing Wild and Var) at line " + node.getSemicolon().getLine() + ". Ignored...");
00446 }
00447 } else
00448 if (!tokenSet.contains(lid)) {
00449 if (isTest) {
00450 warnings.add("Invalid test pattern definition (using Var) at line " + node.getSemicolon().getLine() + ". Ignored...");
00451 return;
00452 }
00453 if (!tokenSet.contains(rid)) {
00454 warnings.add("Invalid operator pattern definition (using two Vars) at line " + node.getSemicolon().getLine() + ". Ignored...");
00455 return;
00456 } else {
00457 if ((otherToken.size() == 1) && (result == 0) && (otherToken.iterator().next().equals(lid))) {
00458 int index = tokenSet.indexOf(rid);
00459 boolean necessary = false;
00460 for (int i = 0; i < fields.length; i++) {
00461 if (possibleArguments.remove(fields[i] + ":" + fields[index])) {
00462 necessary = true;
00463 opLeftResult[i][result] |= (1 << index);
00464 opLeftRight[i][index] = result;
00465 opRightResult[index][result] |= (1 << i);
00466 }
00467 }
00468 if (necessary) {
00469 currentOp.add("if (right$ == " + rid + ") return left$;");
00470 } else {
00471 warnings.add("Invalid operator pattern definition (Var declared but not used) at line " + node.getSemicolon().getLine() + ". Ignored...");
00472 return;
00473 }
00474 }
00475 }
00476 } else
00477 if (!tokenSet.contains(rid)) {
00478 if (isTest) {
00479 warnings.add("Invalid test pattern definition (using Var) at line " + node.getSemicolon().getLine() + ". Ignored...");
00480 return;
00481 }
00482 if ((otherToken.size() == 1) && (result == 0) && (otherToken.iterator().next().equals(rid))) {
00483 int index = tokenSet.indexOf(lid);
00484 boolean necessary = false;
00485 for (int i = 0; i < fields.length; i++) {
00486 if (possibleArguments.remove(fields[index] + ":" + fields[i])) {
00487 necessary = true;
00488 opLeftResult[index][result] |= (1 << i);
00489 opLeftResult[index][i] = result;
00490 opRightResult[i][result] |= (1 << index);
00491 }
00492 }
00493 if (necessary) {
00494 currentOp.add("if (left$ == " + lid + ") return right$;");
00495 } else {
00496 warnings.add("Invalid operator pattern definition (Var declared but not used) at line " + node.getSemicolon().getLine() + ". Ignored...");
00497 return;
00498 }
00499 }
00500 } else {
00501 if (possibleArguments.remove(lid + ":" + rid)) {
00502 if (isTest) {
00503 switch (result) {
00504 case Abstraction.FALSE:
00505 currentOp.add("if (left$ == " + lid + " && right$ == " + rid + ") return false;");
00506 break;
00507 case Abstraction.TRUE:
00508 currentOp.add("if (left$ == " + lid + " && right$ == " + rid + ") return true;");
00509 break;
00510 case Abstraction.TRUE_OR_FALSE:
00511 currentOp.add("if (left$ == " + lid + " && right$ == " + rid + ") return Abstraction.choose();");
00512 break;
00513 default: throw new RuntimeException();
00514 }
00515 int lidx = tokenSet.indexOf(lid);
00516 int ridx = tokenSet.indexOf(rid);
00517 opLeftResult[lidx][result] |= (1 << ridx);
00518 opLeftRight[lidx][ridx] = result;
00519 opRightResult[ridx][result] |= (1 << lidx);
00520 } else {
00521 for (Iterator i = otherToken.iterator(); i.hasNext();) {
00522 warnings.add("Invalid token '" + i.next() + "' at line " + node.getSemicolon().getLine() + ". Ignored...");
00523 }
00524 if (result == 0) {
00525 warnings.add("Invalid operator pattern definition (no valid result) at line " + node.getSemicolon().getLine() + ". Ignored...");
00526 return;
00527 }
00528 int lidx = tokenSet.indexOf(lid);
00529 int ridx = tokenSet.indexOf(rid);
00530 opLeftResult[lidx][result] |= (1 << ridx);
00531 opLeftRight[lidx][ridx] = result;
00532 opRightResult[ridx][result] |= (1 << lidx);
00533 if (useChoose) {
00534 currentOp.add("if (left$ == " + lid + " && right$ == " + rid + ") return Abstraction.choose(" + getExpandedString(result) + ");");
00535 } else {
00536 currentOp.add("if (left$ == " + lid + " && right$ == " + rid + ") return " + fields[lastIndex] + ";");
00537 }
00538 }
00539 } else {
00540 warnings.add("Unnecessary " + (isTest ? "test" : "operator") + " pattern '" + node.toString() + "' at line " + node.getSemicolon().getLine() + ". Ignored...");
00541 return;
00542 }
00543 }
00544 }
00545
00546
00547
00548
00549 public void caseARealType(ARealType node) {
00550 superTypeName = "RealAbstraction";
00551 type = "real";
00552 }
00553
00554
00555
00556
00557 public void caseATest(ATest node) {
00558 String op = node.getTOp().toString().trim();
00559 currentOp = new Vector();
00560 opLeftRight = new int[fields.length][fields.length];
00561 opLeftResult = new int[fields.length][3];
00562 opRightResult = new int[fields.length][3];
00563 isTest = true;
00564 createPossibleArguments();
00565 for (int i = 0; i < fields.length; i++) {
00566 for (int j = 0; j < fields.length; j++) {
00567 opLeftRight[i][j] = -1;
00568 }
00569 }
00570
00571 {
00572 Object temp[] = node.getPattern().toArray();
00573 for (int i = 0; i < temp.length; i++) {
00574 ((PPattern) temp[i]).apply(this);
00575 }
00576 }
00577 opTable.put(op, new Object[] {opLeftResult, currentOp, opLeftRight, opRightResult});
00578 if (possibleArguments.size() > 0)
00579 warnings.add("Cases " + possibleArguments + " are not handled in " + abstractionName + "." + opNameTable.get(op));
00580 }
00581
00582
00583
00584
00585 public void caseATokenTokenTokenSet(ATokenTokenTokenSet node) {
00586 String token = node.getId().toString().trim();
00587 if ("T".equals(token)) {
00588 if (isTest) {
00589 tempCollection.add("TRUE");
00590 tempCollection.add("FALSE");
00591 } else {
00592 for (int i = 0; i < fields.length; i++) {
00593 tempCollection.add(fields[i]);
00594 }
00595 }
00596 } else {
00597 tempCollection.add(token);
00598 }
00599 }
00600
00601
00602
00603
00604 public void caseAUnit(AUnit node) {
00605 node.getType().apply(this);
00606
00607 abstractionName = node.getId().toString().trim();
00608
00609 tempCollection = new Vector();
00610
00611 node.getTokenSet().apply(this);
00612
00613 tokenSet = (Vector) tempCollection;
00614
00615 if (node.getDefaultToken() != null) {
00616 node.getDefaultToken().apply(this);
00617 } else {
00618 errors.add("Default token is undefined");
00619 }
00620
00621 fields = new String[tokenSet.size()];
00622
00623 System.arraycopy(tokenSet.toArray(), 0, fields, 0, tokenSet.size());
00624
00625 tempCollection = new HashSet();
00626
00627 if (node.getOne2oneSet() != null)
00628 node.getOne2oneSet().apply(this);
00629
00630 one2oneSet = new HashSet();
00631
00632 for (Iterator i = tempCollection.iterator(); i.hasNext();) {
00633 String token = (String) i.next();
00634 if (tokenSet.contains(token)) {
00635 one2oneSet.add(token);
00636 } else {
00637 warnings.add("Invalid token '" + token + "' at ONE2ONE token set definition");
00638 }
00639 }
00640
00641 absFunctions = new Vector();
00642
00643 node.getAbstractFunction().apply(this);
00644
00645 opTable = new Hashtable();
00646
00647 {
00648 Object temp[] = node.getOperatorTest().toArray();
00649 for (int i = 0; i < temp.length; i++) {
00650 ((POperatorTest) temp[i]).apply(this);
00651 }
00652 }
00653 }
00654
00655
00656
00657 private void createPossibleArguments() {
00658 possibleArguments = new HashSet();
00659 for (int i = 0; i < fields.length; i++) {
00660 for (int j = 0; j < fields.length; j++) {
00661 possibleArguments.add(fields[i] + ":" + fields[j]);
00662 }
00663 }
00664 }
00665
00666
00667
00668
00669 public String generate(String packageName) {
00670 if (node != null) node.apply(this);
00671 if (errors.size() > 0) return null;
00672
00673 buffer = new StringBuffer("// This file was generated by Bandera (http://www.cis.ksu.edu/santos/bandera)." + lineSeparator);
00674
00675 if (warnings.size() > 0) {
00676 println("//");
00677 println("// WARNING:");
00678 println("// --------");
00679 for (Iterator i = warnings.iterator(); i.hasNext();) {
00680 println("// * " + i.next());
00681 }
00682 println("//");
00683 println("//");
00684 }
00685
00686 String typeName = abstractionName;
00687
00688 if (packageName != null) {
00689 if ("".equals(packageName))
00690 this.packageName = type;
00691 else
00692 this.packageName = packageName + ("." + type);
00693 println("package " + this.packageName + ";");
00694 }
00695 println("import edu.ksu.cis.bandera.abstraction.*;");
00696 println("public class " + typeName + " extends " + superTypeName + " {");
00697 println(" private static final " + typeName + " v = new " + typeName + "();");
00698
00699 for (int i = 0; i < fields.length; i++) {
00700 println(" public static final int " + fields[i] + " = " + i + ";");
00701 }
00702
00703 println(" private " + typeName + "() {");
00704 println(" }");
00705
00706 println(" public static " + typeName + " v() {");
00707 println(" return v;");
00708 println(" }");
00709
00710 println(" public static int getNumOfTokens() {");
00711 println(" return " + fields.length + ";");
00712 println(" }");
00713
00714
00715 println(" public static String getToken(int value) {");
00716 println(" switch(value) {");
00717 for (int i = 0; i < fields.length; i++) {
00718 println(" case " + fields[i] + ": return \"" + abstractionName + "." + fields[i] + "\";");
00719 }
00720 println(" }");
00721 println(" return \"" + abstractionName + ".???\";");
00722 println(" }");
00723
00724 println(" public static boolean isOne2One(int value) {");
00725 if (one2oneSet.size() > 0) {
00726 println(" switch(value) {");
00727 for (Iterator i = one2oneSet.iterator(); i.hasNext();) {
00728 println(" case " + i.next() + ": return true;");
00729 }
00730 println(" }");
00731 }
00732 println(" return false;");
00733 println(" }");
00734
00735 println(" public static int abs(" + ("integral".equals(type) ? "long " : "double ") + paramAbsFunction + ") {");
00736 for (Iterator i = absFunctions.iterator(); i.hasNext();) {
00737 println(" " + i.next());
00738 }
00739 println(" throw new RuntimeException(\"" + typeName + " cannot abstract value '\" + " + paramAbsFunction + " + \"'\");");
00740 println(" }");
00741
00742 generateOperators();
00743
00744 generateBASL();
00745
00746 println(" public static String getName() {");
00747 println(" return \"" + abstractionName + "\";");
00748 println(" }");
00749 println(" public String toString() {");
00750 println(" return getName();");
00751 println(" }");
00752 println("}");
00753
00754 return buffer.toString();
00755 }
00756
00757
00758
00759 private void generateBASL() {
00760 println(" public static String getBASLRepresentation() {");
00761 println(" return");
00762 try {
00763 LineNumberReader r = new LineNumberReader(new StringReader(AbstractionPrinter.print((Start) node, true)));
00764 String line = r.readLine();
00765 println(" \"" + line + "\\n\"");
00766 while ((line = r.readLine()) != null) {
00767 println(" + \"" + line + "\\n\"");
00768 }
00769 } catch (Exception e) {
00770 }
00771 println(" ;");
00772 println(" }");
00773 }
00774
00775
00776
00777 private void generateOperators() {
00778 String typeName = abstractionName;
00779
00780 for (Enumeration e = opNameTable.keys(); e.hasMoreElements();) {
00781 String op = (String) e.nextElement();
00782 String opName = (String) opNameTable.get(op);
00783 boolean isTest = (op.length() > 1) || ">".equals(op) || "<".equals(op);
00784 Object[] o = (Object[]) opTable.get(op);
00785 if (o == null) continue;
00786 opLeftResult = (int[][]) o[0];
00787 currentOp = (Vector) o[1];
00788 opLeftRight = (int[][]) o[2];
00789 opRightResult = (int[][]) o[3];
00790
00791 if (isTest) {
00792 println(" public static boolean " + opName + "(int left$, int right$) {");
00793 } else {
00794 println(" public static int " + opName + "(int left$, int right$) {");
00795 }
00796 for (Iterator j = currentOp.iterator(); j.hasNext();) {
00797 println(" " + j.next());
00798 }
00799 println(" throw new RuntimeException(\"" + typeName + "." + opName + "(\" + left$ + \", \" + right$ + \") is undefined\");");
00800 println(" }");
00801
00802 if (isTest) {
00803 println(" private static byte " + opName + "NoChoose(int left, int right) {");
00804 println(" byte result = -1;");
00805 } else {
00806 println(" private static int " + opName + "NoChoose(int left, int right) {");
00807 println(" int result = 0;");
00808 }
00809 println(" switch (left) {");
00810 for (int i = 0; i < fields.length; i++) {
00811 println(" case " + i + ":");
00812 println(" switch (right) {");
00813 for (int j = 0; j < fields.length; j++) {
00814 if ((!isTest && opLeftRight[i][j] != 0) || (isTest && opLeftRight[i][j] != -1)) {
00815 println(" case " + j + ":");
00816 println(" result = " + opLeftRight[i][j] + ";");
00817 println(" break;");
00818 }
00819 }
00820 println(" }");
00821 println(" break;");
00822 }
00823 println(" }");
00824 if (isTest) {
00825 println(" if (result == -1) throw new RuntimeException(\"" + typeName + "." + opName + "NoChoose(\" + left + \", \" + right + \") is undefined\");");
00826 } else {
00827 println(" if (result == 0) throw new RuntimeException(\"" + typeName + "." + opName + "NoChoose(\" + left + \", \" + right + \") is undefined\");");
00828 }
00829 println(" return result;");
00830 println(" }");
00831
00832
00833 if (isTest) {
00834 println(" public static byte " + opName + "Set(int leftTokens, int rightTokens) {");
00835 println(" byte result = -1;");
00836 } else {
00837 println(" public static int " + opName + "Set(int leftTokens, int rightTokens) {");
00838 println(" int result = -1;");
00839 }
00840 println(" for (int left = 0; (1 << left) <= leftTokens; left++) {");
00841 println(" if ((leftTokens & (1 << left)) == 0) continue;");
00842 println(" for (int right = 0; (1 << right) <= rightTokens; right++) {");
00843 println(" if ((rightTokens & (1 << right)) != 0) {");
00844 println(" if (result == -1) result = " + opName + "NoChoose(left, right);");
00845 if (isTest) {
00846 println(" else result = Abstraction.meetTest(result, " + opName + "NoChoose(left, right));");
00847 } else {
00848 println(" else result = Abstraction.meetArith(result, " + opName + "NoChoose(left, right));");
00849 }
00850 println(" }");
00851 println(" }");
00852 println(" }");
00853 println(" return result;");
00854 println(" }");
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899 }
00900 }
00901
00902
00903
00904 private void generateOperatorSetTable() {
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943 }
00944
00945
00946
00947 private void generateOperatorsTable() {
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979 }
00980
00981
00982
00983
00984 public String getAbstractionFullyQualifiedName() {
00985 return packageName + "." + getAbstractionName();
00986 }
00987
00988
00989
00990
00991 public String getAbstractionName() {
00992 return abstractionName;
00993 }
00994
00995
00996
00997
00998 public String getAbstractionType() {
00999 return type;
01000 }
01001
01002
01003
01004
01005 public Vector getErrors() {
01006 return errors;
01007 }
01008
01009
01010
01011
01012
01013 private String getExpandedString(int values) {
01014 HashSet set = new HashSet();
01015 for (int l = 0, mask = 1; l < fields.length; l++, mask <<= 1) {
01016 if ((values & mask) == mask) {
01017 set.add(fields[l]);
01018 }
01019 }
01020 switch (set.size()) {
01021 case 0:
01022 return "NOTHING";
01023 case 1:
01024 return "(1 << " + set.iterator().next() + ")";
01025 default:
01026 Iterator i = set.iterator();
01027 String result = (String) ("(1 << " + i.next() + ")");
01028 while (i.hasNext()) result += (" | (1 << " + i.next() + ")");
01029 return result;
01030 }
01031 }
01032
01033
01034
01035
01036 public Start getNode() {
01037 return (Start) node;
01038 }
01039
01040
01041
01042
01043 public Vector getWarnings() {
01044 return warnings;
01045 }
01046
01047
01048
01049
01050 private void print(String s) {
01051 buffer.append(s);
01052 }
01053
01054
01055
01056
01057 private void println(String s) {
01058 buffer.append(s + lineSeparator);
01059 }
01060 }