实现示例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'] : [] } } 审计与发布治理审计表达式与冲突结果;命中禁止许可证阻断并输出建议。例外审批需设到期与影响范围;产线默认拒绝未审批项。

发表评论 取消回复