docs: private AstNode let(boolean isStatement, int pos)
          throws IOException
      {
          LetNode pn = new LetNode(pos);
          pn.setLineno(ts.lineno);
          if (mustMatchToken(Token.LP, "msg.no.paren.after.let", true))
              pn.setLp(ts.tokenBeg - pos);
          pushScope(pn);
          try {
              VariableDeclaration vars = variables(Token.LET, ts.tokenBeg, isStatement);
              pn.setVariables(vars);
              if (mustMatchToken(Token.RP, "msg.no.paren.let", true)) {
                  pn.setRp(ts.tokenBeg - pos);
              }
              if (isStatement && peekToken() == Token.LC) {
                  // let statement
                  consumeToken();
                  int beg = ts.tokenBeg;  // position stmt at LC
                  AstNode stmt = statements();
                  mustMatchToken(Token.RC, "msg.no.curly.let", true);
                  stmt.setLength(ts.tokenEnd - beg);
                  pn.setLength(ts.tokenEnd - pos);
                  pn.setBody(stmt);
                  pn.setType(Token.LET);
              } else {
                  // let expression
                  AstNode expr = expr();
                  pn.setLength(getNodeEnd(expr) - pos);
                  pn.setBody(expr);
                  if (isStatement) {
                      // let expression in statement context
                      ExpressionStatement es =
                              new ExpressionStatement(pn, !insideFunction());
                      es.setLineno(pn.getLineno());
                      return es;
                  }
              }
          } finally {
              popScope();
          }
          return pn;
      }