basant307/AI_Governance_Project
048
1'use strict'2 3// The ABNF grammar in the spec is totally ambiguous.4//5// This parser follows the operator precedence defined in the6// `Order of Precedence and Parentheses` section.7 8module.exports = function (tokens) {9 var index = 010 11 function hasMore () {12 return index < tokens.length13 }14 15 function token () {16 return hasMore() ? tokens[index] : null17 }18 19 function next () {20 if (!hasMore()) {21 throw new Error()22 }23 index++24 }25 26 function parseOperator (operator) {27 var t = token()28 if (t && t.type === 'OPERATOR' && operator === t.string) {29 next()30 return t.string31 }32 }33 34 function parseWith () {35 if (parseOperator('WITH')) {36 var t = token()37 if (t && t.type === 'EXCEPTION') {38 next()39 return t.string40 }41 throw new Error('Expected exception after `WITH`')42 }43 }44 45 function parseLicenseRef () {46 // TODO: Actually, everything is concatenated into one string47 // for backward-compatibility but it could be better to return48 // a nice structure.49 var begin = index50 var string = ''51 var t = token()52 if (t.type === 'DOCUMENTREF') {53 next()54 string += 'DocumentRef-' + t.string + ':'55 if (!parseOperator(':')) {56 throw new Error('Expected `:` after `DocumentRef-...`')57 }58 }59 t = token()60 if (t.type === 'LICENSEREF') {61 next()62 string += 'LicenseRef-' + t.string63 return { license: string }64 }65 index = begin66 }67 68 function parseLicense () {69 var t = token()70 if (t && t.type === 'LICENSE') {71 next()72 var node = { license: t.string }73 if (parseOperator('+')) {74 node.plus = true75 }76 var exception = parseWith()77 if (exception) {78 node.exception = exception79 }80 return node81 }82 }83 84 function parseParenthesizedExpression () {85 var left = parseOperator('(')86 if (!left) {87 return88 }89 90 var expr = parseExpression()91 92 if (!parseOperator(')')) {93 throw new Error('Expected `)`')94 }95 96 return expr97 }98 99 function parseAtom () {100 return (101 parseParenthesizedExpression() ||102 parseLicenseRef() ||103 parseLicense()104 )105 }106 107 function makeBinaryOpParser (operator, nextParser) {108 return function parseBinaryOp () {109 var left = nextParser()110 if (!left) {111 return112 }113 114 if (!parseOperator(operator)) {115 return left116 }117 118 var right = parseBinaryOp()119 if (!right) {120 throw new Error('Expected expression')121 }122 return {123 left: left,124 conjunction: operator.toLowerCase(),125 right: right126 }127 }128 }129 130 var parseAnd = makeBinaryOpParser('AND', parseAtom)131 var parseExpression = makeBinaryOpParser('OR', parseAnd)132 133 var node = parseExpression()134 if (!node || hasMore()) {135 throw new Error('Syntax error')136 }137 return node138}139 