| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 | 'use strict'var licenses = []  .concat(require('spdx-license-ids'))  .concat(require('spdx-license-ids/deprecated'))var exceptions = require('spdx-exceptions')module.exports = function (source) {  var index = 0  function hasMore () {    return index < source.length  }  // `value` can be a regexp or a string.  // If it is recognized, the matching source string is returned and  // the index is incremented. Otherwise `undefined` is returned.  function read (value) {    if (value instanceof RegExp) {      var chars = source.slice(index)      var match = chars.match(value)      if (match) {        index += match[0].length        return match[0]      }    } else {      if (source.indexOf(value, index) === index) {        index += value.length        return value      }    }  }  function skipWhitespace () {    read(/[ ]*/)  }  function operator () {    var string    var possibilities = ['WITH', 'AND', 'OR', '(', ')', ':', '+']    for (var i = 0; i < possibilities.length; i++) {      string = read(possibilities[i])      if (string) {        break      }    }    if (string === '+' && index > 1 && source[index - 2] === ' ') {      throw new Error('Space before `+`')    }    return string && {      type: 'OPERATOR',      string: string    }  }  function idstring () {    return read(/[A-Za-z0-9-.]+/)  }  function expectIdstring () {    var string = idstring()    if (!string) {      throw new Error('Expected idstring at offset ' + index)    }    return string  }  function documentRef () {    if (read('DocumentRef-')) {      var string = expectIdstring()      return {type: 'DOCUMENTREF', string: string}    }  }  function licenseRef () {    if (read('LicenseRef-')) {      var string = expectIdstring()      return {type: 'LICENSEREF', string: string}    }  }  function identifier () {    var begin = index    var string = idstring()    if (licenses.indexOf(string) !== -1) {      return {        type: 'LICENSE',        string: string      }    } else if (exceptions.indexOf(string) !== -1) {      return {        type: 'EXCEPTION',        string: string      }    }    index = begin  }  // Tries to read the next token. Returns `undefined` if no token is  // recognized.  function parseToken () {    // Ordering matters    return (      operator() ||      documentRef() ||      licenseRef() ||      identifier()    )  }  var tokens = []  while (hasMore()) {    skipWhitespace()    if (!hasMore()) {      break    }    var token = parseToken()    if (!token) {      throw new Error('Unexpected `' + source[index] +                      '` at offset ' + index)    }    tokens.push(token)  }  return tokens}
 |