function parseAccessors (state, node, types) {
    let params

    while ((state.token === '(' || state.token === '[' || state.token === '.') &&
        (!types || types.includes(state.token))) { // eslint-disable-line no-unmodified-loop-condition
      params = []

      if (state.token === '(') {
        if (isSymbolNode(node) || isAccessorNode(node)) {
          // function invocation like fn(2, 3) or obj.fn(2, 3)
          openParams(state)
          getToken(state)

          if (state.token !== ')') {
            params.push(parseAssignment(state))

            // parse a list with parameters
            while (state.token === ',') { // eslint-disable-line no-unmodified-loop-condition
              getToken(state)
              params.push(parseAssignment(state))
            }
          }

          if (state.token !== ')') {
            throw createSyntaxError(state, 'Parenthesis ) expected')
          }
          closeParams(state)
          getToken(state)

          node = new FunctionNode(node, params)
        } else {
          // implicit multiplication like (2+3)(4+5) or sqrt(2)(1+2)
          // don't parse it here but let it be handled by parseImplicitMultiplication
          // with correct precedence
          return node
        }
      } else if (state.token === '[') {
        // index notation like variable[2, 3]
        openParams(state)
        getToken(state)

        if (state.token !== ']') {
          params.push(parseAssignment(state))

          // parse a list with parameters
          while (state.token === ',') { // eslint-disable-line no-unmodified-loop-condition
            getToken(state)
            params.push(parseAssignment(state))
          }
        }

        if (state.token !== ']') {
          throw createSyntaxError(state, 'Parenthesis ] expected')
        }
        closeParams(state)
        getToken(state)

        node = new AccessorNode(node, new IndexNode(params))
      } else {
        // dot notation like variable.prop
        getToken(state)

        const isPropertyName = state.tokenType === TOKENTYPE.SYMBOL ||
          (state.tokenType === TOKENTYPE.DELIMITER && state.token in NAMED_DELIMITERS)
        if (!isPropertyName) {
          throw createSyntaxError(state, 'Property name expected after dot')
        }

        params.push(new ConstantNode(state.token))
        getToken(state)

        const dotNotation = true
        node = new AccessorNode(node, new IndexNode(params, dotNotation))
      }
    }

    return node
  }
parse accessors:
- function invocation in round brackets (...), for example sqrt(2)
- index enclosed in square brackets [...], for example A[2,3]
- dot notation for properties, like foo.bar
@param {Object} state
@param {Node} node    Node on which to apply the parameters. If there
                      are no parameters in the expression, the node
                      itself is returned
@param {string[]} [types]  Filter the types of notations
                           can be ['(', '[', '.']
@return {Node} node
@private