codemirror-lang-dimacs 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (C) 2026 by Johannes Schuster <johannes.c.schuster@proton.me>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/NOTICE ADDED
@@ -0,0 +1,8 @@
1
+ lang-dimacs is licensed under the MIT licence in LICENSE.
2
+
3
+ The Lezer grammar (dimacs.grammar) and the tests are written by hand. What they accept
4
+ was worked out by reading the DIMACS and solution parser of CaDiCaL
5
+ (https://github.com/arminbiere/cadical, src/parse.cpp; version and checksum in
6
+ spec/SOURCE of the lang-dimacs repository), which is MIT-licensed, Copyright (c) Armin
7
+ Biere and others. No CaDiCaL code is copied. CaDiCaL itself is used only as a test
8
+ oracle and is not distributed.
package/README.md CHANGED
@@ -1,3 +1,79 @@
1
- # Temporary Holding Version
1
+ # codemirror-lang-dimacs
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ DIMACS CNF language support for [CodeMirror 6](https://codemirror.net/): a Lezer parser
4
+ for the dialects that [CaDiCaL](https://github.com/arminbiere/cadical) reads, with
5
+ highlighting.
6
+
7
+ ```js
8
+ import {EditorView, basicSetup} from "codemirror"
9
+ import {dimacs} from "codemirror-lang-dimacs"
10
+
11
+ new EditorView({extensions: [basicSetup, dimacs()], parent: document.body})
12
+ ```
13
+
14
+ For solver output in the SAT competition format (`s` and `v` lines), configure the
15
+ second top rule:
16
+
17
+ ```js
18
+ import {LanguageSupport} from "@codemirror/language"
19
+ import {dimacsLanguage} from "codemirror-lang-dimacs"
20
+
21
+ new LanguageSupport(dimacsLanguage.configure({top: "Solution"}))
22
+ ```
23
+
24
+ ## Scope
25
+
26
+ - `p cnf <max-var> <num-clauses>` and `p inccnf` files, with comments and, after the
27
+ clauses, cubes (`a <literals> 0`).
28
+ - Solutions: comments, one status line `s SATISFIABLE`, `s UNSATISFIABLE` or `s UNKNOWN`,
29
+ then `v` lines.
30
+
31
+ Not covered: `p sat`, WCNF, QDIMACS, XOR lines, `p knf`. CaDiCaL rejects every problem
32
+ line but `p cnf` and `p inccnf`.
33
+
34
+ The parser is permissive: it accepts any white space (space, tab, CR, LF) in the problem
35
+ line, cubes after a `p cnf` header, and header counts that do not match the body.
36
+ Checking those is left to a linter; this package has none.
37
+
38
+ ## What CaDiCaL accepts
39
+
40
+ Read from `src/parse.cpp` of CaDiCaL 3.0.1 (source and checksum in `spec/SOURCE` of the
41
+ repository) and checked against its `cadical` binary with the files in `fixtures/`.
42
+
43
+ 1. Before the problem line, lines starting with `c` are comments, and white space
44
+ (space, tab, CR, LF) before them is skipped. A header comment must end with a newline.
45
+ 2. In a header comment, the text from the first `-` to the end of the line is passed to
46
+ CaDiCaL as an option; only `--name[=value]` takes effect. Comments after the problem
47
+ line are not read for options.
48
+ 3. Problem line: `p cnf <max-var> <num-clauses>`, or `p inccnf` without numbers, ended by
49
+ a newline. Between `p` and the format any spaces and tabs; between the format and the
50
+ numbers any white space (C `isspace`), newlines included. (`--strict` demands single spaces.)
51
+ 4. In the body, space, tab, CR and LF separate tokens. A literal is an optional `-` and
52
+ digits, followed by white space, end of file or `c`. Leading zeros are allowed: `007`
53
+ is `7`, and `0`, `00` and `-0` all end a clause. Clauses may span lines and share
54
+ them.
55
+ 5. `c` at the start of a token starts a comment to the end of the line, also directly
56
+ after a literal (`1 -2 0c note`).
57
+ 6. `p inccnf` only: the first `a` at the start of a token ends the clauses. Each cube is
58
+ `a`, literals, `0`; an `a` before that `0` is an error. After a cube's `0` only white
59
+ space, another `a` or the end of the file may follow, and a comment only if it runs to
60
+ the end of the file.
61
+ 7. `a` in a `p cnf` file is an error.
62
+ 8. Unless `--force` is given, the clause count must match and no literal may exceed
63
+ `<max-var>`.
64
+ 9. A solution (`cadical -r`) is: lines starting with `c`, then exactly `s SATISFIABLE`,
65
+ then lines starting with `v ` holding literals, the last ended by `0`. A comment
66
+ directly after a literal is an error there. The `cadical` binary itself prints
67
+ `s SATISFIABLE`, `s UNSATISFIABLE` or `c UNKNOWN`, and exits with 10, 20 or 0.
68
+
69
+ ## Hand-written files
70
+
71
+ Every source file is hand-written; nothing is generated:
72
+
73
+ - `src/dimacs.grammar`, `src/dimacs.grammar.d.ts`
74
+ - `src/highlight.ts`, `src/index.ts`
75
+ - `test/dimacs.txt`, `test/solution.txt`, `test/test.js`, `test/fixtures.js`
76
+ - `rollup.config.js`, `tsconfig.json`
77
+
78
+ The parser in `dist/` is generated from `src/dimacs.grammar` by `@lezer/generator` when
79
+ the package is built.
@@ -0,0 +1,2 @@
1
+ import type { NodePropSource } from "@lezer/common";
2
+ export declare const dimacsHighlighting: NodePropSource;
package/dist/index.cjs ADDED
@@ -0,0 +1,50 @@
1
+ 'use strict';
2
+
3
+ var lr = require('@lezer/lr');
4
+ var highlight = require('@lezer/highlight');
5
+ var language = require('@codemirror/language');
6
+
7
+ const dimacsHighlighting = highlight.styleTags({
8
+ LineComment: highlight.tags.lineComment,
9
+ "p CubeMarker s v": highlight.tags.keyword,
10
+ Format: highlight.tags.typeName,
11
+ Number: highlight.tags.number,
12
+ PositiveLiteral: highlight.tags.variableName,
13
+ NegativeLiteral: highlight.tags.special(highlight.tags.variableName),
14
+ Terminator: highlight.tags.separator,
15
+ Status: highlight.tags.bool,
16
+ });
17
+
18
+ // This file was generated by lezer-generator. You probably shouldn't edit it.
19
+ const parser = lr.LRParser.deserialize({
20
+ version: 14,
21
+ states: "%dO_QPOOOdQPOOOiYQO'#C_QqQPOOO!PQPO'#CkQ!UQPOOO!ZYQO,58yOOQO,58y,58yOOQO'#Cx'#CxOOQO'#Cq'#CqO!`QPO'#CdOOQO'#Cd'#CdOOQO'#Cp'#CpQqQPOOO!kQPO'#ChOOQO'#Cr'#CrQzQPOOOOQO,59V,59VO!vQPO'#CnOOQO'#Cs'#CsQ!UQPOOO#XYQO1G.eOOQO-E6o-E6oOOQO,59O,59OOOQO-E6n-E6nO#^QPO,59SOOQO,59S,59SOOQO-E6p-E6pO#iQPO,59YOOQO,59Y,59YOOQO-E6q-E6qOOQO7+$P7+$POOQO1G.n1G.nOOQO1G.t1G.t",
22
+ stateData: "$O~OkOSPOS~OkOS~OSQO~O`SO~OTUOVVO~OXWOYWOZZO]^O~OaaO~OcbO~OUeO~OXWOYWOZgO~OXWOYWOZjO~OXWOYWOZmOcbXhbX~OUoO~OXWOYWOZpO~OXWOYWOZqOcbahba~OXYZ~",
23
+ goto: "#OmPPPnPPPPqPPPuPPzPP}P!R!X!h!oPPPP!uRROT[R]V_R]`RTPTcTdQ]RRh]SYR]UfYilQi^RlbS`R]Rk`QdTRnd_XRY]^bil",
24
+ nodeNames: "⚠ LineComment Dimacs ProblemLine p Format Number Format Clause PositiveLiteral NegativeLiteral Terminator Cube CubeMarker Solution StatusLine s Status ValueLine v",
25
+ maxTerm: 28,
26
+ propSources: [dimacsHighlighting],
27
+ skippedNodes: [0,1],
28
+ repeatNodeCount: 4,
29
+ tokenData: "(y~R_XY!QYZ!Q]^!Qpq!Q}!O!c!Q!R#P!R![#^!u!v#h!w!x${#T#U%t#V#W%y#]#^'u#d#e(j#g#h(o#j#k(t~!VSk~XY!QYZ!Q]^!Qpq!Q~!fQ!Q!R!l!R![!w~!qQZP!Q!R!l!R![!w~!|PY~!Q![!wR#WQUQZP!Q!R#P!R![#^R#ePUQXP!Q![#^~#kP!c!d#n~#qP!v!w#t~#wP!k!l#z~#}P!u!v$Q~$TP!h!i$W~$ZP!k!l$^~$aP!c!d$d~$gP!d!e$j~$mP!n!o$p~$sP!g!h$v~${Oa~~%OP!p!q%R~%UQ!m!n%[!u!v#h~%_P!p!q%b~%eP!q!r%h~%kP!y!z%n~%qP!p!q$v~%yO]~R&OUPPOY&bZ#b&b#b#c&y#c;'S&b;'S;=`&s<%lO&bP&gSPPOY&bZ;'S&b;'S;=`&s<%lO&bP&vP;=`<%l&bR'OUPPOY&bZ#Y&b#Y#Z'b#Z;'S&b;'S;=`&s<%lO&bR'iSPPTQOY&bZ;'S&b;'S;=`&s<%lO&b~'xP#b#c'{~(OP#V#W(R~(UP#V#W(X~([P#b#c(_~(bP#Y#Z(e~(jOV~~(oOS~~(tO`~~(yOc~",
30
+ tokenizers: [0, 1],
31
+ topRules: {"Dimacs":[0,2],"Solution":[1,14]},
32
+ tokenPrec: 134
33
+ });
34
+
35
+ /// DIMACS CNF as CaDiCaL reads it (`p cnf` and `p inccnf`). For solver output in the
36
+ /// competition format, use `dimacsLanguage.configure({top: "Solution"})`.
37
+ const dimacsLanguage = language.LRLanguage.define({
38
+ name: "dimacs",
39
+ parser,
40
+ languageData: {
41
+ commentTokens: { line: "c" },
42
+ },
43
+ });
44
+ /// DIMACS language support for CodeMirror.
45
+ function dimacs() {
46
+ return new language.LanguageSupport(dimacsLanguage);
47
+ }
48
+
49
+ exports.dimacs = dimacs;
50
+ exports.dimacsLanguage = dimacsLanguage;
@@ -0,0 +1,3 @@
1
+ import { LRLanguage, LanguageSupport } from "@codemirror/language";
2
+ export declare const dimacsLanguage: LRLanguage;
3
+ export declare function dimacs(): LanguageSupport;
package/dist/index.js ADDED
@@ -0,0 +1,47 @@
1
+ import { LRParser } from '@lezer/lr';
2
+ import { styleTags, tags } from '@lezer/highlight';
3
+ import { LRLanguage, LanguageSupport } from '@codemirror/language';
4
+
5
+ const dimacsHighlighting = styleTags({
6
+ LineComment: tags.lineComment,
7
+ "p CubeMarker s v": tags.keyword,
8
+ Format: tags.typeName,
9
+ Number: tags.number,
10
+ PositiveLiteral: tags.variableName,
11
+ NegativeLiteral: tags.special(tags.variableName),
12
+ Terminator: tags.separator,
13
+ Status: tags.bool,
14
+ });
15
+
16
+ // This file was generated by lezer-generator. You probably shouldn't edit it.
17
+ const parser = LRParser.deserialize({
18
+ version: 14,
19
+ states: "%dO_QPOOOdQPOOOiYQO'#C_QqQPOOO!PQPO'#CkQ!UQPOOO!ZYQO,58yOOQO,58y,58yOOQO'#Cx'#CxOOQO'#Cq'#CqO!`QPO'#CdOOQO'#Cd'#CdOOQO'#Cp'#CpQqQPOOO!kQPO'#ChOOQO'#Cr'#CrQzQPOOOOQO,59V,59VO!vQPO'#CnOOQO'#Cs'#CsQ!UQPOOO#XYQO1G.eOOQO-E6o-E6oOOQO,59O,59OOOQO-E6n-E6nO#^QPO,59SOOQO,59S,59SOOQO-E6p-E6pO#iQPO,59YOOQO,59Y,59YOOQO-E6q-E6qOOQO7+$P7+$POOQO1G.n1G.nOOQO1G.t1G.t",
20
+ stateData: "$O~OkOSPOS~OkOS~OSQO~O`SO~OTUOVVO~OXWOYWOZZO]^O~OaaO~OcbO~OUeO~OXWOYWOZgO~OXWOYWOZjO~OXWOYWOZmOcbXhbX~OUoO~OXWOYWOZpO~OXWOYWOZqOcbahba~OXYZ~",
21
+ goto: "#OmPPPnPPPPqPPPuPPzPP}P!R!X!h!oPPPP!uRROT[R]V_R]`RTPTcTdQ]RRh]SYR]UfYilQi^RlbS`R]Rk`QdTRnd_XRY]^bil",
22
+ nodeNames: "⚠ LineComment Dimacs ProblemLine p Format Number Format Clause PositiveLiteral NegativeLiteral Terminator Cube CubeMarker Solution StatusLine s Status ValueLine v",
23
+ maxTerm: 28,
24
+ propSources: [dimacsHighlighting],
25
+ skippedNodes: [0,1],
26
+ repeatNodeCount: 4,
27
+ tokenData: "(y~R_XY!QYZ!Q]^!Qpq!Q}!O!c!Q!R#P!R![#^!u!v#h!w!x${#T#U%t#V#W%y#]#^'u#d#e(j#g#h(o#j#k(t~!VSk~XY!QYZ!Q]^!Qpq!Q~!fQ!Q!R!l!R![!w~!qQZP!Q!R!l!R![!w~!|PY~!Q![!wR#WQUQZP!Q!R#P!R![#^R#ePUQXP!Q![#^~#kP!c!d#n~#qP!v!w#t~#wP!k!l#z~#}P!u!v$Q~$TP!h!i$W~$ZP!k!l$^~$aP!c!d$d~$gP!d!e$j~$mP!n!o$p~$sP!g!h$v~${Oa~~%OP!p!q%R~%UQ!m!n%[!u!v#h~%_P!p!q%b~%eP!q!r%h~%kP!y!z%n~%qP!p!q$v~%yO]~R&OUPPOY&bZ#b&b#b#c&y#c;'S&b;'S;=`&s<%lO&bP&gSPPOY&bZ;'S&b;'S;=`&s<%lO&bP&vP;=`<%l&bR'OUPPOY&bZ#Y&b#Y#Z'b#Z;'S&b;'S;=`&s<%lO&bR'iSPPTQOY&bZ;'S&b;'S;=`&s<%lO&b~'xP#b#c'{~(OP#V#W(R~(UP#V#W(X~([P#b#c(_~(bP#Y#Z(e~(jOV~~(oOS~~(tO`~~(yOc~",
28
+ tokenizers: [0, 1],
29
+ topRules: {"Dimacs":[0,2],"Solution":[1,14]},
30
+ tokenPrec: 134
31
+ });
32
+
33
+ /// DIMACS CNF as CaDiCaL reads it (`p cnf` and `p inccnf`). For solver output in the
34
+ /// competition format, use `dimacsLanguage.configure({top: "Solution"})`.
35
+ const dimacsLanguage = LRLanguage.define({
36
+ name: "dimacs",
37
+ parser,
38
+ languageData: {
39
+ commentTokens: { line: "c" },
40
+ },
41
+ });
42
+ /// DIMACS language support for CodeMirror.
43
+ function dimacs() {
44
+ return new LanguageSupport(dimacsLanguage);
45
+ }
46
+
47
+ export { dimacs, dimacsLanguage };
package/package.json CHANGED
@@ -1,6 +1,46 @@
1
1
  {
2
2
  "name": "codemirror-lang-dimacs",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "keywords": [
5
+ "codemirror",
6
+ "lezer",
7
+ "dimacs",
8
+ "sat"
9
+ ],
10
+ "description": "DIMACS CNF language support for CodeMirror, as read by CaDiCaL",
11
+ "scripts": {
12
+ "test": "mocha test/test.js test/fixtures.js",
13
+ "build": "rollup -c && tsc -p tsconfig.json --declaration --emitDeclarationOnly --outDir dist",
14
+ "prepare": "pnpm run build"
15
+ },
16
+ "type": "module",
17
+ "main": "dist/index.cjs",
18
+ "module": "dist/index.js",
19
+ "exports": {
20
+ "import": "./dist/index.js",
21
+ "require": "./dist/index.cjs"
22
+ },
23
+ "types": "dist/index.d.ts",
24
+ "sideEffects": false,
25
+ "dependencies": {
26
+ "@codemirror/language": "^6.0.0",
27
+ "@lezer/common": "^1.5.3",
28
+ "@lezer/highlight": "^1.0.0",
29
+ "@lezer/lr": "^1.0.0"
30
+ },
31
+ "devDependencies": {
32
+ "@lezer/generator": "^1.0.0",
33
+ "@rollup/plugin-typescript": "^12.1.4",
34
+ "@types/node": "^26.0.0",
35
+ "mocha": "^11.7.1",
36
+ "rollup": "^4.45.1",
37
+ "tslib": "^2.8.1",
38
+ "typescript": "^5.8.3"
39
+ },
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/jcschuster/lang-dimacs.git",
43
+ "directory": "packages/codemirror-lang-dimacs"
44
+ },
45
+ "license": "MIT"
46
+ }