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