You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
2.7 KiB
131 lines
2.7 KiB
'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 |
|
}
|
|
|