Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #include "jsi.h"
  2. #include "jslex.h"
  3. #include "jsparse.h"
  4.  
  5. #define LIST(h)                 jsP_newnode(J, AST_LIST, 0, h, 0, 0, 0)
  6.  
  7. #define EXP0(x)                 jsP_newnode(J, EXP_ ## x, line, 0, 0, 0, 0)
  8. #define EXP1(x,a)               jsP_newnode(J, EXP_ ## x, line, a, 0, 0, 0)
  9. #define EXP2(x,a,b)             jsP_newnode(J, EXP_ ## x, line, a, b, 0, 0)
  10. #define EXP3(x,a,b,c)           jsP_newnode(J, EXP_ ## x, line, a, b, c, 0)
  11.  
  12. #define STM0(x)                 jsP_newnode(J, STM_ ## x, line, 0, 0, 0, 0)
  13. #define STM1(x,a)               jsP_newnode(J, STM_ ## x, line, a, 0, 0, 0)
  14. #define STM2(x,a,b)             jsP_newnode(J, STM_ ## x, line, a, b, 0, 0)
  15. #define STM3(x,a,b,c)           jsP_newnode(J, STM_ ## x, line, a, b, c, 0)
  16. #define STM4(x,a,b,c,d)         jsP_newnode(J, STM_ ## x, line, a, b, c, d)
  17.  
  18. static js_Ast *expression(js_State *J, int notin);
  19. static js_Ast *assignment(js_State *J, int notin);
  20. static js_Ast *memberexp(js_State *J);
  21. static js_Ast *statement(js_State *J);
  22. static js_Ast *funbody(js_State *J);
  23.  
  24. JS_NORETURN static void jsP_error(js_State *J, const char *fmt, ...) JS_PRINTFLIKE(2,3);
  25.  
  26. #define INCREC() if (++J->astdepth > JS_ASTLIMIT) jsP_error(J, "too much recursion")
  27. #define DECREC() --J->astdepth
  28. #define SAVEREC() int SAVE=J->astdepth
  29. #define POPREC() J->astdepth=SAVE
  30.  
  31. static void jsP_error(js_State *J, const char *fmt, ...)
  32. {
  33.         va_list ap;
  34.         char buf[512];
  35.         char msgbuf[256];
  36.  
  37.         va_start(ap, fmt);
  38.         vsnprintf(msgbuf, 256, fmt, ap);
  39.         va_end(ap);
  40.  
  41.         snprintf(buf, 256, "%s:%d: ", J->filename, J->lexline);
  42.         strcat(buf, msgbuf);
  43.  
  44.         js_newsyntaxerror(J, buf);
  45.         js_throw(J);
  46. }
  47.  
  48. static void jsP_warning(js_State *J, const char *fmt, ...)
  49. {
  50.         va_list ap;
  51.         char buf[512];
  52.         char msg[256];
  53.  
  54.         va_start(ap, fmt);
  55.         vsnprintf(msg, sizeof msg, fmt, ap);
  56.         va_end(ap);
  57.  
  58.         snprintf(buf, sizeof buf, "%s:%d: warning: %s", J->filename, J->lexline, msg);
  59.         js_report(J, buf);
  60. }
  61.  
  62. static js_Ast *jsP_newnode(js_State *J, enum js_AstType type, int line, js_Ast *a, js_Ast *b, js_Ast *c, js_Ast *d)
  63. {
  64.         js_Ast *node = js_malloc(J, sizeof *node);
  65.  
  66.         node->type = type;
  67.         node->line = line;
  68.         node->a = a;
  69.         node->b = b;
  70.         node->c = c;
  71.         node->d = d;
  72.         node->number = 0;
  73.         node->string = NULL;
  74.         node->jumps = NULL;
  75.         node->casejump = 0;
  76.  
  77.         node->parent = NULL;
  78.         if (a) a->parent = node;
  79.         if (b) b->parent = node;
  80.         if (c) c->parent = node;
  81.         if (d) d->parent = node;
  82.  
  83.         node->gcnext = J->gcast;
  84.         J->gcast = node;
  85.  
  86.         return node;
  87. }
  88.  
  89. static js_Ast *jsP_list(js_Ast *head)
  90. {
  91.         /* set parent pointers in list nodes */
  92.         js_Ast *prev = head, *node = head->b;
  93.         while (node) {
  94.                 node->parent = prev;
  95.                 prev = node;
  96.                 node = node->b;
  97.         }
  98.         return head;
  99. }
  100.  
  101. static js_Ast *jsP_newstrnode(js_State *J, enum js_AstType type, const char *s)
  102. {
  103.         js_Ast *node = jsP_newnode(J, type, J->lexline, 0, 0, 0, 0);
  104.         node->string = s;
  105.         return node;
  106. }
  107.  
  108. static js_Ast *jsP_newnumnode(js_State *J, enum js_AstType type, double n)
  109. {
  110.         js_Ast *node = jsP_newnode(J, type, J->lexline, 0, 0, 0, 0);
  111.         node->number = n;
  112.         return node;
  113. }
  114.  
  115. static void jsP_freejumps(js_State *J, js_JumpList *node)
  116. {
  117.         while (node) {
  118.                 js_JumpList *next = node->next;
  119.                 js_free(J, node);
  120.                 node = next;
  121.         }
  122. }
  123.  
  124. void jsP_freeparse(js_State *J)
  125. {
  126.         js_Ast *node = J->gcast;
  127.         while (node) {
  128.                 js_Ast *next = node->gcnext;
  129.                 jsP_freejumps(J, node->jumps);
  130.                 js_free(J, node);
  131.                 node = next;
  132.         }
  133.         J->gcast = NULL;
  134. }
  135.  
  136. /* Lookahead */
  137.  
  138. static void jsP_next(js_State *J)
  139. {
  140.         J->lookahead = jsY_lex(J);
  141. }
  142.  
  143. #define jsP_accept(J,x) (J->lookahead == x ? (jsP_next(J), 1) : 0)
  144.  
  145. #define jsP_expect(J,x) if (!jsP_accept(J, x)) jsP_error(J, "unexpected token: %s (expected %s)", jsY_tokenstring(J->lookahead), jsY_tokenstring(x))
  146.  
  147. static void semicolon(js_State *J)
  148. {
  149.         if (J->lookahead == ';') {
  150.                 jsP_next(J);
  151.                 return;
  152.         }
  153.         if (J->newline || J->lookahead == '}' || J->lookahead == 0)
  154.                 return;
  155.         jsP_error(J, "unexpected token: %s (expected ';')", jsY_tokenstring(J->lookahead));
  156. }
  157.  
  158. /* Literals */
  159.  
  160. static js_Ast *identifier(js_State *J)
  161. {
  162.         js_Ast *a;
  163.         if (J->lookahead == TK_IDENTIFIER) {
  164.                 a = jsP_newstrnode(J, AST_IDENTIFIER, J->text);
  165.                 jsP_next(J);
  166.                 return a;
  167.         }
  168.         jsP_error(J, "unexpected token: %s (expected identifier)", jsY_tokenstring(J->lookahead));
  169. }
  170.  
  171. static js_Ast *identifieropt(js_State *J)
  172. {
  173.         if (J->lookahead == TK_IDENTIFIER)
  174.                 return identifier(J);
  175.         return NULL;
  176. }
  177.  
  178. static js_Ast *identifiername(js_State *J)
  179. {
  180.         if (J->lookahead == TK_IDENTIFIER || J->lookahead >= TK_BREAK) {
  181.                 js_Ast *a = jsP_newstrnode(J, AST_IDENTIFIER, J->text);
  182.                 jsP_next(J);
  183.                 return a;
  184.         }
  185.         jsP_error(J, "unexpected token: %s (expected identifier or keyword)", jsY_tokenstring(J->lookahead));
  186. }
  187.  
  188. static js_Ast *arrayelement(js_State *J)
  189. {
  190.         int line = J->lexline;
  191.         if (J->lookahead == ',')
  192.                 return EXP0(UNDEF);
  193.         return assignment(J, 0);
  194. }
  195.  
  196. static js_Ast *arrayliteral(js_State *J)
  197. {
  198.         js_Ast *head, *tail;
  199.         if (J->lookahead == ']')
  200.                 return NULL;
  201.         head = tail = LIST(arrayelement(J));
  202.         while (jsP_accept(J, ',')) {
  203.                 if (J->lookahead != ']')
  204.                         tail = tail->b = LIST(arrayelement(J));
  205.         }
  206.         return jsP_list(head);
  207. }
  208.  
  209. static js_Ast *propname(js_State *J)
  210. {
  211.         js_Ast *name;
  212.         if (J->lookahead == TK_NUMBER) {
  213.                 name = jsP_newnumnode(J, EXP_NUMBER, J->number);
  214.                 jsP_next(J);
  215.         } else if (J->lookahead == TK_STRING) {
  216.                 name = jsP_newstrnode(J, EXP_STRING, J->text);
  217.                 jsP_next(J);
  218.         } else {
  219.                 name = identifiername(J);
  220.         }
  221.         return name;
  222. }
  223.  
  224. static js_Ast *propassign(js_State *J)
  225. {
  226.         js_Ast *name, *value, *arg, *body;
  227.         int line = J->lexline;
  228.  
  229.         name = propname(J);
  230.  
  231.         if (J->lookahead != ':' && name->type == AST_IDENTIFIER) {
  232.                 if (!strcmp(name->string, "get")) {
  233.                         name = propname(J);
  234.                         jsP_expect(J, '(');
  235.                         jsP_expect(J, ')');
  236.                         body = funbody(J);
  237.                         return EXP3(PROP_GET, name, NULL, body);
  238.                 }
  239.                 if (!strcmp(name->string, "set")) {
  240.                         name = propname(J);
  241.                         jsP_expect(J, '(');
  242.                         arg = identifier(J);
  243.                         jsP_expect(J, ')');
  244.                         body = funbody(J);
  245.                         return EXP3(PROP_SET, name, LIST(arg), body);
  246.                 }
  247.         }
  248.  
  249.         jsP_expect(J, ':');
  250.         value = assignment(J, 0);
  251.         return EXP2(PROP_VAL, name, value);
  252. }
  253.  
  254. static js_Ast *objectliteral(js_State *J)
  255. {
  256.         js_Ast *head, *tail;
  257.         if (J->lookahead == '}')
  258.                 return NULL;
  259.         head = tail = LIST(propassign(J));
  260.         while (jsP_accept(J, ',')) {
  261.                 if (J->lookahead == '}')
  262.                         break;
  263.                 tail = tail->b = LIST(propassign(J));
  264.         }
  265.         return jsP_list(head);
  266. }
  267.  
  268. /* Functions */
  269.  
  270. static js_Ast *parameters(js_State *J)
  271. {
  272.         js_Ast *head, *tail;
  273.         if (J->lookahead == ')')
  274.                 return NULL;
  275.         head = tail = LIST(identifier(J));
  276.         while (jsP_accept(J, ',')) {
  277.                 tail = tail->b = LIST(identifier(J));
  278.         }
  279.         return jsP_list(head);
  280. }
  281.  
  282. static js_Ast *fundec(js_State *J, int line)
  283. {
  284.         js_Ast *a, *b, *c;
  285.         a = identifier(J);
  286.         jsP_expect(J, '(');
  287.         b = parameters(J);
  288.         jsP_expect(J, ')');
  289.         c = funbody(J);
  290.         return jsP_newnode(J, AST_FUNDEC, line, a, b, c, 0);
  291. }
  292.  
  293. static js_Ast *funstm(js_State *J, int line)
  294. {
  295.         js_Ast *a, *b, *c;
  296.         a = identifier(J);
  297.         jsP_expect(J, '(');
  298.         b = parameters(J);
  299.         jsP_expect(J, ')');
  300.         c = funbody(J);
  301.         /* rewrite function statement as "var X = function X() {}" */
  302.         return STM1(VAR, LIST(EXP2(VAR, a, EXP3(FUN, a, b, c))));
  303. }
  304.  
  305. static js_Ast *funexp(js_State *J, int line)
  306. {
  307.         js_Ast *a, *b, *c;
  308.         a = identifieropt(J);
  309.         jsP_expect(J, '(');
  310.         b = parameters(J);
  311.         jsP_expect(J, ')');
  312.         c = funbody(J);
  313.         return EXP3(FUN, a, b, c);
  314. }
  315.  
  316. /* Expressions */
  317.  
  318. static js_Ast *primary(js_State *J)
  319. {
  320.         js_Ast *a;
  321.         int line = J->lexline;
  322.  
  323.         if (J->lookahead == TK_IDENTIFIER) {
  324.                 a = jsP_newstrnode(J, EXP_IDENTIFIER, J->text);
  325.                 jsP_next(J);
  326.                 return a;
  327.         }
  328.         if (J->lookahead == TK_STRING) {
  329.                 a = jsP_newstrnode(J, EXP_STRING, J->text);
  330.                 jsP_next(J);
  331.                 return a;
  332.         }
  333.         if (J->lookahead == TK_REGEXP) {
  334.                 a = jsP_newstrnode(J, EXP_REGEXP, J->text);
  335.                 a->number = J->number;
  336.                 jsP_next(J);
  337.                 return a;
  338.         }
  339.         if (J->lookahead == TK_NUMBER) {
  340.                 a = jsP_newnumnode(J, EXP_NUMBER, J->number);
  341.                 jsP_next(J);
  342.                 return a;
  343.         }
  344.  
  345.         if (jsP_accept(J, TK_THIS)) return EXP0(THIS);
  346.         if (jsP_accept(J, TK_NULL)) return EXP0(NULL);
  347.         if (jsP_accept(J, TK_TRUE)) return EXP0(TRUE);
  348.         if (jsP_accept(J, TK_FALSE)) return EXP0(FALSE);
  349.         if (jsP_accept(J, '{')) {
  350.                 a = EXP1(OBJECT, objectliteral(J));
  351.                 jsP_expect(J, '}');
  352.                 return a;
  353.         }
  354.         if (jsP_accept(J, '[')) {
  355.                 a = EXP1(ARRAY, arrayliteral(J));
  356.                 jsP_expect(J, ']');
  357.                 return a;
  358.         }
  359.         if (jsP_accept(J, '(')) {
  360.                 a = expression(J, 0);
  361.                 jsP_expect(J, ')');
  362.                 return a;
  363.         }
  364.  
  365.         jsP_error(J, "unexpected token in expression: %s", jsY_tokenstring(J->lookahead));
  366. }
  367.  
  368. static js_Ast *arguments(js_State *J)
  369. {
  370.         js_Ast *head, *tail;
  371.         if (J->lookahead == ')')
  372.                 return NULL;
  373.         head = tail = LIST(assignment(J, 0));
  374.         while (jsP_accept(J, ',')) {
  375.                 tail = tail->b = LIST(assignment(J, 0));
  376.         }
  377.         return jsP_list(head);
  378. }
  379.  
  380. static js_Ast *newexp(js_State *J)
  381. {
  382.         js_Ast *a, *b;
  383.         int line = J->lexline;
  384.  
  385.         if (jsP_accept(J, TK_NEW)) {
  386.                 a = memberexp(J);
  387.                 if (jsP_accept(J, '(')) {
  388.                         b = arguments(J);
  389.                         jsP_expect(J, ')');
  390.                         return EXP2(NEW, a, b);
  391.                 }
  392.                 return EXP1(NEW, a);
  393.         }
  394.  
  395.         if (jsP_accept(J, TK_FUNCTION))
  396.                 return funexp(J, line);
  397.  
  398.         return primary(J);
  399. }
  400.  
  401. static js_Ast *memberexp(js_State *J)
  402. {
  403.         js_Ast *a = newexp(J);
  404.         int line;
  405.         SAVEREC();
  406. loop:
  407.         INCREC();
  408.         line = J->lexline;
  409.         if (jsP_accept(J, '.')) { a = EXP2(MEMBER, a, identifiername(J)); goto loop; }
  410.         if (jsP_accept(J, '[')) { a = EXP2(INDEX, a, expression(J, 0)); jsP_expect(J, ']'); goto loop; }
  411.         POPREC();
  412.         return a;
  413. }
  414.  
  415. static js_Ast *callexp(js_State *J)
  416. {
  417.         js_Ast *a = newexp(J);
  418.         int line;
  419.         SAVEREC();
  420. loop:
  421.         INCREC();
  422.         line = J->lexline;
  423.         if (jsP_accept(J, '.')) { a = EXP2(MEMBER, a, identifiername(J)); goto loop; }
  424.         if (jsP_accept(J, '[')) { a = EXP2(INDEX, a, expression(J, 0)); jsP_expect(J, ']'); goto loop; }
  425.         if (jsP_accept(J, '(')) { a = EXP2(CALL, a, arguments(J)); jsP_expect(J, ')'); goto loop; }
  426.         POPREC();
  427.         return a;
  428. }
  429.  
  430. static js_Ast *postfix(js_State *J)
  431. {
  432.         js_Ast *a = callexp(J);
  433.         int line = J->lexline;
  434.         if (!J->newline && jsP_accept(J, TK_INC)) return EXP1(POSTINC, a);
  435.         if (!J->newline && jsP_accept(J, TK_DEC)) return EXP1(POSTDEC, a);
  436.         return a;
  437. }
  438.  
  439. static js_Ast *unary(js_State *J)
  440. {
  441.         js_Ast *a;
  442.         int line = J->lexline;
  443.         INCREC();
  444.         if (jsP_accept(J, TK_DELETE)) a = EXP1(DELETE, unary(J));
  445.         else if (jsP_accept(J, TK_VOID)) a = EXP1(VOID, unary(J));
  446.         else if (jsP_accept(J, TK_TYPEOF)) a = EXP1(TYPEOF, unary(J));
  447.         else if (jsP_accept(J, TK_INC)) a = EXP1(PREINC, unary(J));
  448.         else if (jsP_accept(J, TK_DEC)) a = EXP1(PREDEC, unary(J));
  449.         else if (jsP_accept(J, '+')) a = EXP1(POS, unary(J));
  450.         else if (jsP_accept(J, '-')) a = EXP1(NEG, unary(J));
  451.         else if (jsP_accept(J, '~')) a = EXP1(BITNOT, unary(J));
  452.         else if (jsP_accept(J, '!')) a = EXP1(LOGNOT, unary(J));
  453.         else a = postfix(J);
  454.         DECREC();
  455.         return a;
  456. }
  457.  
  458. static js_Ast *multiplicative(js_State *J)
  459. {
  460.         js_Ast *a = unary(J);
  461.         int line;
  462.         SAVEREC();
  463. loop:
  464.         INCREC();
  465.         line = J->lexline;
  466.         if (jsP_accept(J, '*')) { a = EXP2(MUL, a, unary(J)); goto loop; }
  467.         if (jsP_accept(J, '/')) { a = EXP2(DIV, a, unary(J)); goto loop; }
  468.         if (jsP_accept(J, '%')) { a = EXP2(MOD, a, unary(J)); goto loop; }
  469.         POPREC();
  470.         return a;
  471. }
  472.  
  473. static js_Ast *additive(js_State *J)
  474. {
  475.         js_Ast *a = multiplicative(J);
  476.         int line;
  477.         SAVEREC();
  478. loop:
  479.         INCREC();
  480.         line = J->lexline;
  481.         if (jsP_accept(J, '+')) { a = EXP2(ADD, a, multiplicative(J)); goto loop; }
  482.         if (jsP_accept(J, '-')) { a = EXP2(SUB, a, multiplicative(J)); goto loop; }
  483.         POPREC();
  484.         return a;
  485. }
  486.  
  487. static js_Ast *shift(js_State *J)
  488. {
  489.         js_Ast *a = additive(J);
  490.         int line;
  491.         SAVEREC();
  492. loop:
  493.         INCREC();
  494.         line = J->lexline;
  495.         if (jsP_accept(J, TK_SHL)) { a = EXP2(SHL, a, additive(J)); goto loop; }
  496.         if (jsP_accept(J, TK_SHR)) { a = EXP2(SHR, a, additive(J)); goto loop; }
  497.         if (jsP_accept(J, TK_USHR)) { a = EXP2(USHR, a, additive(J)); goto loop; }
  498.         POPREC();
  499.         return a;
  500. }
  501.  
  502. static js_Ast *relational(js_State *J, int notin)
  503. {
  504.         js_Ast *a = shift(J);
  505.         int line;
  506.         SAVEREC();
  507. loop:
  508.         INCREC();
  509.         line = J->lexline;
  510.         if (jsP_accept(J, '<')) { a = EXP2(LT, a, shift(J)); goto loop; }
  511.         if (jsP_accept(J, '>')) { a = EXP2(GT, a, shift(J)); goto loop; }
  512.         if (jsP_accept(J, TK_LE)) { a = EXP2(LE, a, shift(J)); goto loop; }
  513.         if (jsP_accept(J, TK_GE)) { a = EXP2(GE, a, shift(J)); goto loop; }
  514.         if (jsP_accept(J, TK_INSTANCEOF)) { a = EXP2(INSTANCEOF, a, shift(J)); goto loop; }
  515.         if (!notin && jsP_accept(J, TK_IN)) { a = EXP2(IN, a, shift(J)); goto loop; }
  516.         POPREC();
  517.         return a;
  518. }
  519.  
  520. static js_Ast *equality(js_State *J, int notin)
  521. {
  522.         js_Ast *a = relational(J, notin);
  523.         int line;
  524.         SAVEREC();
  525. loop:
  526.         INCREC();
  527.         line = J->lexline;
  528.         if (jsP_accept(J, TK_EQ)) { a = EXP2(EQ, a, relational(J, notin)); goto loop; }
  529.         if (jsP_accept(J, TK_NE)) { a = EXP2(NE, a, relational(J, notin)); goto loop; }
  530.         if (jsP_accept(J, TK_STRICTEQ)) { a = EXP2(STRICTEQ, a, relational(J, notin)); goto loop; }
  531.         if (jsP_accept(J, TK_STRICTNE)) { a = EXP2(STRICTNE, a, relational(J, notin)); goto loop; }
  532.         POPREC();
  533.         return a;
  534. }
  535.  
  536. static js_Ast *bitand(js_State *J, int notin)
  537. {
  538.         js_Ast *a = equality(J, notin);
  539.         SAVEREC();
  540.         int line = J->lexline;
  541.         while (jsP_accept(J, '&')) {
  542.                 INCREC();
  543.                 a = EXP2(BITAND, a, equality(J, notin));
  544.                 line = J->lexline;
  545.         }
  546.         POPREC();
  547.         return a;
  548. }
  549.  
  550. static js_Ast *bitxor(js_State *J, int notin)
  551. {
  552.         js_Ast *a = bitand(J, notin);
  553.         SAVEREC();
  554.         int line = J->lexline;
  555.         while (jsP_accept(J, '^')) {
  556.                 INCREC();
  557.                 a = EXP2(BITXOR, a, bitand(J, notin));
  558.                 line = J->lexline;
  559.         }
  560.         POPREC();
  561.         return a;
  562. }
  563.  
  564. static js_Ast *bitor(js_State *J, int notin)
  565. {
  566.         js_Ast *a = bitxor(J, notin);
  567.         SAVEREC();
  568.         int line = J->lexline;
  569.         while (jsP_accept(J, '|')) {
  570.                 INCREC();
  571.                 a = EXP2(BITOR, a, bitxor(J, notin));
  572.                 line = J->lexline;
  573.         }
  574.         POPREC();
  575.         return a;
  576. }
  577.  
  578. static js_Ast *logand(js_State *J, int notin)
  579. {
  580.         js_Ast *a = bitor(J, notin);
  581.         int line = J->lexline;
  582.         if (jsP_accept(J, TK_AND)) {
  583.                 INCREC();
  584.                 a = EXP2(LOGAND, a, logand(J, notin));
  585.                 DECREC();
  586.         }
  587.         return a;
  588. }
  589.  
  590. static js_Ast *logor(js_State *J, int notin)
  591. {
  592.         js_Ast *a = logand(J, notin);
  593.         int line = J->lexline;
  594.         if (jsP_accept(J, TK_OR)) {
  595.                 INCREC();
  596.                 a = EXP2(LOGOR, a, logor(J, notin));
  597.                 DECREC();
  598.         }
  599.         return a;
  600. }
  601.  
  602. static js_Ast *conditional(js_State *J, int notin)
  603. {
  604.         js_Ast *a = logor(J, notin);
  605.         int line = J->lexline;
  606.         if (jsP_accept(J, '?')) {
  607.                 js_Ast *b, *c;
  608.                 INCREC();
  609.                 b = assignment(J, 0);
  610.                 jsP_expect(J, ':');
  611.                 c = assignment(J, notin);
  612.                 DECREC();
  613.                 return EXP3(COND, a, b, c);
  614.         }
  615.         return a;
  616. }
  617.  
  618. static js_Ast *assignment(js_State *J, int notin)
  619. {
  620.         js_Ast *a = conditional(J, notin);
  621.         int line = J->lexline;
  622.         INCREC();
  623.         if (jsP_accept(J, '=')) a = EXP2(ASS, a, assignment(J, notin));
  624.         else if (jsP_accept(J, TK_MUL_ASS)) a = EXP2(ASS_MUL, a, assignment(J, notin));
  625.         else if (jsP_accept(J, TK_DIV_ASS)) a = EXP2(ASS_DIV, a, assignment(J, notin));
  626.         else if (jsP_accept(J, TK_MOD_ASS)) a = EXP2(ASS_MOD, a, assignment(J, notin));
  627.         else if (jsP_accept(J, TK_ADD_ASS)) a = EXP2(ASS_ADD, a, assignment(J, notin));
  628.         else if (jsP_accept(J, TK_SUB_ASS)) a = EXP2(ASS_SUB, a, assignment(J, notin));
  629.         else if (jsP_accept(J, TK_SHL_ASS)) a = EXP2(ASS_SHL, a, assignment(J, notin));
  630.         else if (jsP_accept(J, TK_SHR_ASS)) a = EXP2(ASS_SHR, a, assignment(J, notin));
  631.         else if (jsP_accept(J, TK_USHR_ASS)) a = EXP2(ASS_USHR, a, assignment(J, notin));
  632.         else if (jsP_accept(J, TK_AND_ASS)) a = EXP2(ASS_BITAND, a, assignment(J, notin));
  633.         else if (jsP_accept(J, TK_XOR_ASS)) a = EXP2(ASS_BITXOR, a, assignment(J, notin));
  634.         else if (jsP_accept(J, TK_OR_ASS)) a = EXP2(ASS_BITOR, a, assignment(J, notin));
  635.         DECREC();
  636.         return a;
  637. }
  638.  
  639. static js_Ast *expression(js_State *J, int notin)
  640. {
  641.         js_Ast *a = assignment(J, notin);
  642.         SAVEREC();
  643.         int line = J->lexline;
  644.         while (jsP_accept(J, ',')) {
  645.                 INCREC();
  646.                 a = EXP2(COMMA, a, assignment(J, notin));
  647.                 line = J->lexline;
  648.         }
  649.         POPREC();
  650.         return a;
  651. }
  652.  
  653. /* Statements */
  654.  
  655. static js_Ast *vardec(js_State *J, int notin)
  656. {
  657.         js_Ast *a = identifier(J);
  658.         int line = J->lexline;
  659.         if (jsP_accept(J, '='))
  660.                 return EXP2(VAR, a, assignment(J, notin));
  661.         return EXP1(VAR, a);
  662. }
  663.  
  664. static js_Ast *vardeclist(js_State *J, int notin)
  665. {
  666.         js_Ast *head, *tail;
  667.         head = tail = LIST(vardec(J, notin));
  668.         while (jsP_accept(J, ','))
  669.                 tail = tail->b = LIST(vardec(J, notin));
  670.         return jsP_list(head);
  671. }
  672.  
  673. static js_Ast *statementlist(js_State *J)
  674. {
  675.         js_Ast *head, *tail;
  676.         if (J->lookahead == '}' || J->lookahead == TK_CASE || J->lookahead == TK_DEFAULT)
  677.                 return NULL;
  678.         head = tail = LIST(statement(J));
  679.         while (J->lookahead != '}' && J->lookahead != TK_CASE && J->lookahead != TK_DEFAULT)
  680.                 tail = tail->b = LIST(statement(J));
  681.         return jsP_list(head);
  682. }
  683.  
  684. static js_Ast *caseclause(js_State *J)
  685. {
  686.         js_Ast *a, *b;
  687.         int line = J->lexline;
  688.  
  689.         if (jsP_accept(J, TK_CASE)) {
  690.                 a = expression(J, 0);
  691.                 jsP_expect(J, ':');
  692.                 b = statementlist(J);
  693.                 return STM2(CASE, a, b);
  694.         }
  695.  
  696.         if (jsP_accept(J, TK_DEFAULT)) {
  697.                 jsP_expect(J, ':');
  698.                 a = statementlist(J);
  699.                 return STM1(DEFAULT, a);
  700.         }
  701.  
  702.         jsP_error(J, "unexpected token in switch: %s (expected 'case' or 'default')", jsY_tokenstring(J->lookahead));
  703. }
  704.  
  705. static js_Ast *caselist(js_State *J)
  706. {
  707.         js_Ast *head, *tail;
  708.         if (J->lookahead == '}')
  709.                 return NULL;
  710.         head = tail = LIST(caseclause(J));
  711.         while (J->lookahead != '}')
  712.                 tail = tail->b = LIST(caseclause(J));
  713.         return jsP_list(head);
  714. }
  715.  
  716. static js_Ast *block(js_State *J)
  717. {
  718.         js_Ast *a;
  719.         int line = J->lexline;
  720.         jsP_expect(J, '{');
  721.         a = statementlist(J);
  722.         jsP_expect(J, '}');
  723.         return STM1(BLOCK, a);
  724. }
  725.  
  726. static js_Ast *forexpression(js_State *J, int end)
  727. {
  728.         js_Ast *a = NULL;
  729.         if (J->lookahead != end)
  730.                 a = expression(J, 0);
  731.         jsP_expect(J, end);
  732.         return a;
  733. }
  734.  
  735. static js_Ast *forstatement(js_State *J, int line)
  736. {
  737.         js_Ast *a, *b, *c, *d;
  738.         jsP_expect(J, '(');
  739.         if (jsP_accept(J, TK_VAR)) {
  740.                 a = vardeclist(J, 1);
  741.                 if (jsP_accept(J, ';')) {
  742.                         b = forexpression(J, ';');
  743.                         c = forexpression(J, ')');
  744.                         d = statement(J);
  745.                         return STM4(FOR_VAR, a, b, c, d);
  746.                 }
  747.                 if (jsP_accept(J, TK_IN)) {
  748.                         b = expression(J, 0);
  749.                         jsP_expect(J, ')');
  750.                         c = statement(J);
  751.                         return STM3(FOR_IN_VAR, a, b, c);
  752.                 }
  753.                 jsP_error(J, "unexpected token in for-var-statement: %s", jsY_tokenstring(J->lookahead));
  754.         }
  755.  
  756.         if (J->lookahead != ';')
  757.                 a = expression(J, 1);
  758.         else
  759.                 a = NULL;
  760.         if (jsP_accept(J, ';')) {
  761.                 b = forexpression(J, ';');
  762.                 c = forexpression(J, ')');
  763.                 d = statement(J);
  764.                 return STM4(FOR, a, b, c, d);
  765.         }
  766.         if (jsP_accept(J, TK_IN)) {
  767.                 b = expression(J, 0);
  768.                 jsP_expect(J, ')');
  769.                 c = statement(J);
  770.                 return STM3(FOR_IN, a, b, c);
  771.         }
  772.         jsP_error(J, "unexpected token in for-statement: %s", jsY_tokenstring(J->lookahead));
  773. }
  774.  
  775. static js_Ast *statement(js_State *J)
  776. {
  777.         js_Ast *a, *b, *c, *d;
  778.         js_Ast *stm;
  779.         int line = J->lexline;
  780.  
  781.         INCREC();
  782.  
  783.         if (J->lookahead == '{') {
  784.                 stm = block(J);
  785.         }
  786.  
  787.         else if (jsP_accept(J, TK_VAR)) {
  788.                 a = vardeclist(J, 0);
  789.                 semicolon(J);
  790.                 stm = STM1(VAR, a);
  791.         }
  792.  
  793.         /* empty statement */
  794.         else if (jsP_accept(J, ';')) {
  795.                 stm = STM0(EMPTY);
  796.         }
  797.  
  798.         else if (jsP_accept(J, TK_IF)) {
  799.                 jsP_expect(J, '(');
  800.                 a = expression(J, 0);
  801.                 jsP_expect(J, ')');
  802.                 b = statement(J);
  803.                 if (jsP_accept(J, TK_ELSE))
  804.                         c = statement(J);
  805.                 else
  806.                         c = NULL;
  807.                 stm = STM3(IF, a, b, c);
  808.         }
  809.  
  810.         else if (jsP_accept(J, TK_DO)) {
  811.                 a = statement(J);
  812.                 jsP_expect(J, TK_WHILE);
  813.                 jsP_expect(J, '(');
  814.                 b = expression(J, 0);
  815.                 jsP_expect(J, ')');
  816.                 semicolon(J);
  817.                 stm = STM2(DO, a, b);
  818.         }
  819.  
  820.         else if (jsP_accept(J, TK_WHILE)) {
  821.                 jsP_expect(J, '(');
  822.                 a = expression(J, 0);
  823.                 jsP_expect(J, ')');
  824.                 b = statement(J);
  825.                 stm = STM2(WHILE, a, b);
  826.         }
  827.  
  828.         else if (jsP_accept(J, TK_FOR)) {
  829.                 stm = forstatement(J, line);
  830.         }
  831.  
  832.         else if (jsP_accept(J, TK_CONTINUE)) {
  833.                 a = identifieropt(J);
  834.                 semicolon(J);
  835.                 stm = STM1(CONTINUE, a);
  836.         }
  837.  
  838.         else if (jsP_accept(J, TK_BREAK)) {
  839.                 a = identifieropt(J);
  840.                 semicolon(J);
  841.                 stm = STM1(BREAK, a);
  842.         }
  843.  
  844.         else if (jsP_accept(J, TK_RETURN)) {
  845.                 if (J->lookahead != ';' && J->lookahead != '}' && J->lookahead != 0)
  846.                         a = expression(J, 0);
  847.                 else
  848.                         a = NULL;
  849.                 semicolon(J);
  850.                 stm = STM1(RETURN, a);
  851.         }
  852.  
  853.         else if (jsP_accept(J, TK_WITH)) {
  854.                 jsP_expect(J, '(');
  855.                 a = expression(J, 0);
  856.                 jsP_expect(J, ')');
  857.                 b = statement(J);
  858.                 stm = STM2(WITH, a, b);
  859.         }
  860.  
  861.         else if (jsP_accept(J, TK_SWITCH)) {
  862.                 jsP_expect(J, '(');
  863.                 a = expression(J, 0);
  864.                 jsP_expect(J, ')');
  865.                 jsP_expect(J, '{');
  866.                 b = caselist(J);
  867.                 jsP_expect(J, '}');
  868.                 stm = STM2(SWITCH, a, b);
  869.         }
  870.  
  871.         else if (jsP_accept(J, TK_THROW)) {
  872.                 a = expression(J, 0);
  873.                 semicolon(J);
  874.                 stm = STM1(THROW, a);
  875.         }
  876.  
  877.         else if (jsP_accept(J, TK_TRY)) {
  878.                 a = block(J);
  879.                 b = c = d = NULL;
  880.                 if (jsP_accept(J, TK_CATCH)) {
  881.                         jsP_expect(J, '(');
  882.                         b = identifier(J);
  883.                         jsP_expect(J, ')');
  884.                         c = block(J);
  885.                 }
  886.                 if (jsP_accept(J, TK_FINALLY)) {
  887.                         d = block(J);
  888.                 }
  889.                 if (!b && !d)
  890.                         jsP_error(J, "unexpected token in try: %s (expected 'catch' or 'finally')", jsY_tokenstring(J->lookahead));
  891.                 stm = STM4(TRY, a, b, c, d);
  892.         }
  893.  
  894.         else if (jsP_accept(J, TK_DEBUGGER)) {
  895.                 semicolon(J);
  896.                 stm = STM0(DEBUGGER);
  897.         }
  898.  
  899.         else if (jsP_accept(J, TK_FUNCTION)) {
  900.                 jsP_warning(J, "function statements are not standard");
  901.                 stm = funstm(J, line);
  902.         }
  903.  
  904.         /* labelled statement or expression statement */
  905.         else if (J->lookahead == TK_IDENTIFIER) {
  906.                 a = expression(J, 0);
  907.                 if (a->type == EXP_IDENTIFIER && jsP_accept(J, ':')) {
  908.                         a->type = AST_IDENTIFIER;
  909.                         b = statement(J);
  910.                         stm = STM2(LABEL, a, b);
  911.                 } else {
  912.                         semicolon(J);
  913.                         stm = a;
  914.                 }
  915.         }
  916.  
  917.         /* expression statement */
  918.         else {
  919.                 stm = expression(J, 0);
  920.                 semicolon(J);
  921.         }
  922.  
  923.         DECREC();
  924.         return stm;
  925. }
  926.  
  927. /* Program */
  928.  
  929. static js_Ast *scriptelement(js_State *J)
  930. {
  931.         int line = J->lexline;
  932.         if (jsP_accept(J, TK_FUNCTION))
  933.                 return fundec(J, line);
  934.         return statement(J);
  935. }
  936.  
  937. static js_Ast *script(js_State *J, int terminator)
  938. {
  939.         js_Ast *head, *tail;
  940.         if (J->lookahead == terminator)
  941.                 return NULL;
  942.         head = tail = LIST(scriptelement(J));
  943.         while (J->lookahead != terminator)
  944.                 tail = tail->b = LIST(scriptelement(J));
  945.         return jsP_list(head);
  946. }
  947.  
  948. static js_Ast *funbody(js_State *J)
  949. {
  950.         js_Ast *a;
  951.         jsP_expect(J, '{');
  952.         a = script(J, '}');
  953.         jsP_expect(J, '}');
  954.         return a;
  955. }
  956.  
  957. /* Constant folding */
  958.  
  959. static int toint32(double d)
  960. {
  961.         double two32 = 4294967296.0;
  962.         double two31 = 2147483648.0;
  963.  
  964.         if (!isfinite(d) || d == 0)
  965.                 return 0;
  966.  
  967.         d = fmod(d, two32);
  968.         d = d >= 0 ? floor(d) : ceil(d) + two32;
  969.         if (d >= two31)
  970.                 return d - two32;
  971.         else
  972.                 return d;
  973. }
  974.  
  975. static unsigned int touint32(double d)
  976. {
  977.         return (unsigned int)toint32(d);
  978. }
  979.  
  980. static int jsP_setnumnode(js_Ast *node, double x)
  981. {
  982.         node->type = EXP_NUMBER;
  983.         node->number = x;
  984.         node->a = node->b = node->c = node->d = NULL;
  985.         return 1;
  986. }
  987.  
  988. static int jsP_foldconst(js_Ast *node)
  989. {
  990.         double x, y;
  991.         int a, b;
  992.  
  993.         if (node->type == AST_LIST) {
  994.                 while (node) {
  995.                         jsP_foldconst(node->a);
  996.                         node = node->b;
  997.                 }
  998.                 return 0;
  999.         }
  1000.  
  1001.         if (node->type == EXP_NUMBER)
  1002.                 return 1;
  1003.  
  1004.         a = node->a ? jsP_foldconst(node->a) : 0;
  1005.         b = node->b ? jsP_foldconst(node->b) : 0;
  1006.         if (node->c) jsP_foldconst(node->c);
  1007.         if (node->d) jsP_foldconst(node->d);
  1008.  
  1009.         if (a) {
  1010.                 x = node->a->number;
  1011.                 switch (node->type) {
  1012.                 default: break;
  1013.                 case EXP_NEG: return jsP_setnumnode(node, -x);
  1014.                 case EXP_POS: return jsP_setnumnode(node, x);
  1015.                 case EXP_BITNOT: return jsP_setnumnode(node, ~toint32(x));
  1016.                 }
  1017.  
  1018.                 if (b) {
  1019.                         y = node->b->number;
  1020.                         switch (node->type) {
  1021.                         default: break;
  1022.                         case EXP_MUL: return jsP_setnumnode(node, x * y);
  1023.                         case EXP_DIV: return jsP_setnumnode(node, x / y);
  1024.                         case EXP_MOD: return jsP_setnumnode(node, fmod(x, y));
  1025.                         case EXP_ADD: return jsP_setnumnode(node, x + y);
  1026.                         case EXP_SUB: return jsP_setnumnode(node, x - y);
  1027.                         case EXP_SHL: return jsP_setnumnode(node, toint32(x) << (touint32(y) & 0x1F));
  1028.                         case EXP_SHR: return jsP_setnumnode(node, toint32(x) >> (touint32(y) & 0x1F));
  1029.                         case EXP_USHR: return jsP_setnumnode(node, touint32(x) >> (touint32(y) & 0x1F));
  1030.                         case EXP_BITAND: return jsP_setnumnode(node, toint32(x) & toint32(y));
  1031.                         case EXP_BITXOR: return jsP_setnumnode(node, toint32(x) ^ toint32(y));
  1032.                         case EXP_BITOR: return jsP_setnumnode(node, toint32(x) | toint32(y));
  1033.                         }
  1034.                 }
  1035.         }
  1036.  
  1037.         return 0;
  1038. }
  1039.  
  1040. /* Main entry point */
  1041.  
  1042. js_Ast *jsP_parse(js_State *J, const char *filename, const char *source)
  1043. {
  1044.         js_Ast *p;
  1045.  
  1046.         jsY_initlex(J, filename, source);
  1047.         jsP_next(J);
  1048.         J->astdepth = 0;
  1049.         p = script(J, 0);
  1050.         if (p)
  1051.                 jsP_foldconst(p);
  1052.  
  1053.         return p;
  1054. }
  1055.  
  1056. js_Ast *jsP_parsefunction(js_State *J, const char *filename, const char *params, const char *body)
  1057. {
  1058.         js_Ast *p = NULL;
  1059.         int line = 0;
  1060.         if (params) {
  1061.                 jsY_initlex(J, filename, params);
  1062.                 jsP_next(J);
  1063.                 J->astdepth = 0;
  1064.                 p = parameters(J);
  1065.         }
  1066.         return EXP3(FUN, NULL, p, jsP_parse(J, filename, body));
  1067. }
  1068.