# All files / src/parser maybe-function-declaration.js

97.06% Statements 33/34
92.86% Branches 13/14
100% Functions 4/4
97.06% Lines 33/34

    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
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    28x
    28x
    28x
    28x

    28x
    144x
    144x

    144x
    144x

    28x
    144x
    144x
    127x

    127x
    127x
    123x

    4x
    4x

    17x

    155x
    11x

    144x
    144x
    144x
    144x

    144x
    144x
    144x
    543x
    543x
    281x

    144x

    144x

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

    export const parseArguments = (ctx: Context): NodeType => {
      ctx.expect(["("]);
      const argumentsNode = ctx.makeNode(
        {
          params: [expression(ctx)],
          value: "FUNCTION_ARGUMENTS",
        },
        Syntax.FunctionArguments
      );
      ctx.expect([")"]);
      return argumentsNode;
    };

    export const parseFunctionResult = (ctx: Context): NodeType => {
      const baseNode: NodeType = ctx.startNode();
      if (ctx.eat([":"])) {
        return ctx.endNode(
          {
            ...baseNode,
            value: ctx.token.value,
            type: (() => {
              const value = ctx.token.value;
              if (ctx.eat(null, Syntax.Type)) {
                return value === "void" ? null : value;
              }

              Eif (ctx.eat(null, Syntax.Identifier)) {
                return "i32";
              }

              return "i32";
            })(),
          },
          Syntax.FunctionResult
        );
      }

      return ctx.endNode(
        {
          ...baseNode,
          value: "FUNCTION_RESULT",
        },
        Syntax.FunctionResult
      );
    };

    export default function maybeFunctionDeclaration(ctx: Context): NodeType {
      if (!ctx.eat(["function"])) {
        return declaration(ctx);
      }

      const node = ctx.startNode();
      const value = ctx.expect(null, Syntax.Identifier).value;
      const argumentsNode = parseArguments(ctx);
      const resultNode = parseFunctionResult(ctx);

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

      return ctx.endNode(
        {
          ...node,
          value,
          params: [argumentsNode, resultNode, ...statements],
        },
        Syntax.FunctionDeclaration
      );
    }