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