实现示例type Node = { type: 'ID' | 'AND' | 'OR' | 'WITH'; left?: Node; right?: Node; id?: string; exception?: string }

function tokenize(expr: string): string[] { return expr.replace(/\(|\)/g, m => ` ${m} `).trim().split(/\s+/) }

function parse(tokens: string[]): Node {

const stack: Node[] = []

const ops: string[] = []

function reduce(op: string) {

const r = stack.pop() as Node

const l = stack.pop() as Node

stack.push({ type: op as any, left: l, right: r })

}

for (const t of tokens) {

if (t === '(') ops.push(t)

else if (t === ')') { while (ops.length && ops[ops.length - 1] !== '(') reduce(ops.pop() as string); ops.pop() }

else if (t === 'AND' || t === 'OR') { while (ops.length && ops[ops.length - 1] !== '(') reduce(ops.pop() as string); ops.push(t) }

else if (t === 'WITH') { const prev = stack.pop() as Node; const next = tokens.shift() as string; stack.push({ type: 'WITH', left: prev, right: { type: 'ID', id: next }, exception: next }) }

else stack.push({ type: 'ID', id: t })

}

while (ops.length) reduce(ops.pop() as string)

return stack[0]

}

function containsDenied(ast: Node, deny: Set<string>): boolean {

if (ast.type === 'ID') return deny.has(ast.id || '')

if (ast.type === 'WITH') return deny.has(ast.left?.id || '')

if (ast.type === 'AND') return containsDenied(ast.left as Node, deny) || containsDenied(ast.right as Node, deny)

if (ast.type === 'OR') return containsDenied(ast.left as Node, deny) && containsDenied(ast.right as Node, deny)

return false

}

function evaluate(expr: string, deny: Set<string>): { ok: boolean; errors: string[] } {

const tokens = tokenize(expr)

const ast = parse(tokens)

const bad = containsDenied(ast, deny)

return { ok: !bad, errors: bad ? ['license-denied'] : [] }

}

审计与发布治理审计表达式与冲突结果;命中禁止许可证阻断并输出建议。例外审批需设到期与影响范围;产线默认拒绝未审批项。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部