# All files / src/parser for-loop.js

100% Statements 30/30
80% Branches 8/10
100% Functions 2/2
100% Lines 30/30

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    28x
    28x
    28x

    28x

    28x
    4x
    4x
    4x
    4x
    12x
    12x
    12x
    12x

    4x
    4x

    28x
    4x
    4x

    4x
    4x
    4x

    4x

    4x

    4x
    4x
    7x
    7x
    4x

    4x

    4x

     // @flow
    import Syntax from "../Syntax";
    import expression from "./expression";
    import statement from "./statement";
    import type Context from "./context";
    import type { NodeType } from "../flow/types";

    const reverse = {
      ">": "<=",
      "<": ">=",
      ">=": "<",
      "<=": ">",
      "==": "!=",
      "!=": "==",
    };

    const paramList = (ctx: Context): NodeType[] => {
      ctx.expect(["("]);
      const params: NodeType[] = [];
      let node = null;
      while (ctx.token.value && ctx.token.value !== ")") {
        node = expression(ctx);
        Eif (node) {
          params.push(node);
          ctx.eat([";"]);
        }
      }

      ctx.expect([")"]);
      return params;
    };

    const forLoop = (ctx: Context): NodeType => {
      const node = ctx.startNode();
      ctx.eat(["for"]);

      // Pop the last expression from param list to append to the body of the loop.
      // This is important to do here as it'll be more difficult to acomplish later
      // in the generator accurately. In a for-loop we always want the afterthought
      // to follow the entire body, so here we are.
      const [initializer, condition, afterthought] = paramList(ctx);
      Eif (reverse[condition.value]) {
        condition.value = reverse[condition.value];
      }
      const body = [];

      ctx.expect(["{"]);

      let stmt = null;
      while (ctx.token && ctx.token.value !== "}") {
        stmt = statement(ctx);
        if (stmt) {
          body.push(stmt);
        }
      }
      ctx.expect(["}"]);

      return ctx.endNode(
        {
          ...node,
          params: [initializer, condition, ...body, afterthought],
        },
        Syntax.Loop
      );
    };

    export default forLoop;