shithub: libmujs

Download patch

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