parser.js
function parse_tag (str, parsers) {
  if (typeof str !== 'string' || str[0] !== '@') { return null }

  var data = parsers.reduce(function (state, parser) {
    var result

    try {
      result = parser(state.source, merge({}, state.data))
    } catch (err) {
      state.data.errors = (state.data.errors || [])
        .concat(parser.name + ': ' + err.message)
    }

    if (result) {
      state.source = state.source.slice(result.source.length)
      state.data = merge(state.data, result.data)
    }

    return state
  }, {
    source: str,
    data: {}
  }).data

  data.optional = !!data.optional
  data.type = data.type === undefined ? '' : data.type
  data.name = data.name === undefined ? '' : data.name
  data.description = data.description === undefined ? '' : data.description

  return data
}
function parse_tag (str, parsers) {
  if (typeof str !== 'string' || str[0] !== '@') { return null }

  var data = parsers.reduce(function (state, parser) {
    var result

    try {
      result = parser(state.source, merge({}, state.data))
    } catch (err) {
      state.data.errors = (state.data.errors || [])
        .concat(parser.name + ': ' + err.message)
    }

    if (result) {
      state.source = state.source.slice(result.source.length)
      state.data = merge(state.data, result.data)
    }

    return state
  }, {
    source: str,
    data: {}
  }).data

  data.optional = !!data.optional
  data.type = data.type === undefined ? '' : data.type
  data.name = data.name === undefined ? '' : data.name
  data.description = data.description === undefined ? '' : data.description

  return data
}
/* ------- parsing ------- 
Parses "@tag {type} name description"
@param {string} str Raw doc string
@param {Array[function]} parsers Array of parsers to be applied to the source
@returns {object} parsed tag node