@fordi-org/bsimp

中文文档
1.0.4发布于 2023/02/21ISCESM + CJS零依赖近 30 天下载 2718

A boolean expression simplifier

原始使用文档
文档目录12 节
  1. parse(string)
  2. toString(expression)
  3. simplify(expression, [steps])
  4. symbolize(termStr)
  5. term(termStr)
  6. Expression Objects
  7. Expression strings
  8. Polish notation
  9. Infix notation
  10. Ternary
  11. Implicit AND
  12. Development concerns

bsimp

A boolean expression simplifier

Demo

parse(string)

Convert a string representation of a logical expression into an expression object

import { parse } from '@fordi-org/bsimp/parse';

console.log(parse('A+A!B'));
[
  Symbol( ∪ ),
  Symbol(A),
  [ Symbol( ∩ ), Symbol(A), [ Symbol(!), Symbol(B) ] ]
]

toString(expression)

Convert an expression object into a string

import { parse, toString, SET } from '@fordi-org/bsimp';

console.log(toString(parse('A+A!B'), SET));
console.log(toString(parse('A+A!B'), LOGIC));
console.log(toString(parse('A+A!B'), POLISH));
console.log(toString(parse('A+A!B'), SOURCE));
A ∪ (A ∖ B)
A+A!B
(∪ A (∩ A !B))
[OR, A, [AND, A, [NOT, B]]]

simplify(expression, [steps])

Simplify a symbolized boolean expression. Optionally, pass an array to collect steps.

import { simplify, parse, toString, LOGIC } from '@fordi-org/bsimp/simplify';

const toSimplify = [
  'A+B!C+C!A',
  'AB!C+ABC+A!B!C+B!A!C',
];

const result = toSimplify.map(expStr => {
  const exp = parse(expStr);
  const steps = [];
  const simple = simplify(exp, steps);
  return {
    simplified: toString(simple, LOGIC),
    steps,
  };
});

console.log(result);
[ 
  {
    simplified: 'A+B+C',
    steps: [
      [
        'absorption',
        null,
        [OR, A, [AND, B, [NOT, C]], [AND, C, [NOT, A]]],
        [OR, A, C, B]
      ]
    ]
  },
  {
    simplified: 'AB+A!C+B!C',
    steps: [...],
  }
]

The structure of a step is a tuple of [transform, parentOperation, fromExpr, toExpr].

symbolize(termStr)

Convert a string into a symbol. For AND, OR, NOT, TRUE, and FALSE, this will convert the string to the internal symbol. For any other string, you'll get term(termStr).

term(termStr)

Convert a string into a symbol. For any previously named term, you'll get the same symbol back for the same input string (this differs from how Symbol(termStr) works, in that every Symbol that is created is unique).


Expression Objects

Formally...

  • Expression: [Operator, ...Operand]
  • Operator: AND | OR | NOT
  • Operand: TRUE | FALSE | Symbol | Expression

That is, it's an array where the first element must be an Operator, and all the following symbols must be Operands. Operators are the symbols AND, OR, and NOT (exported from @fordi-org/bsimp). Operands can be the symbols TRUE or FALSE, another Expression, or any user-defined Symbol.

Expression strings

The grammar is very forgiving, and allows the use of the following:

Polish notation

{OP} {TERM} {TERM}*

e.g.,

"(and A B C)" becomes [AND, A, B, C]

Infix notation

{TERM} ({OP} {TERM})*

e.g.,

(P | Q | R) becomes [OR, P, Q, R]

Ternary

The parser understands Ternary expressions, and the CODE stringifier knows how to convert expressions to them, however, they are expressed as a logical combination of AND, OR, and NOT. A ternary, if you're unaware, is like an if / then / else statment, where each piece is a term.

So, C ? T : F evaluates to [OR, [AND, C, T], [AND, [NOT, C], F]]. You can nest ternaries, but they must be grouped to avoid ambiguity.

Support for ternaries is meant to be an assist in passing expressions into the simplifier - while the CODE stringifier can identify and subsume the simple form of this pattern, nested ternaries will usually be simplified into something the CODE stringifier cannot identify (for example, a ? (b ? c : d) : e will become (a && b && c) || (e && !a) || (a && !b && d), which is not ideal).

I may work more on this, but ternary support was initially meant to be for input.

Implicit AND

{TERM}{TERM}*

e.g.,

XYZ becomes [AND, X, Y, Z]

Note: because of the need for implicit AND, the parser limits terms to single-letter, case-sensitive. The simplifier is not so-limited, and you can do something like this:

const [a, b] = [
  term('longName'),
  term('longerName'),
];
const simple = simplify([OR, a, [AND, a, [NOT, b]]]);

The two use cases I had in mind were a boolean simplifier for linters (where the linter could choose completely random symbol names), and an on-page logic simplifier widget (where a user can enter tight logic strings and get back their simplification).


Development concerns

To run the test suite:

npm run test

To compile the boolean grammar:

npm run build:peg

To build the whole thing:

npm run build

版本与发布记录

@fordi-org/bsimp 共发布 5 个版本,首次发布于 2022/07/26;过去 12 个月发布了 0 个版本。

版本发布日期距今
1.0.4latest2023/02/213 年前
1.0.32022/11/233 年前
1.0.22022/07/264 年前
1.0.12022/07/264 年前
1.0.02022/07/264 年前

关于 @fordi-org/bsimp 的常见问题

@fordi-org/bsimp 是什么?

A boolean expression simplifier

如何安装 @fordi-org/bsimp?

在项目目录运行 npm install @fordi-org/bsimp,或使用 pnpm add / yarn add / bun add。

@fordi-org/bsimp 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/fordi-org__bsimp 是否存在。

@fordi-org/bsimp 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@fordi-org/bsimp 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=16.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@fordi-org/bsimp 可以商用吗?

@fordi-org/bsimp 使用 ISC 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@fordi-org/bsimp 的下载量有多少?

根据 npm 官方下载统计,@fordi-org/bsimp 在 2026/10/16 – 2026/11/14 这 30 天内被下载 2,718 次,日均约 91 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@fordi-org/bsimp 还在维护吗?

最新版本 1.0.4 发布于 2023/02/21(3 年前);至今共发布 5 个版本,其中过去 12 个月发布了 0 个;首次发布于 2022/07/26。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。