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.
|
|
'use strict'
// The ABNF grammar in the spec is totally ambiguous.
//
// This parser follows the operator precedence defined in the
// `Order of Precedence and Parentheses` section.
module.exports = function (tokens) { var index = 0
function hasMore () { return index < tokens.length }
function token () { return hasMore() ? tokens[index] : null }
function next () { if (!hasMore()) { throw new Error() } index++ }
function parseOperator (operator) { var t = token() if (t && t.type === 'OPERATOR' && operator === t.string) { next() return t.string } }
function parseWith () { if (parseOperator('WITH')) { var t = token() if (t && t.type === 'EXCEPTION') { next() return t.string } throw new Error('Expected exception after `WITH`') } }
function parseLicenseRef () { // TODO: Actually, everything is concatenated into one string
// for backward-compatibility but it could be better to return
// a nice structure.
var begin = index var string = '' var t = token() if (t.type === 'DOCUMENTREF') { next() string += 'DocumentRef-' + t.string + ':' if (!parseOperator(':')) { throw new Error('Expected `:` after `DocumentRef-...`') } } t = token() if (t.type === 'LICENSEREF') { next() string += 'LicenseRef-' + t.string return { license: string } } index = begin }
function parseLicense () { var t = token() if (t && t.type === 'LICENSE') { next() var node = { license: t.string } if (parseOperator('+')) { node.plus = true } var exception = parseWith() if (exception) { node.exception = exception } return node } }
function parseParenthesizedExpression () { var left = parseOperator('(') if (!left) { return }
var expr = parseExpression()
if (!parseOperator(')')) { throw new Error('Expected `)`') }
return expr }
function parseAtom () { return ( parseParenthesizedExpression() || parseLicenseRef() || parseLicense() ) }
function makeBinaryOpParser (operator, nextParser) { return function parseBinaryOp () { var left = nextParser() if (!left) { return }
if (!parseOperator(operator)) { return left }
var right = parseBinaryOp() if (!right) { throw new Error('Expected expression') } return { left: left, conjunction: operator.toLowerCase(), right: right } } }
var parseAnd = makeBinaryOpParser('AND', parseAtom) var parseExpression = makeBinaryOpParser('OR', parseAnd)
var node = parseExpression() if (!node || hasMore()) { throw new Error('Syntax error') } return node }
|