0001: /*
0002: * UnparseVisitor.java
0003: *
0004: * Copyright (c) 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
0005: *
0006: * See the file "LICENSE.txt" for information on usage and redistribution
0007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
0008: */
0009: package org.pnuts.lang;
0010:
0011: import pnuts.lang.Context;
0012: import pnuts.lang.SimpleNode;
0013: import pnuts.lang.Visitor;
0014: import pnuts.lang.PnutsParserTreeConstants;
0015:
0016: /**
0017: * This class is used to retrieve a textual representation of a script from
0018: * parsed tree.
0019: */
0020: public class UnparseVisitor implements Visitor {
0021:
0022: private StringBuffer sbuf;
0023: private boolean escape;
0024:
0025: public UnparseVisitor(StringBuffer sbuf) {
0026: this (sbuf, false);
0027: }
0028:
0029: public UnparseVisitor(StringBuffer sbuf, boolean escape) {
0030: this .sbuf = sbuf;
0031: this .escape = escape;
0032: }
0033:
0034: void operand(SimpleNode node, int idx) {
0035: int id = node.jjtGetChild(idx).id;
0036: if (id == PnutsParserTreeConstants.JJTIDNODE
0037: || id == PnutsParserTreeConstants.JJTINDEXNODE
0038: || id == PnutsParserTreeConstants.JJTRANGENODE
0039: || id == PnutsParserTreeConstants.JJTSTATICMETHODNODE
0040: || id == PnutsParserTreeConstants.JJTSTATICMEMBERNODE
0041: || id == PnutsParserTreeConstants.JJTAPPLICATIONNODE
0042: || id == PnutsParserTreeConstants.JJTMETHODNODE
0043: || id == PnutsParserTreeConstants.JJTMEMBERNODE
0044: || id == PnutsParserTreeConstants.JJTCASTEXPRESSION
0045: || id == PnutsParserTreeConstants.JJTINTEGERNODE
0046: || id == PnutsParserTreeConstants.JJTFLOATINGNODE
0047: || id == PnutsParserTreeConstants.JJTCHARACTERNODE
0048: || id == PnutsParserTreeConstants.JJTSTRINGNODE
0049: || id == PnutsParserTreeConstants.JJTTRUENODE
0050: || id == PnutsParserTreeConstants.JJTFALSENODE
0051: || id == PnutsParserTreeConstants.JJTNULLNODE) {
0052: accept(node, idx);
0053: } else if (id == PnutsParserTreeConstants.JJTMULTIASSIGNLHS) {
0054: paramList(node.jjtGetChild(idx));
0055: } else {
0056: sbuf.append('(');
0057: accept(node, idx);
0058: sbuf.append(')');
0059: }
0060: }
0061:
0062: Object binary(SimpleNode node, String operator) {
0063: operand(node, 0);
0064: sbuf.append(' ');
0065: sbuf.append(operator);
0066: sbuf.append(' ');
0067: operand(node, 1);
0068: return null;
0069: }
0070:
0071: public Object startSet(SimpleNode node, Context context) {
0072: expressionList(node, context, '\n');
0073: return null;
0074: }
0075:
0076: public Object start(SimpleNode node, Context context) {
0077: node.jjtGetChild(0).accept(this , context);
0078: return null;
0079: }
0080:
0081: public Object expressionList(SimpleNode node, Context context) {
0082: expressionList(node, context, ';');
0083: return null;
0084: }
0085:
0086: public Object expressionList(SimpleNode node, Context context,
0087: char delimiter) {
0088: int num = node.jjtGetNumChildren();
0089: if (num > 0) {
0090: accept(node, 0);
0091: for (int i = 1; i < num; i++) {
0092: sbuf.append(delimiter);
0093: accept(node, i);
0094: }
0095: }
0096: return null;
0097: }
0098:
0099: static String strip(String name) {
0100: if (name == null) {
0101: return null;
0102: }
0103: int idx = name.indexOf('!');
0104: if (idx < 0) {
0105: return name;
0106: } else if (idx == 0) {
0107: return null;
0108: } else {
0109: return name.substring(0, idx);
0110: }
0111: }
0112:
0113: public Object idNode(SimpleNode node, Context context) {
0114: String s = strip(node.str);
0115: if (s == null) {
0116: return null;
0117: }
0118: sbuf.append(s);
0119: int dim = node.jjtGetNumChildren();
0120: for (int i = 0; i < dim; i++) {
0121: sbuf.append("[]");
0122: }
0123: return null;
0124: }
0125:
0126: public Object global(SimpleNode node, Context context) {
0127: sbuf.append("::");
0128: sbuf.append(node.str);
0129: return null;
0130: }
0131:
0132: public Object className(SimpleNode node, Context context) {
0133: sbuf.append(node.jjtGetChild(0).str);
0134: for (int i = 1; i < node.jjtGetNumChildren(); i++) {
0135: sbuf.append('.');
0136: sbuf.append(node.jjtGetChild(i).str);
0137: }
0138: return null;
0139: }
0140:
0141: public Object arrayType(SimpleNode node, Context context) {
0142: accept(node, 0);
0143: sbuf.append("[]");
0144: return null;
0145: }
0146:
0147: public Object listElements(SimpleNode node, Context context) {
0148: return listElements(node, context, "[", "]");
0149: }
0150:
0151: public Object mapNode(SimpleNode node, Context context) {
0152: sbuf.append('{');
0153: int n = node.jjtGetNumChildren();
0154: if (n > 0) {
0155: SimpleNode c = node.jjtGetChild(0);
0156: accept(c, 0);
0157: sbuf.append(" => ");
0158: accept(c, 1);
0159: }
0160: for (int i = 1; i < n; i++) {
0161: sbuf.append(", ");
0162: SimpleNode c = node.jjtGetChild(i);
0163: accept(c, 0);
0164: sbuf.append(" => ");
0165: accept(c, 1);
0166: }
0167: sbuf.append('}');
0168: return null;
0169: }
0170:
0171: public Object listElements(SimpleNode node, Context context,
0172: String d1, String d2) {
0173: if (d1 != null) {
0174: sbuf.append(d1);
0175: }
0176: int n = node.jjtGetNumChildren();
0177: if (n > 0) {
0178: accept(node, 0);
0179: for (int i = 1; i < n; i++) {
0180: sbuf.append(", ");
0181: accept(node, i);
0182: }
0183: }
0184: if (d2 != null) {
0185: sbuf.append(d2);
0186: }
0187: return null;
0188: }
0189:
0190: void paramList(SimpleNode args) {
0191: int nargs = args.jjtGetNumChildren();
0192: if (nargs > 0) {
0193: sbuf.append(strip(args.jjtGetChild(0).str));
0194: }
0195: for (int i = 1; i < nargs; i++) {
0196: sbuf.append(", ");
0197: sbuf.append(strip(args.jjtGetChild(i).str));
0198: }
0199: }
0200:
0201: public Object castExpression(SimpleNode node, Context context) {
0202: int n = node.jjtGetNumChildren();
0203: if (n == 2) {
0204: sbuf.append('(');
0205: SimpleNode target = (SimpleNode) node.jjtGetChild(1);
0206: int id = target.id;
0207: if (id == PnutsParserTreeConstants.JJTIDNODE
0208: || id == PnutsParserTreeConstants.JJTINDEXNODE
0209: || id == PnutsParserTreeConstants.JJTRANGENODE
0210: || id == PnutsParserTreeConstants.JJTSTATICMETHODNODE
0211: || id == PnutsParserTreeConstants.JJTSTATICMEMBERNODE
0212: || id == PnutsParserTreeConstants.JJTAPPLICATIONNODE
0213: || id == PnutsParserTreeConstants.JJTMETHODNODE
0214: || id == PnutsParserTreeConstants.JJTMEMBERNODE
0215: || id == PnutsParserTreeConstants.JJTCASTEXPRESSION
0216: || id == PnutsParserTreeConstants.JJTINTEGERNODE
0217: || id == PnutsParserTreeConstants.JJTFLOATINGNODE
0218: || id == PnutsParserTreeConstants.JJTCHARACTERNODE
0219: || id == PnutsParserTreeConstants.JJTSTRINGNODE
0220: || id == PnutsParserTreeConstants.JJTTRUENODE
0221: || id == PnutsParserTreeConstants.JJTFALSENODE
0222: || id == PnutsParserTreeConstants.JJTNULLNODE) {
0223: type(node.jjtGetChild(0));
0224: sbuf.append(')');
0225: target.accept(this , context);
0226: } else {
0227: type(node.jjtGetChild(0));
0228: sbuf.append(")(");
0229: target.accept(this , context);
0230: sbuf.append(')');
0231: }
0232: } else {
0233: accept(node, 0);
0234: }
0235: return null;
0236: }
0237:
0238: public Object classNode(SimpleNode node, Context context) {
0239: sbuf.append("class");
0240: int n = node.jjtGetNumChildren();
0241: if (node.str != null) {
0242: sbuf.append(' ');
0243: sbuf.append(node.str);
0244: }
0245: int dim = 0;
0246: for (int i = 0; i < n; i++) {
0247: SimpleNode ch = (SimpleNode) node.jjtGetChild(i);
0248: if (ch.id == PnutsParserTreeConstants.JJTPACKAGE) {
0249: sbuf.append('.');
0250: sbuf.append(ch.str);
0251: } else if (ch.id == PnutsParserTreeConstants.JJTARRAYTYPE) {
0252: dim++;
0253: }
0254: }
0255: for (int i = 0; i < dim; i++) {
0256: sbuf.append("[]");
0257: }
0258: return null;
0259: }
0260:
0261: public Object newNode(SimpleNode node, Context context) {
0262: int n = node.jjtGetNumChildren();
0263: SimpleNode n0 = node.jjtGetChild(0);
0264:
0265: sbuf.append("new ");
0266:
0267: if (n == 3
0268: && node.jjtGetChild(2).id == PnutsParserTreeConstants.JJTCLASSDEFBODY) { // subclass
0269: type(n0);
0270: listElements(node.jjtGetChild(1), context, "(", ")");
0271: SimpleNode classDefBody = node.jjtGetChild(2);
0272: classDefBody.accept(this , context);
0273:
0274: } else if (n0.id == PnutsParserTreeConstants.JJTINDEXNODE) {
0275: SimpleNode n1 = n0;
0276: while (n1.id == PnutsParserTreeConstants.JJTINDEXNODE) {
0277: n1 = n1.jjtGetChild(0);
0278: }
0279: type(n1);
0280: n1 = n1.jjtGetParent();
0281: while (n1 != n0) {
0282: sbuf.append('[');
0283: accept(n1, 1);
0284: sbuf.append(']');
0285: n1 = n1.jjtGetParent();
0286: }
0287: sbuf.append('[');
0288: accept(n1, 1);
0289: sbuf.append(']');
0290: } else if (n0.id == PnutsParserTreeConstants.JJTARRAYTYPE) {
0291: arrayType(n0, context);
0292:
0293: } else if (n0.id == PnutsParserTreeConstants.JJTARRAYNODE) {
0294: type(n0.jjtGetChild(0));
0295: listElements(n0.jjtGetChild(1), context, "{", "}");
0296: } else {
0297: type(node.jjtGetChild(0));
0298: listElements(node.jjtGetChild(1), context, "(", ")");
0299: }
0300: return null;
0301: }
0302:
0303: public Object classScript(SimpleNode node, Context context) {
0304: return null;
0305: }
0306:
0307: public Object classDef(SimpleNode node, Context context) {
0308: sbuf.append("class ");
0309: className(node.jjtGetChild(0), context);
0310: SimpleNode ext = node.jjtGetChild(1);
0311: SimpleNode impl = node.jjtGetChild(2);
0312: SimpleNode classDefBody = node.jjtGetChild(3);
0313: if (ext.jjtGetNumChildren() > 0) {
0314: sbuf.append(" extends ");
0315: className(ext.jjtGetChild(0), context);
0316: }
0317: if (impl.jjtGetNumChildren() > 0) {
0318: sbuf.append(" implements ");
0319: int num = impl.jjtGetNumChildren();
0320: if (num > 0) {
0321: className(impl.jjtGetChild(0), context);
0322: }
0323: for (int i = 1; i < num; i++) {
0324: sbuf.append(", ");
0325: className(impl.jjtGetChild(i), context);
0326: }
0327: }
0328: classDefBody.accept(this , context);
0329: return null;
0330: }
0331:
0332: public Object classDefBody(SimpleNode node, Context context) {
0333: sbuf.append("{");
0334: int n = node.jjtGetNumChildren();
0335: for (int i = 0; i < n; i++) {
0336: sbuf.append("\n");
0337: SimpleNode c = node.jjtGetChild(i);
0338: if (c.id == PnutsParserTreeConstants.JJTFIELDDEF) {
0339: int j = 0;
0340: SimpleNode c2 = c.jjtGetChild(j);
0341: if (c2.id == PnutsParserTreeConstants.JJTCLASSNAME) {
0342: type(c2);
0343: sbuf.append(" ");
0344: j++;
0345: }
0346: sbuf.append(c.str);
0347: if (c.jjtGetNumChildren() > j) {
0348: SimpleNode c3 = c.jjtGetChild(j);
0349: sbuf.append(" = ");
0350: c3.accept(this , context);
0351: }
0352: } else {
0353: methodDef(c, context);
0354: }
0355: }
0356: sbuf.append("\n}");
0357: return null;
0358: }
0359:
0360: public Object methodDef(SimpleNode node, Context context) {
0361: int n = node.jjtGetNumChildren();
0362: if (n == 2) {
0363: sbuf.append(node.str);
0364: typedParamList(node.jjtGetChild(0), context);
0365: node.jjtGetChild(1).accept(this , context);
0366: } else if (n == 3) {
0367: type(node.jjtGetChild(0));
0368: typedParamList(node.jjtGetChild(1), context);
0369: node.jjtGetChild(2).accept(this , context);
0370: } else {
0371: throw new InternalError();
0372: }
0373: return null;
0374: }
0375:
0376: public Object typedParamList(SimpleNode node, Context context) {
0377: sbuf.append("(");
0378: int n = node.jjtGetNumChildren();
0379: if (n > 0) {
0380: SimpleNode p = node.jjtGetChild(0);
0381: typedParam(p, context);
0382: }
0383: for (int i = 1; i < n; i++) {
0384: sbuf.append(",");
0385: SimpleNode p = node.jjtGetChild(i);
0386: typedParam(p, context);
0387: }
0388: sbuf.append(")");
0389: return null;
0390: }
0391:
0392: public Object typedParam(SimpleNode node, Context context) {
0393: int n = node.jjtGetNumChildren();
0394: if (n == 2) {
0395: SimpleNode t = node.jjtGetChild(0);
0396: type(t);
0397: sbuf.append(' ');
0398: sbuf.append(node.jjtGetChild(1).str);
0399: } else if (n == 1) {
0400: sbuf.append(node.jjtGetChild(0).str);
0401: } else {
0402: throw new InternalError();
0403: }
0404: return null;
0405: }
0406:
0407: public Object primitiveNode(SimpleNode node, Context context) {
0408: sbuf.append(node.str);
0409: return null;
0410: }
0411:
0412: public Object packageNode(SimpleNode node, Context context) {
0413: int n = node.jjtGetNumChildren();
0414: sbuf.append("package");
0415: if (node.str != null) {
0416: sbuf.append("(");
0417: if (n > 0) {
0418: node.jjtGetChild(0).accept(this , context);
0419: }
0420: } else {
0421: sbuf.append(" ");
0422: SimpleNode p0 = node.jjtGetChild(0);
0423: sbuf.append(p0.str);
0424: for (int i = 1; i < n; i++) {
0425: sbuf.append(".");
0426: sbuf.append(node.jjtGetChild(i).str);
0427: }
0428: }
0429: if (node.str != null) {
0430: sbuf.append(")");
0431: } else {
0432: sbuf.append("\n");
0433: }
0434: return null;
0435: }
0436:
0437: public Object importNode(SimpleNode node, Context context) {
0438: sbuf.append("import ");
0439: if ("static".equals(node.info)) {
0440: sbuf.append("static ");
0441: }
0442: int n = node.jjtGetNumChildren();
0443: if (n == 0 && "*".equals(node.str)) {
0444: sbuf.append('*');
0445: return null;
0446: } else if ("(".equals(node.str)) {
0447: sbuf.append('(');
0448: if (n == 1) {
0449: accept(node, 0);
0450: }
0451: sbuf.append(')');
0452: return null;
0453: } else {
0454: sbuf.append(node.jjtGetChild(0).str);
0455: for (int i = 1; i < n; i++) {
0456: sbuf.append('.');
0457: sbuf.append(node.jjtGetChild(i).str);
0458: }
0459: if ("*".equals(node.str)) {
0460: sbuf.append(".*");
0461: }
0462: }
0463: return null;
0464: }
0465:
0466: public Object rangeNode(SimpleNode node, Context context) {
0467: if (node.jjtGetNumChildren() == 3) {
0468: accept(node, 0);
0469: sbuf.append('[');
0470: accept(node, 1);
0471: sbuf.append("..");
0472: accept(node, 2);
0473: sbuf.append(']');
0474: } else {
0475: accept(node, 0);
0476: sbuf.append('[');
0477: accept(node, 1);
0478: sbuf.append("..]");
0479: }
0480: return null;
0481: }
0482:
0483: public Object indexNode(SimpleNode node, Context context) {
0484: accept(node, 0);
0485: sbuf.append('[');
0486: accept(node, 1);
0487: sbuf.append(']');
0488: return null;
0489: }
0490:
0491: public Object methodNode(SimpleNode node, Context context) {
0492: int id = ((SimpleNode) node.jjtGetChild(0)).id;
0493: if (id == PnutsParserTreeConstants.JJTINTEGERNODE
0494: || id == PnutsParserTreeConstants.JJTFLOATINGNODE) {
0495: sbuf.append('(');
0496: accept(node, 0);
0497: sbuf.append(')');
0498: } else {
0499: accept(node, 0);
0500: }
0501: sbuf.append('.');
0502: sbuf.append(node.str);
0503: listElements(node.jjtGetChild(1), context, "(", ")");
0504: return null;
0505: }
0506:
0507: public Object staticMethodNode(SimpleNode node, Context context) {
0508: accept(node, 0);
0509: sbuf.append("::");
0510: sbuf.append(node.str);
0511: listElements(node.jjtGetChild(1), context, "(", ")");
0512: return null;
0513: }
0514:
0515: public Object memberNode(SimpleNode node, Context context) {
0516: int id = ((SimpleNode) node.jjtGetChild(0)).id;
0517: if (id == PnutsParserTreeConstants.JJTINTEGERNODE
0518: || id == PnutsParserTreeConstants.JJTFLOATINGNODE) {
0519: sbuf.append('(');
0520: accept(node, 0);
0521: sbuf.append(')');
0522: } else {
0523: accept(node, 0);
0524: }
0525: sbuf.append('.');
0526: sbuf.append(node.str);
0527: return null;
0528: }
0529:
0530: public Object staticMemberNode(SimpleNode node, Context context) {
0531: accept(node, 0);
0532: sbuf.append("::");
0533: sbuf.append(node.str);
0534: return null;
0535: }
0536:
0537: public Object applicationNode(SimpleNode node, Context context) {
0538: SimpleNode n0 = node.jjtGetChild(0);
0539: if (n0.str != null && n0.str.startsWith("!<closure")) {
0540: sbuf.append("yield ");
0541: listElements(node.jjtGetChild(1), context, "", "");
0542: } else {
0543: accept(node, 0);
0544: listElements(node.jjtGetChild(1), context, "(", ")");
0545: }
0546: return null;
0547: }
0548:
0549: public Object integerNode(SimpleNode node, Context context) {
0550: sbuf.append(node.str);
0551: return null;
0552: }
0553:
0554: public Object floatingNode(SimpleNode node, Context context) {
0555: sbuf.append(node.str);
0556: return null;
0557: }
0558:
0559: public Object characterNode(SimpleNode node, Context context) {
0560: sbuf.append(node.str);
0561: return null;
0562: }
0563:
0564: String unparseString(String value, boolean escape) {
0565: char c[] = value.toCharArray();
0566: for (int i = 0; i < c.length; i++) {
0567: if (c[i] == '"') {
0568: sbuf.append("\\\"");
0569: } else if (c[i] == '\\') {
0570: sbuf.append("\\\\");
0571: } else if (c[i] == '\n') {
0572: sbuf.append("\\n");
0573: } else if (c[i] == '\t') {
0574: sbuf.append("\\t");
0575: } else if (c[i] == '\r') {
0576: sbuf.append("\\r");
0577: } else if (c[i] == '\f') {
0578: sbuf.append("\\f");
0579: } else if (c[i] == '\b') {
0580: sbuf.append("\\b");
0581: } else if (c[i] == '\0') {
0582: sbuf.append("\\0");
0583: } else {
0584: sbuf.append(c[i]);
0585: }
0586: }
0587: return null;
0588: }
0589:
0590: public Object stringNode(SimpleNode node, Context context) {
0591: if (escape) {
0592: sbuf.append('\\');
0593: }
0594: sbuf.append('"');
0595: if (node.str != null) {
0596: unparseString(node.str, escape);
0597: } else {
0598: int n = node.jjtGetNumChildren();
0599: for (int i = 0; i < n; i++) {
0600: SimpleNode c = node.jjtGetChild(i);
0601: if (c.id == PnutsParserTreeConstants.JJTSTRINGNODE) {
0602: unparseString(c.str, escape);
0603: } else {
0604: sbuf.append(escape ? "\\\\(" : "\\(");
0605: c.accept(this , context);
0606: sbuf.append(escape ? "\\\\)" : "\\)");
0607: }
0608: }
0609: }
0610: if (escape) {
0611: sbuf.append('\\');
0612: }
0613: sbuf.append('"');
0614: return null;
0615: }
0616:
0617: public Object trueNode(SimpleNode node, Context context) {
0618: sbuf.append("true");
0619: return null;
0620: }
0621:
0622: public Object falseNode(SimpleNode node, Context context) {
0623: sbuf.append("false");
0624: return null;
0625: }
0626:
0627: public Object nullNode(SimpleNode node, Context context) {
0628: sbuf.append("null");
0629: return null;
0630: }
0631:
0632: public Object assignment(SimpleNode node, Context context) {
0633: return binary(node, "=");
0634: }
0635:
0636: public Object assignmentTA(SimpleNode node, Context context) {
0637: return binary(node, "*=");
0638: }
0639:
0640: public Object assignmentMA(SimpleNode node, Context context) {
0641: return binary(node, "%=");
0642: }
0643:
0644: public Object assignmentDA(SimpleNode node, Context context) {
0645: return binary(node, "/=");
0646: }
0647:
0648: public Object assignmentPA(SimpleNode node, Context context) {
0649: return binary(node, "+=");
0650: }
0651:
0652: public Object assignmentSA(SimpleNode node, Context context) {
0653: return binary(node, "-=");
0654: }
0655:
0656: public Object assignmentLA(SimpleNode node, Context context) {
0657: return binary(node, "<<=");
0658: }
0659:
0660: public Object assignmentRA(SimpleNode node, Context context) {
0661: return binary(node, ">>=");
0662: }
0663:
0664: public Object assignmentRAA(SimpleNode node, Context context) {
0665: return binary(node, ">>>=");
0666: }
0667:
0668: public Object assignmentAA(SimpleNode node, Context context) {
0669: return binary(node, "&=");
0670: }
0671:
0672: public Object assignmentEA(SimpleNode node, Context context) {
0673: return binary(node, "^=");
0674: }
0675:
0676: public Object assignmentOA(SimpleNode node, Context context) {
0677: return binary(node, "|=");
0678: }
0679:
0680: public Object logAndNode(SimpleNode node, Context context) {
0681: return binary(node, "&&");
0682: }
0683:
0684: public Object logOrNode(SimpleNode node, Context context) {
0685: return binary(node, "||");
0686: }
0687:
0688: public Object logNotNode(SimpleNode node, Context context) {
0689: sbuf.append('!');
0690: operand(node, 0);
0691: return null;
0692: }
0693:
0694: public Object orNode(SimpleNode node, Context context) {
0695: return binary(node, "|");
0696: }
0697:
0698: public Object xorNode(SimpleNode node, Context context) {
0699: return binary(node, "^");
0700: }
0701:
0702: public Object andNode(SimpleNode node, Context context) {
0703: return binary(node, "&");
0704: }
0705:
0706: public Object equalNode(SimpleNode node, Context context) {
0707: return binary(node, "==");
0708: }
0709:
0710: public Object notEqNode(SimpleNode node, Context context) {
0711: return binary(node, "!=");
0712: }
0713:
0714: void type(SimpleNode node) {
0715: int dim = 0;
0716: while (node.id == PnutsParserTreeConstants.JJTARRAYTYPE) {
0717: dim++;
0718: node = node.jjtGetChild(0);
0719: }
0720: SimpleNode ch = (SimpleNode) node.jjtGetChild(0);
0721: sbuf.append(ch.str);
0722:
0723: int n = node.jjtGetNumChildren();
0724: for (int i = 1; i < n; i++) {
0725: ch = (SimpleNode) node.jjtGetChild(i);
0726: if (ch.id == PnutsParserTreeConstants.JJTPACKAGE) {
0727: sbuf.append('.');
0728: sbuf.append(ch.str);
0729: }
0730: }
0731: for (int i = 0; i < dim; i++) {
0732: sbuf.append("[]");
0733: }
0734: }
0735:
0736: public Object instanceof Expression(SimpleNode node, Context context) {
0737: accept(node, 0);
0738: sbuf.append(" instanceof ");
0739: type(node.jjtGetChild(1));
0740: return null;
0741: }
0742:
0743: public Object ltNode(SimpleNode node, Context context) {
0744: return binary(node, "<");
0745: }
0746:
0747: public Object gtNode(SimpleNode node, Context context) {
0748: return binary(node, ">");
0749: }
0750:
0751: public Object leNode(SimpleNode node, Context context) {
0752: return binary(node, "<=");
0753: }
0754:
0755: public Object geNode(SimpleNode node, Context context) {
0756: return binary(node, ">=");
0757: }
0758:
0759: public Object shiftLeftNode(SimpleNode node, Context context) {
0760: return binary(node, "<<");
0761: }
0762:
0763: public Object shiftRightNode(SimpleNode node, Context context) {
0764: return binary(node, ">>");
0765: }
0766:
0767: public Object shiftArithmeticNode(SimpleNode node, Context context) {
0768: return binary(node, ">>>");
0769: }
0770:
0771: public Object addNode(SimpleNode node, Context context) {
0772: return binary(node, "+");
0773: }
0774:
0775: public Object subtractNode(SimpleNode node, Context context) {
0776: return binary(node, "-");
0777: }
0778:
0779: public Object multNode(SimpleNode node, Context context) {
0780: return binary(node, "*");
0781: }
0782:
0783: public Object divideNode(SimpleNode node, Context context) {
0784: return binary(node, "/");
0785: }
0786:
0787: public Object modNode(SimpleNode node, Context context) {
0788: return binary(node, "%");
0789: }
0790:
0791: public Object negativeNode(SimpleNode node, Context context) {
0792: sbuf.append('-');
0793: operand(node, 0);
0794: return null;
0795: }
0796:
0797: public Object preIncrNode(SimpleNode node, Context context) {
0798: sbuf.append("++");
0799: operand(node, 0);
0800: return null;
0801: }
0802:
0803: public Object preDecrNode(SimpleNode node, Context context) {
0804: sbuf.append("--");
0805: operand(node, 0);
0806: return null;
0807: }
0808:
0809: public Object postIncrNode(SimpleNode node, Context context) {
0810: operand(node, 0);
0811: sbuf.append("++");
0812: return null;
0813: }
0814:
0815: public Object postDecrNode(SimpleNode node, Context context) {
0816: operand(node, 0);
0817: sbuf.append("--");
0818: return null;
0819: }
0820:
0821: public Object notNode(SimpleNode node, Context context) {
0822: sbuf.append('~');
0823: operand(node, 0);
0824: return null;
0825: }
0826:
0827: public Object continueNode(SimpleNode node, Context context) {
0828: sbuf.append("continue");
0829: return null;
0830: }
0831:
0832: public Object breakNode(SimpleNode node, Context context) {
0833: sbuf.append("break");
0834: if (node.jjtGetNumChildren() > 0) {
0835: accept(node, 0);
0836: }
0837: return null;
0838: }
0839:
0840: public Object returnNode(SimpleNode node, Context context) {
0841: sbuf.append("return");
0842: int n = node.jjtGetNumChildren();
0843: if (n == 1) {
0844: sbuf.append(' ');
0845: accept(node, 0);
0846: }
0847: return null;
0848: }
0849:
0850: public Object yieldNode(SimpleNode node, Context context) {
0851: sbuf.append("yield");
0852: int n = node.jjtGetNumChildren();
0853: if (n == 1) {
0854: sbuf.append(' ');
0855: accept(node, 0);
0856: }
0857: return null;
0858: }
0859:
0860: public Object catchNode(SimpleNode node, Context context) {
0861: int n = node.jjtGetNumChildren();
0862: if (n == 0) {
0863: sbuf.append("catch");
0864: return null;
0865: }
0866: sbuf.append("catch");
0867: sbuf.append('(');
0868: accept(node, 0);
0869: sbuf.append(", ");
0870: accept(node, 1);
0871: sbuf.append(')');
0872: return null;
0873: }
0874:
0875: public Object throwNode(SimpleNode node, Context context) {
0876: int n = node.jjtGetNumChildren();
0877: if (n == 0) {
0878: sbuf.append("throw");
0879: } else {
0880: sbuf.append("throw ");
0881: accept(node, 0);
0882: }
0883: return null;
0884: }
0885:
0886: public Object finallyNode(SimpleNode node, Context context) {
0887: int n = node.jjtGetNumChildren();
0888: if (n == 0) {
0889: sbuf.append("finally");
0890: return null;
0891: }
0892: sbuf.append("finally(");
0893: if (n == 1) {
0894: accept(node, 0);
0895: sbuf.append(')');
0896: } else if (n == 2) {
0897: accept(node, 0);
0898: sbuf.append(", ");
0899: accept(node, 1);
0900: sbuf.append(')');
0901: }
0902: return null;
0903: }
0904:
0905: private static String indent = " ";
0906:
0907: private int nest = 0;
0908:
0909: public Object tryStatement(SimpleNode node, Context context) {
0910: sbuf.append("try ");
0911: accept(node, 0);
0912:
0913: int n = node.jjtGetNumChildren();
0914: for (int i = 1; i < n; i++) {
0915: SimpleNode c = node.jjtGetChild(i);
0916: if (c.id == PnutsParserTreeConstants.JJTFINALLYBLOCK) {
0917: sbuf.append(" finally ");
0918: accept(c, 0);
0919: break;
0920: } else if (c.id == PnutsParserTreeConstants.JJTCATCHBLOCK) {
0921: sbuf.append(" catch (");
0922: SimpleNode type = c.jjtGetChild(0);
0923: int n2 = type.jjtGetNumChildren();
0924: sbuf.append(type.jjtGetChild(0).str);
0925: for (int j = 1; j < n2; j++) {
0926: sbuf.append('.');
0927: sbuf.append(type.jjtGetChild(j).str);
0928: }
0929: sbuf.append(' ');
0930: sbuf.append(c.str);
0931: sbuf.append(") ");
0932: accept(c, 1);
0933: }
0934: }
0935: return null;
0936: }
0937:
0938: public Object catchBlock(SimpleNode node, Context context) {
0939: return null;
0940: }
0941:
0942: public Object blockNode(SimpleNode node, Context context) {
0943: int n = node.jjtGetNumChildren();
0944: if (n >= 1) {
0945: String s = null;
0946: if (escape) {
0947: sbuf.append("{\\n");
0948: } else {
0949: sbuf.append("{\n");
0950: }
0951: ++nest;
0952: for (int i = 0; i < nest; i++) {
0953: sbuf.append(indent);
0954: }
0955: accept(node, 0);
0956: for (int i = 1; i < n; i++) {
0957: if (escape) {
0958: sbuf.append("\\n");
0959: } else {
0960: sbuf.append('\n');
0961: }
0962: for (int j = 0; j < nest; j++) {
0963: sbuf.append(indent);
0964: }
0965: accept(node, i);
0966: }
0967: --nest;
0968: if (escape) {
0969: sbuf.append("\\n");
0970: } else {
0971: sbuf.append('\n');
0972: }
0973: for (int i = 0; i < nest; i++) {
0974: sbuf.append(indent);
0975: }
0976: sbuf.append('}');
0977: } else {
0978: sbuf.append("{}");
0979: }
0980: return null;
0981: }
0982:
0983: public Object ifStatement(SimpleNode node, Context context) {
0984: sbuf.append("if (");
0985: accept(node, 0);
0986: sbuf.append(") ");
0987: accept(node, 1);
0988: int n = node.jjtGetNumChildren();
0989: for (int i = 2; i < n; i++) {
0990: SimpleNode c = (SimpleNode) node.jjtGetChild(i);
0991: if (c.id == PnutsParserTreeConstants.JJTELSEIFNODE) {
0992: sbuf.append(" else if (");
0993: accept(c, 0);
0994: sbuf.append(") ");
0995: accept(c, 1);
0996: } else if (c.id == PnutsParserTreeConstants.JJTELSENODE) {
0997: sbuf.append(" else ");
0998: accept(c, 0);
0999: }
1000: }
1001: return null;
1002: }
1003:
1004: public Object doStatement(SimpleNode node, Context context) {
1005: sbuf.append("do {");
1006: accept(node, 0);
1007: sbuf.append("} while (");
1008: accept(node, 1);
1009: sbuf.append(')');
1010: return null;
1011: }
1012:
1013: public Object whileStatement(SimpleNode node, Context context) {
1014: sbuf.append("while (");
1015: accept(node, 0);
1016: sbuf.append(") ");
1017: accept(node, 1);
1018: return null;
1019: }
1020:
1021: public Object forStatement(SimpleNode node, Context context) {
1022: SimpleNode initNode = null;
1023: SimpleNode condNode = null;
1024: SimpleNode updateNode = null;
1025: SimpleNode blockNode = null;
1026:
1027: sbuf.append("for (");
1028:
1029: int j = 0;
1030: SimpleNode n = (SimpleNode) node.jjtGetChild(j);
1031: if (n.id == PnutsParserTreeConstants.JJTFORENUM) {
1032: SimpleNode node0 = n.jjtGetChild(0);
1033: if (node0.id == PnutsParserTreeConstants.JJTMULTIASSIGNLHS) {
1034: int nc2 = node0.jjtGetNumChildren();
1035: if (nc2 > 0) {
1036: sbuf.append(node0.jjtGetChild(0).str);
1037: for (int i = 1; i < nc2; i++) {
1038: sbuf.append(',');
1039: sbuf.append(node0.jjtGetChild(i).str);
1040: }
1041: }
1042: } else {
1043: sbuf.append(strip(n.str));
1044: }
1045: sbuf.append(':');
1046: int nc = n.jjtGetNumChildren();
1047: if (node0.id == PnutsParserTreeConstants.JJTMULTIASSIGNLHS) {
1048: accept(n, 1);
1049: } else {
1050: accept(n, 0);
1051: if (nc == 2) {
1052: sbuf.append("..");
1053: accept(n, 1);
1054: }
1055: }
1056: sbuf.append(')');
1057: j++;
1058: } else {
1059: if (n.id == PnutsParserTreeConstants.JJTFORINIT) {
1060: initNode = n;
1061: j++;
1062: }
1063: n = (SimpleNode) node.jjtGetChild(j);
1064: if (n.id != PnutsParserTreeConstants.JJTFORUPDATE
1065: && n.id != PnutsParserTreeConstants.JJTBLOCK) {
1066: condNode = n;
1067: j++;
1068: }
1069: n = (SimpleNode) node.jjtGetChild(j);
1070: if (n.id == PnutsParserTreeConstants.JJTFORUPDATE) {
1071: updateNode = n;
1072: j++;
1073: }
1074:
1075: if (initNode != null) {
1076: int num = initNode.jjtGetNumChildren();
1077: SimpleNode sn = null;
1078: if (num > 0) {
1079: sn = (SimpleNode) initNode.jjtGetChild(0);
1080: sbuf.append(strip(sn.str));
1081: sbuf.append('=');
1082: accept(sn, 0);
1083: }
1084: for (int i = 1; i < num; i++) {
1085: sn = (SimpleNode) initNode.jjtGetChild(i);
1086: sbuf.append(',');
1087: sbuf.append(strip(sn.str));
1088: sbuf.append('=');
1089: accept(sn, 0);
1090: }
1091: }
1092: sbuf.append(';');
1093: if (condNode != null) {
1094: condNode.accept(this , context);
1095: }
1096: sbuf.append(';');
1097: if (updateNode != null) {
1098: expressionList(updateNode, context, ',');
1099: }
1100: sbuf.append(") ");
1101: }
1102:
1103: blockNode = (SimpleNode) node.jjtGetChild(j);
1104: blockNode.accept(this , context);
1105: return null;
1106: }
1107:
1108: public Object foreachStatement(SimpleNode node, Context context) {
1109: sbuf.append("foreach ");
1110: sbuf.append(strip(node.str));
1111: sbuf.append(" (");
1112: accept(node, 0);
1113: sbuf.append(") ");
1114: accept(node, 1);
1115: return null;
1116: }
1117:
1118: public Object switchStatement(SimpleNode node, Context context) {
1119: sbuf.append("switch (");
1120: accept(node, 0);
1121: sbuf.append("){");
1122:
1123: for (int i = 1; i < node.jjtGetNumChildren(); i++) {
1124: SimpleNode n = (SimpleNode) node.jjtGetChild(i);
1125: if (n.jjtGetNumChildren() == 1) { // case
1126: sbuf.append("case ");
1127: accept(n, 0);
1128: sbuf.append(": ");
1129: accept(node, ++i);
1130: } else {
1131: sbuf.append("default: ");
1132: accept(node, ++i);
1133: }
1134: sbuf.append("; ");
1135: }
1136: sbuf.append('}');
1137: return null;
1138: }
1139:
1140: public Object switchBlock(SimpleNode node, Context context) {
1141: int n = node.jjtGetNumChildren();
1142: if (n > 0) {
1143: accept(node, 0);
1144: for (int i = 1; i < n; i++) {
1145: sbuf.append("; ");
1146: accept(node, i);
1147: }
1148: }
1149: return null;
1150: }
1151:
1152: public Object functionStatement(SimpleNode node, Context context) {
1153: int pid = 0;
1154: if (node.jjtGetParent() != null) {
1155: pid = node.jjtGetParent().id;
1156: if (pid == PnutsParserTreeConstants.JJTAPPLICATIONNODE
1157: || pid == PnutsParserTreeConstants.JJTMETHODNODE) {
1158: sbuf.append('(');
1159: }
1160: }
1161: sbuf.append("function ");
1162:
1163: if (node.str != null) {
1164: sbuf.append(node.str);
1165: }
1166: SimpleNode args = (SimpleNode) node.jjtGetChild(0);
1167: int nargs = args.jjtGetNumChildren();
1168: boolean varargs = "[".equals(args.str);
1169: sbuf.append('(');
1170: SimpleNode n0 = null;
1171: if (nargs > 0) {
1172: paramList((SimpleNode) args);
1173: if (varargs) {
1174: sbuf.append("[]");
1175: }
1176: }
1177: sbuf.append(") ");
1178: accept(node, 1);
1179: if (pid == PnutsParserTreeConstants.JJTAPPLICATIONNODE
1180: || pid == PnutsParserTreeConstants.JJTMETHODNODE) {
1181: sbuf.append(')');
1182: }
1183: return null;
1184: }
1185:
1186: public Object ternary(SimpleNode node, Context context) {
1187: sbuf.append('(');
1188: accept(node, 0);
1189: sbuf.append(" ? ");
1190: accept(node, 1);
1191: sbuf.append(" : ");
1192: accept(node, 2);
1193: sbuf.append(')');
1194: return null;
1195: }
1196:
1197: public Object beanDef(SimpleNode node, Context context) {
1198: node.jjtGetChild(0).accept(this , context);
1199: sbuf.append("{\n");
1200: ++nest;
1201: for (int i = 1; i < node.jjtGetNumChildren(); i++) {
1202: for (int j = 0; j < nest; j++) {
1203: sbuf.append(indent);
1204: }
1205: SimpleNode cn = node.jjtGetChild(i);
1206: sbuf.append(cn.str);
1207: if ("::".equals(cn.info)) {
1208: sbuf.append(":: ");
1209: } else {
1210: sbuf.append(": ");
1211: }
1212: accept(cn, 0);
1213: sbuf.append('\n');
1214: }
1215: --nest;
1216: for (int i = 0; i < nest; i++) {
1217: sbuf.append(indent);
1218: }
1219: sbuf.append("}");
1220: return null;
1221: }
1222:
1223: final void accept(SimpleNode node, int idx) {
1224: node.jjtGetChild(idx).accept(this, null);
1225: }
1226: }
|