11cb0ef41Sopenharmony_ci'use strict' 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_civar licenses = [] 41cb0ef41Sopenharmony_ci .concat(require('spdx-license-ids')) 51cb0ef41Sopenharmony_ci .concat(require('spdx-license-ids/deprecated')) 61cb0ef41Sopenharmony_civar exceptions = require('spdx-exceptions') 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_cimodule.exports = function (source) { 91cb0ef41Sopenharmony_ci var index = 0 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ci function hasMore () { 121cb0ef41Sopenharmony_ci return index < source.length 131cb0ef41Sopenharmony_ci } 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ci // `value` can be a regexp or a string. 161cb0ef41Sopenharmony_ci // If it is recognized, the matching source string is returned and 171cb0ef41Sopenharmony_ci // the index is incremented. Otherwise `undefined` is returned. 181cb0ef41Sopenharmony_ci function read (value) { 191cb0ef41Sopenharmony_ci if (value instanceof RegExp) { 201cb0ef41Sopenharmony_ci var chars = source.slice(index) 211cb0ef41Sopenharmony_ci var match = chars.match(value) 221cb0ef41Sopenharmony_ci if (match) { 231cb0ef41Sopenharmony_ci index += match[0].length 241cb0ef41Sopenharmony_ci return match[0] 251cb0ef41Sopenharmony_ci } 261cb0ef41Sopenharmony_ci } else { 271cb0ef41Sopenharmony_ci if (source.indexOf(value, index) === index) { 281cb0ef41Sopenharmony_ci index += value.length 291cb0ef41Sopenharmony_ci return value 301cb0ef41Sopenharmony_ci } 311cb0ef41Sopenharmony_ci } 321cb0ef41Sopenharmony_ci } 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ci function skipWhitespace () { 351cb0ef41Sopenharmony_ci read(/[ ]*/) 361cb0ef41Sopenharmony_ci } 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci function operator () { 391cb0ef41Sopenharmony_ci var string 401cb0ef41Sopenharmony_ci var possibilities = ['WITH', 'AND', 'OR', '(', ')', ':', '+'] 411cb0ef41Sopenharmony_ci for (var i = 0; i < possibilities.length; i++) { 421cb0ef41Sopenharmony_ci string = read(possibilities[i]) 431cb0ef41Sopenharmony_ci if (string) { 441cb0ef41Sopenharmony_ci break 451cb0ef41Sopenharmony_ci } 461cb0ef41Sopenharmony_ci } 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci if (string === '+' && index > 1 && source[index - 2] === ' ') { 491cb0ef41Sopenharmony_ci throw new Error('Space before `+`') 501cb0ef41Sopenharmony_ci } 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci return string && { 531cb0ef41Sopenharmony_ci type: 'OPERATOR', 541cb0ef41Sopenharmony_ci string: string 551cb0ef41Sopenharmony_ci } 561cb0ef41Sopenharmony_ci } 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci function idstring () { 591cb0ef41Sopenharmony_ci return read(/[A-Za-z0-9-.]+/) 601cb0ef41Sopenharmony_ci } 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci function expectIdstring () { 631cb0ef41Sopenharmony_ci var string = idstring() 641cb0ef41Sopenharmony_ci if (!string) { 651cb0ef41Sopenharmony_ci throw new Error('Expected idstring at offset ' + index) 661cb0ef41Sopenharmony_ci } 671cb0ef41Sopenharmony_ci return string 681cb0ef41Sopenharmony_ci } 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci function documentRef () { 711cb0ef41Sopenharmony_ci if (read('DocumentRef-')) { 721cb0ef41Sopenharmony_ci var string = expectIdstring() 731cb0ef41Sopenharmony_ci return { type: 'DOCUMENTREF', string: string } 741cb0ef41Sopenharmony_ci } 751cb0ef41Sopenharmony_ci } 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci function licenseRef () { 781cb0ef41Sopenharmony_ci if (read('LicenseRef-')) { 791cb0ef41Sopenharmony_ci var string = expectIdstring() 801cb0ef41Sopenharmony_ci return { type: 'LICENSEREF', string: string } 811cb0ef41Sopenharmony_ci } 821cb0ef41Sopenharmony_ci } 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ci function identifier () { 851cb0ef41Sopenharmony_ci var begin = index 861cb0ef41Sopenharmony_ci var string = idstring() 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci if (licenses.indexOf(string) !== -1) { 891cb0ef41Sopenharmony_ci return { 901cb0ef41Sopenharmony_ci type: 'LICENSE', 911cb0ef41Sopenharmony_ci string: string 921cb0ef41Sopenharmony_ci } 931cb0ef41Sopenharmony_ci } else if (exceptions.indexOf(string) !== -1) { 941cb0ef41Sopenharmony_ci return { 951cb0ef41Sopenharmony_ci type: 'EXCEPTION', 961cb0ef41Sopenharmony_ci string: string 971cb0ef41Sopenharmony_ci } 981cb0ef41Sopenharmony_ci } 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci index = begin 1011cb0ef41Sopenharmony_ci } 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci // Tries to read the next token. Returns `undefined` if no token is 1041cb0ef41Sopenharmony_ci // recognized. 1051cb0ef41Sopenharmony_ci function parseToken () { 1061cb0ef41Sopenharmony_ci // Ordering matters 1071cb0ef41Sopenharmony_ci return ( 1081cb0ef41Sopenharmony_ci operator() || 1091cb0ef41Sopenharmony_ci documentRef() || 1101cb0ef41Sopenharmony_ci licenseRef() || 1111cb0ef41Sopenharmony_ci identifier() 1121cb0ef41Sopenharmony_ci ) 1131cb0ef41Sopenharmony_ci } 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_ci var tokens = [] 1161cb0ef41Sopenharmony_ci while (hasMore()) { 1171cb0ef41Sopenharmony_ci skipWhitespace() 1181cb0ef41Sopenharmony_ci if (!hasMore()) { 1191cb0ef41Sopenharmony_ci break 1201cb0ef41Sopenharmony_ci } 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci var token = parseToken() 1231cb0ef41Sopenharmony_ci if (!token) { 1241cb0ef41Sopenharmony_ci throw new Error('Unexpected `' + source[index] + 1251cb0ef41Sopenharmony_ci '` at offset ' + index) 1261cb0ef41Sopenharmony_ci } 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ci tokens.push(token) 1291cb0ef41Sopenharmony_ci } 1301cb0ef41Sopenharmony_ci return tokens 1311cb0ef41Sopenharmony_ci} 132