function parseCustomNodes (state) {
    let params = []

    if (state.tokenType === TOKENTYPE.SYMBOL && hasOwnProperty(state.extraNodes, state.token)) {
      const CustomNode = state.extraNodes[state.token]

      getToken(state)

      // parse parameters
      if (state.token === '(') {
        params = []

        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)
      }

      // create a new custom node
      // noinspection JSValidateTypes
      return new CustomNode(params)
    }

    return parseSymbol(state)
  }
Parse a custom node handler. A node handler can be used to process
nodes in a custom way, for example for handling a plot.

A handler must be passed as second argument of the parse function.
- must extend math.Node
- must contain a function _compile(defs: Object) : string
- must contain a function find(filter: Object) : Node[]
- must contain a function toString() : string
- the constructor is called with a single argument containing all parameters

For example:

    nodes = {
      'plot': PlotHandler
    }

The constructor of the handler is called as:

    node = new PlotHandler(params)

The handler will be invoked when evaluating an expression like:

    node = math.parse('plot(sin(x), x)', nodes)

@return {Node} node
@private