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