ref: 948d6a9fa86fa0e10f0a7674873ac08f0627a173
parent: 747a93838216bb85d7184d75143cbc759fadf3aa
author: Tor Andersson <tor@ccxvii.net>
date: Thu Jan 9 22:27:52 EST 2014
Pretty-print AST to javascript syntax.
--- a/js-ast.c
+++ b/js-ast.c
@@ -148,7 +148,7 @@
putchar('\t');
}
-void printlist(js_Ast *n, int level, const char *sep)
+static void printlist(js_Ast *n, int level, const char *sep)
{
while (n) {
printast(n->a, level);
@@ -163,11 +163,47 @@
while (n) {
indent(level);
printast(n->a, level);
- putchar('\n');
+ if (n->a->type < STM_BLOCK) // expression
+ putchar(';');
n = n->b;
+ if (n)
+ putchar('\n');
}
}
+static void printstm(js_Ast *n, int level)
+{
+ if (n->type == STM_BLOCK) {
+ printf(" {\n");
+ printblock(n->a, level + 1);
+ putchar('\n');
+ indent(level);
+ printf("}");
+ } else {
+ putchar('\n');
+ indent(level + 1);
+ printast(n, level + 1);
+ if (n->type < STM_BLOCK) // expression
+ putchar(';');
+ }
+}
+
+static void printunary(int level, js_Ast *n, const char *pre, const char *suf)
+{
+ printf(pre);
+ printast(n, level);
+ printf(suf);
+}
+
+static void printbinary(int level, js_Ast *a, js_Ast *b, const char *op)
+{
+ printf("(");
+ printast(a, level);
+ printf(" %s ", op);
+ printast(b, level);
+ printf(")");
+}
+
void printast(js_Ast *n, int level)
{
switch (n->type) {
@@ -180,13 +216,322 @@
printlist(n, level, " ");
putchar(']');
break;
+
case STM_BLOCK:
putchar('{');
putchar('\n');
printblock(n->a, level + 1);
+ putchar('\n');
indent(level);
putchar('}');
break;
+
+ case STM_FOR:
+ printf("for (");
+ printast(n->a, level); printf("; ");
+ printast(n->b, level); printf("; ");
+ printast(n->c, level); printf(")");
+ printstm(n->d, level);
+ break;
+ case STM_FOR_VAR:
+ printf("for (var ");
+ printlist(n->a, level, ", "); printf("; ");
+ printast(n->b, level); printf("; ");
+ printast(n->c, level); printf(")");
+ printstm(n->d, level);
+ break;
+ case STM_FOR_IN:
+ printf("for (");
+ printast(n->a, level); printf(" in ");
+ printast(n->b, level); printf(")");
+ printstm(n->c, level);
+ break;
+ case STM_FOR_IN_VAR:
+ printf("for (var ");
+ printlist(n->a, level, ", "); printf(" in ");
+ printast(n->b, level); printf(")");
+ printstm(n->c, level);
+ break;
+
+ case STM_NOP:
+ putchar(';');
+ break;
+
+ case STM_VAR:
+ printf("var ");
+ printlist(n->a, level, ", ");
+ putchar(';');
+ break;
+
+ case STM_IF:
+ printf("if (");
+ printast(n->a, level);
+ printf(")");
+ printstm(n->b, level);
+ if (n->c) {
+ putchar('\n');
+ indent(level);
+ printf("else");
+ printstm(n->c, level);
+ }
+ break;
+
+ case STM_DO:
+ printf("do");
+ printstm(n->a, level);
+ if (n->a->type == STM_BLOCK) {
+ putchar(' ');
+ } else {
+ putchar('\n');
+ indent(level);
+ }
+ printf("while (");
+ printast(n->b, level);
+ printf(");");
+ break;
+
+ case STM_WHILE:
+ printf("while (");
+ printast(n->a, level);
+ printf(")");
+ printstm(n->b, level);
+ break;
+
+ case STM_CONTINUE:
+ if (n->a) {
+ printf("continue ");
+ printast(n->a, level);
+ printf(";");
+ } else {
+ printf("continue;");
+ }
+ break;
+
+ case STM_BREAK:
+ if (n->a) {
+ printf("break ");
+ printast(n->a, level);
+ printf(";");
+ } else {
+ printf("break;");
+ }
+ break;
+
+ case STM_RETURN:
+ if (n->a) {
+ printf("return ");
+ printast(n->a, level);
+ printf(";");
+ } else {
+ printf("return;");
+ }
+ break;
+
+ case STM_THROW:
+ printf("throw ");
+ printast(n->a, level);
+ printf(";");
+ break;
+
+ case STM_SWITCH:
+ printf("switch (");
+ printast(n->a, level);
+ printf(")");
+ printstm(n->b, level);
+ break;
+
+ case STM_CASE:
+ printf("case ");
+ printast(n->a, level);
+ printf(":");
+ if (n->b) {
+ printf("\n");
+ printblock(n->b, level + 1);
+ }
+ break;
+
+ case STM_DEFAULT:
+ printf("default:");
+ if (n->a) {
+ printf("\n");
+ printblock(n->a, level + 1);
+ }
+ break;
+
+ case STM_LABEL:
+ printast(n->a, level);
+ printf(":");
+ printstm(n->b, level - 1);
+ break;
+
+ case STM_WITH:
+ printf("with (");
+ printast(n->a, level);
+ printf(")");
+ printstm(n->b, level);
+ break;
+
+ case STM_TRY:
+ printf("try");
+ printstm(n->a, level);
+ if (n->b && n->c) {
+ printf(" catch (");
+ printast(n->b, level);
+ printf(")");
+ printstm(n->c, level);
+ }
+ if (n->d) {
+ printf(" finally");
+ printstm(n->d, level);
+ }
+ break;
+
+ case STM_DEBUGGER:
+ printf("debugger");
+ break;
+
+ case AST_INIT:
+ printast(n->a, level);
+ if (n->b) {
+ printf(" = ");
+ printast(n->b, level);
+ }
+ break;
+
+ case STM_FUNC:
+ printf("function ");
+ printast(n->a, level);
+ printf("(");
+ printlist(n->b, level, ", ");
+ printf(")");
+ printstm(n->c, level);
+ break;
+
+ case EXP_FUNC:
+ printf("(function ");
+ if (n->a)
+ printast(n->a, level);
+ printf("(");
+ printlist(n->b, level, ", ");
+ printf(")");
+ printstm(n->c, level);
+ printf(")");
+ break;
+
+ case EXP_OBJECT:
+ printf("{ ");
+ printlist(n->a, level, ", ");
+ printf(" }");
+ break;
+
+ case EXP_PROP_VAL:
+ printast(n->a, level);
+ printf(": ");
+ printast(n->b, level);
+ break;
+
+ case EXP_ARRAY:
+ printf("[ ");
+ printlist(n->a, level, ", ");
+ printf(" ]");
+ break;
+
+ case EXP_NEW:
+ printf("(new ");
+ printast(n->a, level);
+ printf("(");
+ printlist(n->b, level, ", ");
+ printf("))");
+ break;
+
+ case EXP_CALL:
+ printf("(");
+ printast(n->a, level);
+ printf("(");
+ printlist(n->b, level, ", ");
+ printf("))");
+ break;
+
+ case EXP_MEMBER:
+ printf("(");
+ printast(n->a, level);
+ printf(".");
+ printast(n->b, level);
+ printf(")");
+ break;
+
+ case EXP_INDEX:
+ printf("(");
+ printast(n->a, level);
+ printf("[");
+ printast(n->b, level);
+ printf("])");
+ break;
+
+ case EXP_COND:
+ printf("(");
+ printast(n->a, level);
+ printf(" ? ");
+ printast(n->b, level);
+ printf(" : ");
+ printast(n->c, level);
+ printf(")");
+ break;
+
+ case EXP_NULL: printf("null"); break;
+ case EXP_TRUE: printf("true"); break;
+ case EXP_FALSE: printf("false"); break;
+ case EXP_THIS: printf("this"); break;
+
+ case EXP_DELETE: printunary(level, n->a, "(delete ", ")"); break;
+ case EXP_VOID: printunary(level, n->a, "(void ", ")"); break;
+ case EXP_TYPEOF: printunary(level, n->a, "(typeof ", ")"); break;
+ case EXP_PREINC: printunary(level, n->a, "(++", ")"); break;
+ case EXP_PREDEC: printunary(level, n->a, "(--", ")"); break;
+ case EXP_POSTINC: printunary(level, n->a, "(", "++)"); break;
+ case EXP_POSTDEC: printunary(level, n->a, "(", "--)"); break;
+ case EXP_POS: printunary(level, n->a, "(+", ")"); break;
+ case EXP_NEG: printunary(level, n->a, "(-", ")"); break;
+ case EXP_BITNOT: printunary(level, n->a, "(~", ")"); break;
+ case EXP_LOGNOT: printunary(level, n->a, "(!", ")"); break;
+
+ case EXP_COMMA: printbinary(level, n->a, n->b, ","); break;
+ case EXP_LOGOR: printbinary(level, n->a, n->b, "||"); break;
+ case EXP_LOGAND: printbinary(level, n->a, n->b, "&&"); break;
+ case EXP_BITOR: printbinary(level, n->a, n->b, "|"); break;
+ case EXP_BITXOR: printbinary(level, n->a, n->b, "^"); break;
+ case EXP_BITAND: printbinary(level, n->a, n->b, "&"); break;
+ case EXP_EQ: printbinary(level, n->a, n->b, "=="); break;
+ case EXP_NE: printbinary(level, n->a, n->b, "!="); break;
+ case EXP_EQ3: printbinary(level, n->a, n->b, "==="); break;
+ case EXP_NE3: printbinary(level, n->a, n->b, "!=="); break;
+ case EXP_LT: printbinary(level, n->a, n->b, "<"); break;
+ case EXP_GT: printbinary(level, n->a, n->b, ">"); break;
+ case EXP_LE: printbinary(level, n->a, n->b, "<="); break;
+ case EXP_GE: printbinary(level, n->a, n->b, ">="); break;
+ case EXP_INSTANCEOF: printbinary(level, n->a, n->b, "instanceof"); break;
+ case EXP_IN: printbinary(level, n->a, n->b, "in"); break;
+ case EXP_SHL: printbinary(level, n->a, n->b, "<<"); break;
+ case EXP_SHR: printbinary(level, n->a, n->b, ">>"); break;
+ case EXP_USHR: printbinary(level, n->a, n->b, ">>>"); break;
+ case EXP_ADD: printbinary(level, n->a, n->b, "+"); break;
+ case EXP_SUB: printbinary(level, n->a, n->b, "-"); break;
+ case EXP_MUL: printbinary(level, n->a, n->b, "*"); break;
+ case EXP_DIV: printbinary(level, n->a, n->b, "/"); break;
+ case EXP_MOD: printbinary(level, n->a, n->b, "%"); break;
+ case EXP_ASS: printbinary(level, n->a, n->b, "="); break;
+ case EXP_ASS_MUL: printbinary(level, n->a, n->b, "*="); break;
+ case EXP_ASS_DIV: printbinary(level, n->a, n->b, "/="); break;
+ case EXP_ASS_MOD: printbinary(level, n->a, n->b, "%="); break;
+ case EXP_ASS_ADD: printbinary(level, n->a, n->b, "+="); break;
+ case EXP_ASS_SUB: printbinary(level, n->a, n->b, "-="); break;
+ case EXP_ASS_SHL: printbinary(level, n->a, n->b, "<<="); break;
+ case EXP_ASS_SHR: printbinary(level, n->a, n->b, ">>="); break;
+ case EXP_ASS_USHR: printbinary(level, n->a, n->b, ">>>="); break;
+ case EXP_ASS_BITAND: printbinary(level, n->a, n->b, "&="); break;
+ case EXP_ASS_BITXOR: printbinary(level, n->a, n->b, "^="); break;
+ case EXP_ASS_BITOR: printbinary(level, n->a, n->b, "|="); break;
+
default:
printf("(%s", strast(n->type));
if (n->a) { putchar(' '); printast(n->a, level); }
--- a/js-ast.h
+++ b/js-ast.h
@@ -122,5 +122,6 @@
void jsP_freeast(js_State *J);
void printast(js_Ast *n, int level);
+void printblock(js_Ast *n, int level);
#endif
--- a/js-parse.c
+++ b/js-parse.c
@@ -836,7 +836,7 @@
}
next(J);
- printast(sourcelist(J), 0);
+ printblock(sourcelist(J)->a, 0);
putchar('\n');
// TODO: compile to bytecode