@echecs/pgn 2.1.1 → 2.1.3

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/README.md CHANGED
@@ -15,8 +15,63 @@ yarn add @echecs/pgn
15
15
 
16
16
  ## Usage
17
17
 
18
- We just need to provide with a PGN to the parser. It always return an array
19
- because PGN files could contain several games.
18
+ `parse(input: string): PGN[]`
19
+
20
+ **PGN** format:
21
+
22
+ ```json
23
+ {
24
+ meta: Meta,
25
+ moves: Moves,
26
+ result: 1-0 // 1-0 | 0-1 | 1/2-1/2 | ?
27
+ }
28
+ ```
29
+
30
+ **Meta** format:
31
+
32
+ ```json
33
+ {
34
+ // Based on the PGN specification at least the following Tags should be available
35
+ Event: "the name of the tournament or match event"
36
+ Site: "the location of the event"
37
+ Date: "the starting date of the game"
38
+ Round: "the playing round ordinal of the game"
39
+ White: "the player of the white pieces"
40
+ Black: "the player of the black pieces"
41
+ Result: "the result of the game"
42
+ // plus any other additional tags with `key` string
43
+ [key]: "string"
44
+ }
45
+ ```
46
+
47
+ **Moves** is an _array_ of:
48
+
49
+ ```json
50
+ // move number, white move, black move
51
+ [5, Move, Move]
52
+ ```
53
+
54
+ Notice that half move are available for variations of if the last move of the game was white.
55
+
56
+ **Move** format:
57
+
58
+ ```json
59
+ {
60
+ annotations: ["!", "$126"], // (optional) all the annotations for the given move
61
+ capture: false, // (optional) indicates if the move capture any piece
62
+ castling: true, // (optional) indicates if the move was castling
63
+ check: false, // (optional) indicates if the move checks the rival king
64
+ checkmate: false, // (optional) indicates if it is checkmate
65
+ comment: 'Some comment', // (optional) comment of the move
66
+ from: 'e', // (optional) Disambiguation of the move
67
+ piece: 'K', // (required) P (Pawn) | R (Rook) | N (Knight) | B (Bishop) | Q (Queen) | K (King)
68
+ promotion: Piece; // (optional) R (Rook) | N (Knight) | B (Bishop) | Q (Queen)
69
+ to: 'g1', // ending square of the piece
70
+ variants: [...] // moves following Moves format
71
+ }
72
+ ```
73
+
74
+ **Example**
20
75
 
21
76
  ```js
22
77
  import { readFileSync } from 'fs';
@@ -32,328 +87,150 @@ const pgn = parse(readFile('./games/file.pgn'));
32
87
  // [
33
88
  // {
34
89
  // "meta": {
35
- // "Site": "?",
90
+ // "Black": "Cordts, Ingo",
91
+ // "BlackElo": "2222",
36
92
  // "Date": "2000.10.29",
93
+ // "ECO": "A56",
94
+ // "Result": "0-1",
37
95
  // "Round": "?",
96
+ // "Site": "?",
38
97
  // "White": "Carlsen, Magnus",
39
- // "Black": "Cordts, Ingo",
40
- // "ECO": "A56",
41
98
  // "WhiteElo": "0",
42
- // "BlackElo": "2222",
43
- // "Result": "0-1"
44
99
  // },
45
100
  // "moves": [
46
101
  // [
102
+ // 1,
47
103
  // {
48
104
  // "piece": "P",
49
- // "to": "d4"
105
+ // "to": "d4",
50
106
  // },
51
107
  // {
52
108
  // "piece": "N",
53
- // "to": "f6"
54
- // }
109
+ // "to": "f6",
110
+ // },
55
111
  // ],
56
112
  // [
113
+ // 2,
57
114
  // {
58
115
  // "piece": "P",
59
- // "to": "c4"
116
+ // "to": "c4",
60
117
  // },
61
118
  // {
62
119
  // "piece": "P",
63
- // "to": "c5"
64
- // }
65
- // ],
66
- // [
67
- // {
68
- // "piece": "N",
69
- // "to": "f3"
120
+ // "to": "c5",
70
121
  // },
71
- // {
72
- // "from": "c",
73
- // "piece": "P",
74
- // "to": "d4"
75
- // }
76
122
  // ],
77
123
  // [
124
+ // 3,
78
125
  // {
79
126
  // "piece": "N",
80
- // "to": "d4"
127
+ // "to": "f3",
81
128
  // },
82
129
  // {
130
+ // "capture": true,
131
+ // "from": "c",
83
132
  // "piece": "P",
84
- // "to": "e5"
85
- // }
86
- // ],
87
- // [
88
- // {
89
- // "piece": "N",
90
- // "to": "b5"
133
+ // "to": "d4",
91
134
  // },
92
- // {
93
- // "piece": "P",
94
- // "to": "d5"
95
- // }
96
135
  // ],
136
+ // ...
97
137
  // [
138
+ // 6,
98
139
  // {
140
+ // "capture": true,
99
141
  // "from": "c",
100
142
  // "piece": "P",
101
- // "to": "d5"
143
+ // "to": "d5",
102
144
  // },
103
145
  // {
104
146
  // "piece": "B",
105
- // "to": "c5"
106
- // }
147
+ // "to": "c5",
148
+ // },
107
149
  // ],
108
150
  // [
151
+ // 7,
109
152
  // {
110
153
  // "from": "5",
111
154
  // "piece": "N",
112
- // "to": "c3"
155
+ // "to": "c3",
113
156
  // },
114
157
  // {
115
158
  // "castling": true,
116
159
  // "piece": "K",
117
- // "to": "c8"
118
- // }
119
- // ],
120
- // [
121
- // {
122
- // "piece": "P",
123
- // "to": "e3"
160
+ // "to": "g8",
124
161
  // },
125
- // {
126
- // "piece": "P",
127
- // "to": "e4"
128
- // }
129
- // ],
130
- // [
131
- // {
132
- // "piece": "P",
133
- // "to": "h3"
134
- // },
135
- // {
136
- // "piece": "R",
137
- // "to": "e8"
138
- // }
139
- // ],
140
- // [
141
- // {
142
- // "piece": "P",
143
- // "to": "g4"
144
- // },
145
- // {
146
- // "piece": "R",
147
- // "to": "e5"
148
- // }
149
- // ],
150
- // [
151
- // {
152
- // "piece": "B",
153
- // "to": "c4"
154
- // },
155
- // {
156
- // "from": "b",
157
- // "piece": "N",
158
- // "to": "d7"
159
- // }
160
- // ],
161
- // [
162
- // {
163
- // "piece": "Q",
164
- // "to": "b3"
165
- // },
166
- // {
167
- // "piece": "N",
168
- // "to": "e8"
169
- // }
170
162
  // ],
163
+ // ...
171
164
  // [
165
+ // 21,
172
166
  // {
167
+ // "capture": true,
173
168
  // "piece": "N",
174
- // "to": "d2"
169
+ // "to": "e4",
175
170
  // },
176
171
  // {
177
- // "piece": "N",
178
- // "to": "d6"
179
- // }
180
- // ],
181
- // [
182
- // {
183
172
  // "piece": "B",
184
- // "to": "e2"
185
- // },
186
- // {
187
- // "piece": "Q",
188
- // "to": "h4"
189
- // }
190
- // ],
191
- // [
192
- // {
193
- // "piece": "N",
194
- // "to": "c4"
173
+ // "to": "b7",
195
174
  // },
196
- // {
197
- // "piece": "N",
198
- // "to": "c4"
199
- // }
200
175
  // ],
201
176
  // [
177
+ // 22,
202
178
  // {
179
+ // "capture": true,
203
180
  // "piece": "Q",
204
- // "to": "c4"
205
- // },
206
- // {
207
- // "piece": "P",
208
- // "to": "b5"
209
- // }
210
- // ],
211
- // [
212
- // {
213
- // "piece": "Q",
214
- // "to": "b5"
215
- // },
216
- // {
217
- // "piece": "R",
218
- // "to": "b8"
219
- // }
220
- // ],
221
- // [
222
- // {
223
- // "piece": "Q",
224
- // "to": "a4"
225
- // },
226
- // {
227
- // "piece": "N",
228
- // "to": "f6"
229
- // }
230
- // ],
231
- // [
232
- // {
233
- // "piece": "Q",
234
- // "to": "c6"
235
- // },
236
- // {
237
- // "piece": "N",
238
- // "to": "d7"
239
- // }
240
- // ],
241
- // [
242
- // {
243
- // "piece": "P",
244
- // "to": "d6"
245
- // },
246
- // {
247
- // "piece": "R",
248
- // "to": "e6"
249
- // }
250
- // ],
251
- // [
252
- // {
253
- // "piece": "N",
254
- // "to": "e4"
181
+ // "to": "d7",
255
182
  // },
256
183
  // {
184
+ // "capture": true,
257
185
  // "piece": "B",
258
- // "to": "b7"
259
- // }
260
- // ],
261
- // [
262
- // {
263
- // "piece": "Q",
264
- // "to": "d7"
186
+ // "to": "e4",
265
187
  // },
266
- // {
267
- // "piece": "B",
268
- // "to": "e4"
269
- // }
270
188
  // ],
271
189
  // [
190
+ // 23,
272
191
  // {
273
192
  // "piece": "R",
274
- // "to": "h2"
193
+ // "to": "h2",
275
194
  // },
276
195
  // {
196
+ // "capture": true,
277
197
  // "piece": "B",
278
- // "to": "d6"
279
- // }
280
- // ],
281
- // [
282
- // {
283
- // "piece": "B",
284
- // "to": "c4"
198
+ // "to": "d6",
285
199
  // },
286
- // {
287
- // "piece": "R",
288
- // "to": "d8"
289
- // }
290
200
  // ],
201
+ // ...
291
202
  // [
203
+ // 29,
292
204
  // {
205
+ // "capture": true,
206
+ // "check": true,
293
207
  // "piece": "Q",
294
- // "to": "a7"
208
+ // "to": "e6",
295
209
  // },
296
210
  // {
297
- // "piece": "B",
298
- // "to": "h2"
299
- // }
300
- // ],
301
- // [
302
- // {
303
- // "piece": "B",
304
- // "to": "e6"
211
+ // "piece": "K",
212
+ // "to": "h8",
305
213
  // },
306
- // {
307
- // "from": "f",
308
- // "piece": "P",
309
- // "to": "e6"
310
- // }
311
214
  // ],
312
215
  // [
216
+ // 30,
313
217
  // {
314
218
  // "piece": "Q",
315
- // "to": "a6"
219
+ // "to": "e7",
316
220
  // },
317
221
  // {
318
222
  // "piece": "B",
319
- // "to": "f3"
320
- // }
321
- // ],
322
- // [
323
- // {
324
- // "piece": "B",
325
- // "to": "d2"
326
- // },
327
- // {
328
- // "piece": "Q",
329
- // "to": "h3"
330
- // }
331
- // ],
332
- // [
333
- // {
334
- // "annotations": [
335
- // "check"
336
- // ],
337
- // "piece": "Q",
338
- // "to": "e6"
223
+ // "to": "c7",
339
224
  // },
340
- // {
341
- // "piece": "K",
342
- // "to": "h8"
343
- // }
344
225
  // ],
345
- // [
346
- // {
347
- // "piece": "Q",
348
- // "to": "e7"
349
- // },
350
- // {
351
- // "piece": "B",
352
- // "to": "c7"
353
- // }
354
- // ]
355
226
  // ],
356
- // "result": 0
357
- // }
358
- // ]
227
+ // "result": 0,
228
+ // },
229
+ // ];
359
230
  ```
231
+
232
+ ## Warning
233
+
234
+ **PGN** does not guarantee PGN games are valid. It does only parse the content.
235
+ As part of the **ECHECS** project, it is responsability of **@echecs/game** to
236
+ verify the validity of the game.
package/package.json CHANGED
@@ -19,6 +19,11 @@
19
19
  "ts-jest": "^29.0.3",
20
20
  "typescript": "^4.9.4"
21
21
  },
22
+ "files": [
23
+ "/dist/",
24
+ "LICENSE",
25
+ "README.md"
26
+ ],
22
27
  "keywords": [
23
28
  "chess",
24
29
  "fide",
@@ -34,7 +39,7 @@
34
39
  "compile": "tsc",
35
40
  "format": "prettier --ignore-path .gitignore \"src/**/*.+(js|json|md|yml)\" --write",
36
41
  "grammar:compile": "nearleyc src/grammar.ne -o src/grammar.js",
37
- "grammar:diagram": "nearley-railroad regex.ne -o diagram.html",
42
+ "grammar:diagram": "nearley-railroad src/grammar.ne -o diagram.html",
38
43
  "grammar:test": "nearley-test -s DATABASE src/grammar.js < ./test.pgn",
39
44
  "lint": "eslint \"src/**/*.ts\" --fix",
40
45
  "prepare": "npm run build",
@@ -42,5 +47,6 @@
42
47
  "test:coverage": "npm run test -- --coverage",
43
48
  "test:watch": "npm run test -- --watch"
44
49
  },
45
- "version": "2.1.1"
50
+ "types": "dist/index.d.ts",
51
+ "version": "2.1.3"
46
52
  }
@@ -1,11 +0,0 @@
1
- version: 2
2
- updates:
3
- - package-ecosystem: npm
4
- directory: '/'
5
- schedule:
6
- interval: daily
7
- time: '13:00'
8
- open-pull-requests-limit: 10
9
- commit-message:
10
- prefix: 'chore'
11
- include: 'scope'
@@ -1,34 +0,0 @@
1
- name: Release
2
-
3
- on:
4
- push:
5
- branches:
6
- - main
7
-
8
- jobs:
9
- build:
10
- name: Release
11
- runs-on: ubuntu-latest
12
- steps:
13
- - name: Checkout code
14
- uses: actions/checkout@v3
15
- - name: Setup
16
- uses: actions/setup-node@v3
17
- with:
18
- node-version: node
19
- - name: Cache NPM Modules
20
- id: cache-node
21
- uses: actions/cache@v3
22
- with:
23
- path: '**/node_modules'
24
- key: ${{ runner.os }}-yarn-${{ hashFiles('**/package-lock.json') }}
25
- - name: Install dependencies
26
- if: steps.cache-node.outputs.cache-hit != 'true'
27
- run: npm ci
28
- - name: Verify
29
- run: npm run test
30
- - name: Release to NPM
31
- uses: JS-DevTools/npm-publish@v1
32
- with:
33
- access: public
34
- token: ${{ secrets.NPM_TOKEN }}
package/.husky/pre-commit DELETED
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env sh
2
- . "$(dirname -- "$0")/_/husky.sh"
3
-
4
- npx lint-staged
package/.husky/pre-push DELETED
@@ -1,4 +0,0 @@
1
- #!/bin/sh
2
- . "$(dirname "$0")/_/husky.sh"
3
-
4
- npm run format && npm run lint && npm run test
package/jest.config.js DELETED
@@ -1,5 +0,0 @@
1
- /** @type {import('ts-jest').JestConfigWithTsJest} */
2
- module.exports = {
3
- preset: 'ts-jest',
4
- testEnvironment: 'node',
5
- };
package/src/grammar.js DELETED
@@ -1,428 +0,0 @@
1
- // Generated automatically by nearley, version 2.20.1
2
- // http://github.com/Hardmath123/nearley
3
- (function () {
4
- function id(x) { return x[0]; }
5
- var grammar = {
6
- Lexer: undefined,
7
- ParserRules: [
8
- {"name": "unsigned_int$ebnf$1", "symbols": [/[0-9]/]},
9
- {"name": "unsigned_int$ebnf$1", "symbols": ["unsigned_int$ebnf$1", /[0-9]/], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
10
- {"name": "unsigned_int", "symbols": ["unsigned_int$ebnf$1"], "postprocess":
11
- function(d) {
12
- return parseInt(d[0].join(""));
13
- }
14
- },
15
- {"name": "int$ebnf$1$subexpression$1", "symbols": [{"literal":"-"}]},
16
- {"name": "int$ebnf$1$subexpression$1", "symbols": [{"literal":"+"}]},
17
- {"name": "int$ebnf$1", "symbols": ["int$ebnf$1$subexpression$1"], "postprocess": id},
18
- {"name": "int$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
19
- {"name": "int$ebnf$2", "symbols": [/[0-9]/]},
20
- {"name": "int$ebnf$2", "symbols": ["int$ebnf$2", /[0-9]/], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
21
- {"name": "int", "symbols": ["int$ebnf$1", "int$ebnf$2"], "postprocess":
22
- function(d) {
23
- if (d[0]) {
24
- return parseInt(d[0][0]+d[1].join(""));
25
- } else {
26
- return parseInt(d[1].join(""));
27
- }
28
- }
29
- },
30
- {"name": "unsigned_decimal$ebnf$1", "symbols": [/[0-9]/]},
31
- {"name": "unsigned_decimal$ebnf$1", "symbols": ["unsigned_decimal$ebnf$1", /[0-9]/], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
32
- {"name": "unsigned_decimal$ebnf$2$subexpression$1$ebnf$1", "symbols": [/[0-9]/]},
33
- {"name": "unsigned_decimal$ebnf$2$subexpression$1$ebnf$1", "symbols": ["unsigned_decimal$ebnf$2$subexpression$1$ebnf$1", /[0-9]/], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
34
- {"name": "unsigned_decimal$ebnf$2$subexpression$1", "symbols": [{"literal":"."}, "unsigned_decimal$ebnf$2$subexpression$1$ebnf$1"]},
35
- {"name": "unsigned_decimal$ebnf$2", "symbols": ["unsigned_decimal$ebnf$2$subexpression$1"], "postprocess": id},
36
- {"name": "unsigned_decimal$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}},
37
- {"name": "unsigned_decimal", "symbols": ["unsigned_decimal$ebnf$1", "unsigned_decimal$ebnf$2"], "postprocess":
38
- function(d) {
39
- return parseFloat(
40
- d[0].join("") +
41
- (d[1] ? "."+d[1][1].join("") : "")
42
- );
43
- }
44
- },
45
- {"name": "decimal$ebnf$1", "symbols": [{"literal":"-"}], "postprocess": id},
46
- {"name": "decimal$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
47
- {"name": "decimal$ebnf$2", "symbols": [/[0-9]/]},
48
- {"name": "decimal$ebnf$2", "symbols": ["decimal$ebnf$2", /[0-9]/], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
49
- {"name": "decimal$ebnf$3$subexpression$1$ebnf$1", "symbols": [/[0-9]/]},
50
- {"name": "decimal$ebnf$3$subexpression$1$ebnf$1", "symbols": ["decimal$ebnf$3$subexpression$1$ebnf$1", /[0-9]/], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
51
- {"name": "decimal$ebnf$3$subexpression$1", "symbols": [{"literal":"."}, "decimal$ebnf$3$subexpression$1$ebnf$1"]},
52
- {"name": "decimal$ebnf$3", "symbols": ["decimal$ebnf$3$subexpression$1"], "postprocess": id},
53
- {"name": "decimal$ebnf$3", "symbols": [], "postprocess": function(d) {return null;}},
54
- {"name": "decimal", "symbols": ["decimal$ebnf$1", "decimal$ebnf$2", "decimal$ebnf$3"], "postprocess":
55
- function(d) {
56
- return parseFloat(
57
- (d[0] || "") +
58
- d[1].join("") +
59
- (d[2] ? "."+d[2][1].join("") : "")
60
- );
61
- }
62
- },
63
- {"name": "percentage", "symbols": ["decimal", {"literal":"%"}], "postprocess":
64
- function(d) {
65
- return d[0]/100;
66
- }
67
- },
68
- {"name": "jsonfloat$ebnf$1", "symbols": [{"literal":"-"}], "postprocess": id},
69
- {"name": "jsonfloat$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
70
- {"name": "jsonfloat$ebnf$2", "symbols": [/[0-9]/]},
71
- {"name": "jsonfloat$ebnf$2", "symbols": ["jsonfloat$ebnf$2", /[0-9]/], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
72
- {"name": "jsonfloat$ebnf$3$subexpression$1$ebnf$1", "symbols": [/[0-9]/]},
73
- {"name": "jsonfloat$ebnf$3$subexpression$1$ebnf$1", "symbols": ["jsonfloat$ebnf$3$subexpression$1$ebnf$1", /[0-9]/], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
74
- {"name": "jsonfloat$ebnf$3$subexpression$1", "symbols": [{"literal":"."}, "jsonfloat$ebnf$3$subexpression$1$ebnf$1"]},
75
- {"name": "jsonfloat$ebnf$3", "symbols": ["jsonfloat$ebnf$3$subexpression$1"], "postprocess": id},
76
- {"name": "jsonfloat$ebnf$3", "symbols": [], "postprocess": function(d) {return null;}},
77
- {"name": "jsonfloat$ebnf$4$subexpression$1$ebnf$1", "symbols": [/[+-]/], "postprocess": id},
78
- {"name": "jsonfloat$ebnf$4$subexpression$1$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
79
- {"name": "jsonfloat$ebnf$4$subexpression$1$ebnf$2", "symbols": [/[0-9]/]},
80
- {"name": "jsonfloat$ebnf$4$subexpression$1$ebnf$2", "symbols": ["jsonfloat$ebnf$4$subexpression$1$ebnf$2", /[0-9]/], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
81
- {"name": "jsonfloat$ebnf$4$subexpression$1", "symbols": [/[eE]/, "jsonfloat$ebnf$4$subexpression$1$ebnf$1", "jsonfloat$ebnf$4$subexpression$1$ebnf$2"]},
82
- {"name": "jsonfloat$ebnf$4", "symbols": ["jsonfloat$ebnf$4$subexpression$1"], "postprocess": id},
83
- {"name": "jsonfloat$ebnf$4", "symbols": [], "postprocess": function(d) {return null;}},
84
- {"name": "jsonfloat", "symbols": ["jsonfloat$ebnf$1", "jsonfloat$ebnf$2", "jsonfloat$ebnf$3", "jsonfloat$ebnf$4"], "postprocess":
85
- function(d) {
86
- return parseFloat(
87
- (d[0] || "") +
88
- d[1].join("") +
89
- (d[2] ? "."+d[2][1].join("") : "") +
90
- (d[3] ? "e" + (d[3][1] || "+") + d[3][2].join("") : "")
91
- );
92
- }
93
- },
94
- {"name": "dqstring$ebnf$1", "symbols": []},
95
- {"name": "dqstring$ebnf$1", "symbols": ["dqstring$ebnf$1", "dstrchar"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
96
- {"name": "dqstring", "symbols": [{"literal":"\""}, "dqstring$ebnf$1", {"literal":"\""}], "postprocess": function(d) {return d[1].join(""); }},
97
- {"name": "sqstring$ebnf$1", "symbols": []},
98
- {"name": "sqstring$ebnf$1", "symbols": ["sqstring$ebnf$1", "sstrchar"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
99
- {"name": "sqstring", "symbols": [{"literal":"'"}, "sqstring$ebnf$1", {"literal":"'"}], "postprocess": function(d) {return d[1].join(""); }},
100
- {"name": "btstring$ebnf$1", "symbols": []},
101
- {"name": "btstring$ebnf$1", "symbols": ["btstring$ebnf$1", /[^`]/], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
102
- {"name": "btstring", "symbols": [{"literal":"`"}, "btstring$ebnf$1", {"literal":"`"}], "postprocess": function(d) {return d[1].join(""); }},
103
- {"name": "dstrchar", "symbols": [/[^\\"\n]/], "postprocess": id},
104
- {"name": "dstrchar", "symbols": [{"literal":"\\"}, "strescape"], "postprocess":
105
- function(d) {
106
- return JSON.parse("\""+d.join("")+"\"");
107
- }
108
- },
109
- {"name": "sstrchar", "symbols": [/[^\\'\n]/], "postprocess": id},
110
- {"name": "sstrchar", "symbols": [{"literal":"\\"}, "strescape"], "postprocess": function(d) { return JSON.parse("\""+d.join("")+"\""); }},
111
- {"name": "sstrchar$string$1", "symbols": [{"literal":"\\"}, {"literal":"'"}], "postprocess": function joiner(d) {return d.join('');}},
112
- {"name": "sstrchar", "symbols": ["sstrchar$string$1"], "postprocess": function(d) {return "'"; }},
113
- {"name": "strescape", "symbols": [/["\\/bfnrt]/], "postprocess": id},
114
- {"name": "strescape", "symbols": [{"literal":"u"}, /[a-fA-F0-9]/, /[a-fA-F0-9]/, /[a-fA-F0-9]/, /[a-fA-F0-9]/], "postprocess":
115
- function(d) {
116
- return d.join("");
117
- }
118
- },
119
- {"name": "_$ebnf$1", "symbols": []},
120
- {"name": "_$ebnf$1", "symbols": ["_$ebnf$1", "wschar"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
121
- {"name": "_", "symbols": ["_$ebnf$1"], "postprocess": function(d) {return null;}},
122
- {"name": "__$ebnf$1", "symbols": ["wschar"]},
123
- {"name": "__$ebnf$1", "symbols": ["__$ebnf$1", "wschar"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
124
- {"name": "__", "symbols": ["__$ebnf$1"], "postprocess": function(d) {return null;}},
125
- {"name": "wschar", "symbols": [/[ \t\n\v\f]/], "postprocess": id},
126
- {"name": "DATABASE$ebnf$1", "symbols": ["GAME"]},
127
- {"name": "DATABASE$ebnf$1", "symbols": ["DATABASE$ebnf$1", "GAME"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
128
- {"name": "DATABASE", "symbols": ["DATABASE$ebnf$1"], "postprocess": id},
129
- {"name": "GAME", "symbols": ["TAGS", "MOVE_SECTION", "__", "result", "__"], "postprocess":
130
- (d) => ({ meta: d[0], moves: d[1], result: d[3] })
131
- },
132
- {"name": "TAGS$ebnf$1$subexpression$1", "symbols": ["TAG", "__"]},
133
- {"name": "TAGS$ebnf$1", "symbols": ["TAGS$ebnf$1$subexpression$1"]},
134
- {"name": "TAGS$ebnf$1$subexpression$2", "symbols": ["TAG", "__"]},
135
- {"name": "TAGS$ebnf$1", "symbols": ["TAGS$ebnf$1", "TAGS$ebnf$1$subexpression$2"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
136
- {"name": "TAGS", "symbols": ["TAGS$ebnf$1"], "postprocess": (d) => d[0].map(d0 => d0[0]).reduce((acc, item) => ({ ...acc, ...item }), {})},
137
- {"name": "TAG", "symbols": [{"literal":"["}, "NAME", "__", "VALUE", {"literal":"]"}], "postprocess": (d) => ({ [d[1]]: d[3] })},
138
- {"name": "NAME", "symbols": ["string"]},
139
- {"name": "VALUE", "symbols": ["dqstring"], "postprocess": id},
140
- {"name": "MOVE_SECTION$ebnf$1", "symbols": []},
141
- {"name": "MOVE_SECTION$ebnf$1$subexpression$1", "symbols": ["_", "MOVE"]},
142
- {"name": "MOVE_SECTION$ebnf$1", "symbols": ["MOVE_SECTION$ebnf$1", "MOVE_SECTION$ebnf$1$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
143
- {"name": "MOVE_SECTION$ebnf$2$subexpression$1", "symbols": ["_", "HM_WHITE"]},
144
- {"name": "MOVE_SECTION$ebnf$2", "symbols": ["MOVE_SECTION$ebnf$2$subexpression$1"], "postprocess": id},
145
- {"name": "MOVE_SECTION$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}},
146
- {"name": "MOVE_SECTION", "symbols": ["MOVE", "MOVE_SECTION$ebnf$1", "MOVE_SECTION$ebnf$2"], "postprocess":
147
- (d) => {
148
- const moves = [d[0]];
149
-
150
- if (d[1].length > 0) {
151
- const d1 = d[1];
152
-
153
- moves.push(...d1.map(d => d[1]));
154
- }
155
-
156
- if (d[2]) {
157
- const d2 = d[2];
158
-
159
- moves.push(d2[1]);
160
- }
161
-
162
- return moves;
163
- }
164
- },
165
- {"name": "MOVE_SECTION", "symbols": ["HM_WHITE"], "postprocess": d => [d[0]]},
166
- {"name": "MOVES$ebnf$1", "symbols": []},
167
- {"name": "MOVES$ebnf$1$subexpression$1", "symbols": ["_", "MOVE"]},
168
- {"name": "MOVES$ebnf$1", "symbols": ["MOVES$ebnf$1", "MOVES$ebnf$1$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
169
- {"name": "MOVES$ebnf$2$subexpression$1", "symbols": ["_", "HM_WHITE"]},
170
- {"name": "MOVES$ebnf$2", "symbols": ["MOVES$ebnf$2$subexpression$1"], "postprocess": id},
171
- {"name": "MOVES$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}},
172
- {"name": "MOVES", "symbols": ["MOVES$ebnf$1", "MOVES$ebnf$2"], "postprocess":
173
- (d) => {
174
- const moves = [];
175
-
176
- if (d[0]) {
177
- d[0].map(d0 => d0[1]).map(d01 => moves.push(d01));
178
- }
179
-
180
- if (d[1]) {
181
- moves.push(d[1][1]);
182
- }
183
-
184
- return moves;
185
- }
186
- },
187
- {"name": "HM_WHITE$ebnf$1", "symbols": []},
188
- {"name": "HM_WHITE$ebnf$1$subexpression$1", "symbols": ["_", "VARIANT"]},
189
- {"name": "HM_WHITE$ebnf$1", "symbols": ["HM_WHITE$ebnf$1", "HM_WHITE$ebnf$1$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
190
- {"name": "HM_WHITE", "symbols": ["NUMBER", "_", "SAN", "HM_WHITE$ebnf$1"], "postprocess":
191
- (d) => {
192
- const move = [d[0], {...d[2], ...(d[3].length > 0 && { variants: d[3].map(d3 => d3[1]) }), }];
193
-
194
- if (move[1].castling) {
195
- move[1].to = move[1].castling === 'K' ? 'g1' : 'c1';
196
- move[1].castling = true;
197
- }
198
-
199
- return move;
200
- }
201
- },
202
- {"name": "HM_BLACK$ebnf$1", "symbols": []},
203
- {"name": "HM_BLACK$ebnf$1$subexpression$1", "symbols": ["_", "VARIANT"]},
204
- {"name": "HM_BLACK$ebnf$1", "symbols": ["HM_BLACK$ebnf$1", "HM_BLACK$ebnf$1$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
205
- {"name": "HM_BLACK", "symbols": ["_", "NUMBER", "continuation", "_", "SAN", "HM_BLACK$ebnf$1"], "postprocess":
206
- (d) => {
207
- const move = [d[1], undefined, {...d[4], ...(d[5].length > 0 && { variants: d[5].map(d5 => d5[1]) }) }];
208
-
209
- if (move[2].castling) {
210
- move[2].to = move[2].castling === 'K' ? 'g8' : 'c8';
211
- move[2].castling = true;
212
- }
213
-
214
- return move;
215
- }
216
- },
217
- {"name": "MOVE$ebnf$1", "symbols": []},
218
- {"name": "MOVE$ebnf$1$subexpression$1", "symbols": ["_", "VARIANT"]},
219
- {"name": "MOVE$ebnf$1", "symbols": ["MOVE$ebnf$1", "MOVE$ebnf$1$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
220
- {"name": "MOVE", "symbols": ["NUMBER", "_", "SAN", "__", "SAN", "MOVE$ebnf$1"], "postprocess":
221
- (d) => {
222
- const move = [d[0], d[2], d[4]];
223
-
224
- if (move[1].castling) {
225
- move[1].to = move[1].castling === 'K' ? 'g1' : 'c1';
226
- move[1].castling = true;
227
- }
228
-
229
- if (move[2].castling) {
230
- move[2].to = move[2].castling === 'K' ? 'g8' : 'c8';
231
- move[2].castling = true;
232
- }
233
-
234
- if (d[5]) {
235
- const variants = d[5].map(d5 => d5[1]);
236
-
237
- const white = variants.filter(variant => variant[0][1]);
238
- const black = variants.filter(variant => !variant[0][1]);
239
-
240
- if (white.length > 0) {
241
- move[1].variants = white;
242
- }
243
-
244
- if (black.length > 0) {
245
- move[2].variants = black;
246
- }
247
- }
248
-
249
- return move;
250
- }
251
- },
252
- {"name": "MOVE", "symbols": ["HM_WHITE", "__", "HM_BLACK"], "postprocess":
253
- d => [d[0][0], d[0][1], d[2][2]]
254
- },
255
- {"name": "NUMBER$ebnf$1", "symbols": [{"literal":"."}], "postprocess": id},
256
- {"name": "NUMBER$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
257
- {"name": "NUMBER", "symbols": ["unsigned_int", "NUMBER$ebnf$1"], "postprocess": (d) => d[0]},
258
- {"name": "VARIANT", "symbols": [{"literal":"("}, "MOVES", "_", {"literal":")"}], "postprocess":
259
- (d) => d[1]
260
- },
261
- {"name": "VARIANT", "symbols": [{"literal":"("}, "HM_BLACK", "MOVES", "_", {"literal":")"}], "postprocess":
262
- (d) => [d[1], ...d[2]]
263
- },
264
- {"name": "SAN$ebnf$1", "symbols": ["piece"], "postprocess": id},
265
- {"name": "SAN$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
266
- {"name": "SAN$ebnf$2", "symbols": ["DISAMBIGUATION"], "postprocess": id},
267
- {"name": "SAN$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}},
268
- {"name": "SAN$ebnf$3", "symbols": ["capture"], "postprocess": id},
269
- {"name": "SAN$ebnf$3", "symbols": [], "postprocess": function(d) {return null;}},
270
- {"name": "SAN$ebnf$4", "symbols": ["PROMOTION"], "postprocess": id},
271
- {"name": "SAN$ebnf$4", "symbols": [], "postprocess": function(d) {return null;}},
272
- {"name": "SAN$ebnf$5$subexpression$1", "symbols": ["_", "SUFFIX"]},
273
- {"name": "SAN$ebnf$5", "symbols": ["SAN$ebnf$5$subexpression$1"], "postprocess": id},
274
- {"name": "SAN$ebnf$5", "symbols": [], "postprocess": function(d) {return null;}},
275
- {"name": "SAN$ebnf$6", "symbols": []},
276
- {"name": "SAN$ebnf$6$subexpression$1", "symbols": ["_", "COMMENT"]},
277
- {"name": "SAN$ebnf$6", "symbols": ["SAN$ebnf$6", "SAN$ebnf$6$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
278
- {"name": "SAN", "symbols": ["SAN$ebnf$1", "SAN$ebnf$2", "SAN$ebnf$3", "file", "rank", "SAN$ebnf$4", "SAN$ebnf$5", "SAN$ebnf$6"], "postprocess":
279
- (d) => {
280
- const comments = d[7].map(d7 => d7[1]).filter(Boolean);
281
-
282
- return ({
283
- ...(d[6] && d[6][1]),
284
- ...(comments.length > 0 && { comment: comments.reduce((acc, item) => `${acc} ${item}`, '') }),
285
- ...(d[2] && { capture: true }),
286
- ...(d[1] && { from: d[1][0] }),
287
- piece: d[0] ? d[0][0] : 'P',
288
- ...(d[5] && { promotion: d[5] }),
289
- to: `${d[3]}${d[4]}`,
290
- });
291
- }
292
- },
293
- {"name": "SAN$ebnf$7", "symbols": []},
294
- {"name": "SAN$ebnf$7$subexpression$1", "symbols": ["_", "SUFFIX"]},
295
- {"name": "SAN$ebnf$7", "symbols": ["SAN$ebnf$7", "SAN$ebnf$7$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
296
- {"name": "SAN$ebnf$8", "symbols": []},
297
- {"name": "SAN$ebnf$8$subexpression$1", "symbols": ["_", "COMMENT"]},
298
- {"name": "SAN$ebnf$8", "symbols": ["SAN$ebnf$8", "SAN$ebnf$8$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
299
- {"name": "SAN", "symbols": ["castling", "SAN$ebnf$7", "SAN$ebnf$8"], "postprocess":
300
- (d) => {
301
- const comments = d[2].map(d2 => d2[1]).filter(Boolean);
302
-
303
- return ({
304
- ...(d[1]),
305
- ...(comments.length > 0 && { comment: comments.reduce((acc, item) => `${acc} ${item}`, '') }),
306
- castling: d[0],
307
- piece: 'K'
308
- })
309
- }
310
- },
311
- {"name": "DISAMBIGUATION", "symbols": ["file"], "postprocess": id},
312
- {"name": "DISAMBIGUATION", "symbols": ["rank"], "postprocess": id},
313
- {"name": "PROMOTION", "symbols": [{"literal":"="}, /[QBNR]/], "postprocess": (d) => d[1]},
314
- {"name": "SUFFIX$subexpression$1", "symbols": ["check"]},
315
- {"name": "SUFFIX$subexpression$1", "symbols": ["checkmate"]},
316
- {"name": "SUFFIX$ebnf$1", "symbols": ["annotation"], "postprocess": id},
317
- {"name": "SUFFIX$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
318
- {"name": "SUFFIX$ebnf$2", "symbols": []},
319
- {"name": "SUFFIX$ebnf$2$subexpression$1", "symbols": ["_", "NAG"]},
320
- {"name": "SUFFIX$ebnf$2", "symbols": ["SUFFIX$ebnf$2", "SUFFIX$ebnf$2$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
321
- {"name": "SUFFIX", "symbols": ["SUFFIX$subexpression$1", "SUFFIX$ebnf$1", "SUFFIX$ebnf$2"], "postprocess":
322
- (d) => ({
323
- ...(d[0] && { [d[0]]: true }),
324
- ...((d[1] || d[2].length > 0) && { annotations: [...(d[1] ? [d[1]] : []), ...d[2].map(d2 => d2[1])] }),
325
- })
326
- },
327
- {"name": "SUFFIX$ebnf$3$subexpression$1", "symbols": ["check"]},
328
- {"name": "SUFFIX$ebnf$3$subexpression$1", "symbols": ["checkmate"]},
329
- {"name": "SUFFIX$ebnf$3", "symbols": ["SUFFIX$ebnf$3$subexpression$1"], "postprocess": id},
330
- {"name": "SUFFIX$ebnf$3", "symbols": [], "postprocess": function(d) {return null;}},
331
- {"name": "SUFFIX$ebnf$4", "symbols": []},
332
- {"name": "SUFFIX$ebnf$4$subexpression$1", "symbols": ["_", "NAG"]},
333
- {"name": "SUFFIX$ebnf$4", "symbols": ["SUFFIX$ebnf$4", "SUFFIX$ebnf$4$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
334
- {"name": "SUFFIX", "symbols": ["SUFFIX$ebnf$3", "annotation", "SUFFIX$ebnf$4"], "postprocess":
335
- (d) => ({
336
- ...(d[0] && { [d[0]]: true }),
337
- ...((d[1] || d[2].length > 0) && { annotations: [...(d[1] ? [d[1]] : []), ...d[2].map(d2 => d2[1])] }),
338
- })
339
- },
340
- {"name": "SUFFIX$ebnf$5$subexpression$1", "symbols": ["check"]},
341
- {"name": "SUFFIX$ebnf$5$subexpression$1", "symbols": ["checkmate"]},
342
- {"name": "SUFFIX$ebnf$5", "symbols": ["SUFFIX$ebnf$5$subexpression$1"], "postprocess": id},
343
- {"name": "SUFFIX$ebnf$5", "symbols": [], "postprocess": function(d) {return null;}},
344
- {"name": "SUFFIX$ebnf$6", "symbols": ["annotation"], "postprocess": id},
345
- {"name": "SUFFIX$ebnf$6", "symbols": [], "postprocess": function(d) {return null;}},
346
- {"name": "SUFFIX$ebnf$7$subexpression$1", "symbols": ["_", "NAG"]},
347
- {"name": "SUFFIX$ebnf$7", "symbols": ["SUFFIX$ebnf$7$subexpression$1"]},
348
- {"name": "SUFFIX$ebnf$7$subexpression$2", "symbols": ["_", "NAG"]},
349
- {"name": "SUFFIX$ebnf$7", "symbols": ["SUFFIX$ebnf$7", "SUFFIX$ebnf$7$subexpression$2"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
350
- {"name": "SUFFIX", "symbols": ["SUFFIX$ebnf$5", "SUFFIX$ebnf$6", "SUFFIX$ebnf$7"], "postprocess":
351
- (d) => ({
352
- ...(d[0] && { [d[0]]: true }),
353
- ...((d[1] || d[2].length > 0) && { annotations: [...(d[1] ? [d[1]] : []), ...d[2].map(d2 => d2[1])] }),
354
- })
355
- },
356
- {"name": "NAG$subexpression$1$string$1", "symbols": [{"literal":"2"}, {"literal":"5"}], "postprocess": function joiner(d) {return d.join('');}},
357
- {"name": "NAG$subexpression$1", "symbols": ["NAG$subexpression$1$string$1", /[0-5]/]},
358
- {"name": "NAG$subexpression$1", "symbols": [{"literal":"2"}, /[0-4]/, /[0-9]/]},
359
- {"name": "NAG$subexpression$1", "symbols": [{"literal":"1"}, /[0-9]/, /[0-9]/]},
360
- {"name": "NAG$subexpression$1", "symbols": [/[1-9]/, /[0-9]/]},
361
- {"name": "NAG$subexpression$1", "symbols": [/[0-9]/]},
362
- {"name": "NAG", "symbols": [{"literal":"$"}, "NAG$subexpression$1"], "postprocess":
363
- (d) => d[1]
364
- },
365
- {"name": "COMMENT", "symbols": ["bstring"]},
366
- {"name": "COMMENT$ebnf$1", "symbols": []},
367
- {"name": "COMMENT$ebnf$1", "symbols": ["COMMENT$ebnf$1", /[^\n]/], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
368
- {"name": "COMMENT", "symbols": [{"literal":";"}, "COMMENT$ebnf$1"]},
369
- {"name": "annotation$string$1", "symbols": [{"literal":"!"}, {"literal":"!"}], "postprocess": function joiner(d) {return d.join('');}},
370
- {"name": "annotation", "symbols": ["annotation$string$1"], "postprocess": id},
371
- {"name": "annotation", "symbols": [{"literal":"!"}], "postprocess": id},
372
- {"name": "annotation$string$2", "symbols": [{"literal":"!"}, {"literal":"?"}], "postprocess": function joiner(d) {return d.join('');}},
373
- {"name": "annotation", "symbols": ["annotation$string$2"], "postprocess": id},
374
- {"name": "annotation$string$3", "symbols": [{"literal":"?"}, {"literal":"!"}], "postprocess": function joiner(d) {return d.join('');}},
375
- {"name": "annotation", "symbols": ["annotation$string$3"], "postprocess": id},
376
- {"name": "annotation", "symbols": [{"literal":"?"}], "postprocess": id},
377
- {"name": "annotation$string$4", "symbols": [{"literal":"?"}, {"literal":"?"}], "postprocess": function joiner(d) {return d.join('');}},
378
- {"name": "annotation", "symbols": ["annotation$string$4"], "postprocess": id},
379
- {"name": "annotation$string$5", "symbols": [{"literal":"+"}, {"literal":"-"}], "postprocess": function joiner(d) {return d.join('');}},
380
- {"name": "annotation", "symbols": ["annotation$string$5"], "postprocess": id},
381
- {"name": "annotation$string$6", "symbols": [{"literal":"-"}, {"literal":"+"}], "postprocess": function joiner(d) {return d.join('');}},
382
- {"name": "annotation", "symbols": ["annotation$string$6"], "postprocess": id},
383
- {"name": "annotation", "symbols": [{"literal":"="}], "postprocess": id},
384
- {"name": "annotation$string$7", "symbols": [{"literal":"?"}, {"literal":"!"}], "postprocess": function joiner(d) {return d.join('');}},
385
- {"name": "annotation", "symbols": ["annotation$string$7"], "postprocess": id},
386
- {"name": "annotation", "symbols": [{"literal":"?"}], "postprocess": id},
387
- {"name": "annotation$string$8", "symbols": [{"literal":"?"}, {"literal":"?"}], "postprocess": function joiner(d) {return d.join('');}},
388
- {"name": "annotation", "symbols": ["annotation$string$8"], "postprocess": id},
389
- {"name": "annotation", "symbols": [{"literal":"±"}], "postprocess": id},
390
- {"name": "annotation", "symbols": [{"literal":"∓"}], "postprocess": id},
391
- {"name": "annotation", "symbols": [{"literal":"∞"}], "postprocess": id},
392
- {"name": "annotation", "symbols": [{"literal":"⨀"}], "postprocess": id},
393
- {"name": "annotation", "symbols": [{"literal":"⩱"}], "postprocess": id},
394
- {"name": "annotation", "symbols": [{"literal":"⩲"}], "postprocess": id},
395
- {"name": "check", "symbols": [{"literal":"+"}], "postprocess": () => 'check'},
396
- {"name": "checkmate", "symbols": [{"literal":"#"}], "postprocess": () => 'checkmate'},
397
- {"name": "bstring$ebnf$1", "symbols": []},
398
- {"name": "bstring$ebnf$1", "symbols": ["bstring$ebnf$1", /[^}]/], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
399
- {"name": "bstring", "symbols": [{"literal":"{"}, "bstring$ebnf$1", {"literal":"}"}], "postprocess": (d) => d[1].join('')},
400
- {"name": "capture", "symbols": [{"literal":"x"}]},
401
- {"name": "castling$string$1", "symbols": [{"literal":"O"}, {"literal":"-"}, {"literal":"O"}], "postprocess": function joiner(d) {return d.join('');}},
402
- {"name": "castling", "symbols": ["castling$string$1"], "postprocess": () => 'K'},
403
- {"name": "castling$string$2", "symbols": [{"literal":"O"}, {"literal":"-"}, {"literal":"O"}, {"literal":"-"}, {"literal":"O"}], "postprocess": function joiner(d) {return d.join('');}},
404
- {"name": "castling", "symbols": ["castling$string$2"], "postprocess": () => 'Q'},
405
- {"name": "continuation$string$1", "symbols": [{"literal":"."}, {"literal":"."}, {"literal":"."}], "postprocess": function joiner(d) {return d.join('');}},
406
- {"name": "continuation", "symbols": ["continuation$string$1"]},
407
- {"name": "file", "symbols": [/[a-h]/]},
408
- {"name": "piece", "symbols": [/[KQBNR]/]},
409
- {"name": "rank", "symbols": [/[1-8]/]},
410
- {"name": "result$string$1", "symbols": [{"literal":"1"}, {"literal":"-"}, {"literal":"0"}], "postprocess": function joiner(d) {return d.join('');}},
411
- {"name": "result", "symbols": ["result$string$1"], "postprocess": () => 1},
412
- {"name": "result$string$2", "symbols": [{"literal":"0"}, {"literal":"-"}, {"literal":"1"}], "postprocess": function joiner(d) {return d.join('');}},
413
- {"name": "result", "symbols": ["result$string$2"], "postprocess": () => 0},
414
- {"name": "result$string$3", "symbols": [{"literal":"1"}, {"literal":"/"}, {"literal":"2"}, {"literal":"-"}, {"literal":"1"}, {"literal":"/"}, {"literal":"2"}], "postprocess": function joiner(d) {return d.join('');}},
415
- {"name": "result", "symbols": ["result$string$3"], "postprocess": () => 0.5},
416
- {"name": "result", "symbols": [{"literal":"*"}], "postprocess": () => '?'},
417
- {"name": "string$ebnf$1", "symbols": [/[^\s]/]},
418
- {"name": "string$ebnf$1", "symbols": ["string$ebnf$1", /[^\s]/], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
419
- {"name": "string", "symbols": ["string$ebnf$1"], "postprocess": (d) => d[0].join('')}
420
- ]
421
- , ParserStart: "DATABASE"
422
- }
423
- if (typeof module !== 'undefined'&& typeof module.exports !== 'undefined') {
424
- module.exports = grammar;
425
- } else {
426
- window.grammar = grammar;
427
- }
428
- })();
package/src/grammar.ne DELETED
@@ -1,242 +0,0 @@
1
- @builtin "number.ne"
2
- @builtin "string.ne"
3
- @builtin "whitespace.ne"
4
-
5
- # ----- pgn ----- #
6
- DATABASE -> GAME:+ {% id %}
7
-
8
- # TAGS contains whitespace at the end
9
- GAME -> TAGS MOVE_SECTION __ result __ {%
10
- (d) => ({ meta: d[0], moves: d[1], result: d[3] })
11
- %}
12
- # ----- /pgn ---- #
13
-
14
- # ----- tags ----- #
15
- TAGS -> (TAG __):+ {% (d) => d[0].map(d0 => d0[0]).reduce((acc, item) => ({ ...acc, ...item }), {}) %}
16
-
17
- TAG -> "[" NAME __ VALUE "]" {% (d) => ({ [d[1]]: d[3] }) %}
18
-
19
- NAME -> string
20
-
21
- VALUE -> dqstring {% id %}
22
- # ----- /tags ----- #
23
-
24
-
25
- # ----- moves ----- #
26
- MOVE_SECTION ->
27
- MOVE (_ MOVE):* (_ HM_WHITE):? {%
28
- (d) => {
29
- const moves = [d[0]];
30
-
31
- if (d[1].length > 0) {
32
- const d1 = d[1];
33
-
34
- moves.push(...d1.map(d => d[1]));
35
- }
36
-
37
- if (d[2]) {
38
- const d2 = d[2];
39
-
40
- moves.push(d2[1]);
41
- }
42
-
43
- return moves;
44
- }
45
- %}
46
- | HM_WHITE {% d => [d[0]] %}
47
-
48
- MOVES -> (_ MOVE):* (_ HM_WHITE):? {%
49
- (d) => {
50
- const moves = [];
51
-
52
- if (d[0]) {
53
- d[0].map(d0 => d0[1]).map(d01 => moves.push(d01));
54
- }
55
-
56
- if (d[1]) {
57
- moves.push(d[1][1]);
58
- }
59
-
60
- return moves;
61
- }
62
- %}
63
-
64
- # Half Move White #
65
- HM_WHITE -> NUMBER _ SAN (_ VARIANT):* {%
66
- (d) => {
67
- const move = [d[0], {...d[2], ...(d[3].length > 0 && { variants: d[3].map(d3 => d3[1]) }), }];
68
-
69
- if (move[1].castling) {
70
- move[1].to = move[1].castling === 'K' ? 'g1' : 'c1';
71
- move[1].castling = true;
72
- }
73
-
74
- return move;
75
- }
76
- %}
77
-
78
- HM_BLACK -> _ NUMBER continuation _ SAN (_ VARIANT):* {%
79
- (d) => {
80
- const move = [d[1], undefined, {...d[4], ...(d[5].length > 0 && { variants: d[5].map(d5 => d5[1]) }) }];
81
-
82
- if (move[2].castling) {
83
- move[2].to = move[2].castling === 'K' ? 'g8' : 'c8';
84
- move[2].castling = true;
85
- }
86
-
87
- return move;
88
- }
89
- %}
90
-
91
- MOVE ->
92
- NUMBER _ SAN __ SAN (_ VARIANT):* {%
93
- (d) => {
94
- const move = [d[0], d[2], d[4]];
95
-
96
- if (move[1].castling) {
97
- move[1].to = move[1].castling === 'K' ? 'g1' : 'c1';
98
- move[1].castling = true;
99
- }
100
-
101
- if (move[2].castling) {
102
- move[2].to = move[2].castling === 'K' ? 'g8' : 'c8';
103
- move[2].castling = true;
104
- }
105
-
106
- if (d[5]) {
107
- const variants = d[5].map(d5 => d5[1]);
108
-
109
- const white = variants.filter(variant => variant[0][1]);
110
- const black = variants.filter(variant => !variant[0][1]);
111
-
112
- if (white.length > 0) {
113
- move[1].variants = white;
114
- }
115
-
116
- if (black.length > 0) {
117
- move[2].variants = black;
118
- }
119
- }
120
-
121
- return move;
122
- }
123
- %}
124
- | HM_WHITE __ HM_BLACK {%
125
- d => [d[0][0], d[0][1], d[2][2]]
126
- %}
127
-
128
- NUMBER -> unsigned_int ".":? {% (d) => d[0] %}
129
-
130
- VARIANT ->
131
- "(" MOVES _ ")" {%
132
- (d) => d[1]
133
- %}
134
- | "(" HM_BLACK MOVES _ ")" {%
135
- (d) => [d[1], ...d[2]]
136
- %}
137
-
138
- # ----- /moves ----- #
139
-
140
- # ----- san ----- #
141
-
142
- SAN ->
143
- piece:? DISAMBIGUATION:? capture:? file rank PROMOTION:? (_ SUFFIX):? (_ COMMENT):* {%
144
- (d) => {
145
- const comments = d[7].map(d7 => d7[1]).filter(Boolean);
146
-
147
- return ({
148
- ...(d[6] && d[6][1]),
149
- ...(comments.length > 0 && { comment: comments.reduce((acc, item) => `${acc} ${item}`, '') }),
150
- ...(d[2] && { capture: true }),
151
- ...(d[1] && { from: d[1][0] }),
152
- piece: d[0] ? d[0][0] : 'P',
153
- ...(d[5] && { promotion: d[5] }),
154
- to: `${d[3]}${d[4]}`,
155
- });
156
- }
157
- %}
158
- | castling (_ SUFFIX):* (_ COMMENT):* {%
159
- (d) => {
160
- const comments = d[2].map(d2 => d2[1]).filter(Boolean);
161
-
162
- return ({
163
- ...(d[1]),
164
- ...(comments.length > 0 && { comment: comments.reduce((acc, item) => `${acc} ${item}`, '') }),
165
- castling: d[0],
166
- piece: 'K'
167
- })
168
- }
169
- %}
170
-
171
- DISAMBIGUATION ->
172
- file {% id %}
173
- | rank {% id %}
174
-
175
- PROMOTION -> "=" [QBNR] {% (d) => d[1] %}
176
-
177
- SUFFIX ->
178
- (check | checkmate) annotation:? (_ NAG):* {%
179
- (d) => ({
180
- ...(d[0] && { [d[0]]: true }),
181
- ...((d[1] || d[2].length > 0) && { annotations: [...(d[1] ? [d[1]] : []), ...d[2].map(d2 => d2[1])] }),
182
- })
183
- %}
184
- | (check | checkmate):? annotation (_ NAG):* {%
185
- (d) => ({
186
- ...(d[0] && { [d[0]]: true }),
187
- ...((d[1] || d[2].length > 0) && { annotations: [...(d[1] ? [d[1]] : []), ...d[2].map(d2 => d2[1])] }),
188
- })
189
- %}
190
- | (check | checkmate):? annotation:? (_ NAG):+ {%
191
- (d) => ({
192
- ...(d[0] && { [d[0]]: true }),
193
- ...((d[1] || d[2].length > 0) && { annotations: [...(d[1] ? [d[1]] : []), ...d[2].map(d2 => d2[1])] }),
194
- })
195
- %}
196
-
197
- # Numeric Annotation Glyph
198
- NAG -> "$" ("25" [0-5] | "2" [0-4] [0-9] | "1" [0-9] [0-9] | [1-9] [0-9] | [0-9]) {%
199
- (d) => d[1]
200
- %}
201
-
202
- COMMENT -> bstring | ";" [^\n]:*
203
-
204
- # ----- /san ----- #
205
-
206
- # types
207
- annotation ->
208
- "!!" {% id %}
209
- | "!" {% id %}
210
- | "!?" {% id %}
211
- | "?!" {% id %}
212
- | "?" {% id %}
213
- | "??" {% id %}
214
- | "+-" {% id %}
215
- | "-+" {% id %}
216
- | "=" {% id %}
217
- | "?!" {% id %}
218
- | "?" {% id %}
219
- | "??" {% id %}
220
- | "±" {% id %}
221
- | "∓" {% id %}
222
- | "∞" {% id %}
223
- | "⨀" {% id %}
224
- | "⩱" {% id %}
225
- | "⩲" {% id %}
226
- check -> "+" {% () => 'check' %}
227
- checkmate -> "#" {% () => 'checkmate' %}
228
- bstring -> "{" [^}]:* "}" {% (d) => d[1].join('') %}
229
- capture -> "x"
230
- castling ->
231
- "O-O" {% () => 'K' %}
232
- | "O-O-O" {% () => 'Q' %}
233
- continuation -> "..."
234
- file -> [a-h]
235
- piece -> [KQBNR]
236
- rank -> [1-8]
237
- result ->
238
- "1-0" {% () => 1 %}
239
- | "0-1" {% () => 0 %}
240
- | "1/2-1/2" {% () => 0.5 %}
241
- | "*" {% () => '?' %}
242
- string -> [^\s]:+ {% (d) => d[0].join('') %}
package/src/index.ts DELETED
@@ -1,59 +0,0 @@
1
- import { Grammar, Parser } from 'nearley';
2
-
3
- import grammar from './grammar';
4
-
5
- type File = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h';
6
- type Piece = 'B' | 'K' | 'N' | 'P' | 'Q' | 'R';
7
- type Rank = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8';
8
- type Result = '1-0' | '0-1' | '1/2-1/2' | '?';
9
-
10
- type Square = `${File}${Rank}`;
11
-
12
- type HalfMove = [number, undefined, Move];
13
- type VariantMove = Move | HalfMove;
14
- type VariantMoves = VariantMove[];
15
-
16
- type Move = {
17
- annotations?: string[];
18
- capture?: boolean;
19
- castling?: boolean;
20
- check?: boolean;
21
- checkmate?: boolean;
22
- comment?: string;
23
- from?: File | Rank;
24
- piece: Piece;
25
- promotion?: Piece;
26
- to: Square;
27
- variants?: VariantMoves[];
28
- };
29
-
30
- type Meta = {
31
- Result: Result;
32
- [key: string]: string;
33
- };
34
-
35
- type Moves = [number, Move] | [number, Move, Move];
36
-
37
- type PGN = {
38
- meta: Meta;
39
- moves: Moves;
40
- result: Result;
41
- };
42
-
43
- function tokenize(input: string): PGN[] {
44
- const parser = new Parser(Grammar.fromCompiled(grammar));
45
-
46
- parser.feed(input);
47
-
48
- if (parser.results.length > 1) {
49
- throw new Error(`@echecs/parser: Ambiguous syntax. Found ${parser.results.length} results`);
50
- }
51
-
52
- return parser.results[0] as PGN[];
53
- }
54
-
55
- export default function parse(input: string): PGN[] {
56
- const games = input.replace(/[\r\uFEFF]/g, '');
57
-
58
- return tokenize(games);
59
- }
@@ -1,15 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "allowJs": true,
4
- "declaration": true,
5
- "esModuleInterop": true,
6
- "forceConsistentCasingInFileNames": true,
7
- "module": "ESNext",
8
- "moduleResolution": "node",
9
- "outDir": "dist/",
10
- "removeComments": true,
11
- "resolveJsonModule": true,
12
- "strict": true,
13
- "target": "ESNext"
14
- }
15
- }
package/tsconfig.json DELETED
@@ -1,16 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "allowJs": true,
4
- "declaration": true,
5
- "esModuleInterop": true,
6
- "forceConsistentCasingInFileNames": true,
7
- "module": "ESNext",
8
- "moduleResolution": "node",
9
- "outDir": "dist/",
10
- "removeComments": true,
11
- "resolveJsonModule": true,
12
- "strict": true,
13
- "target": "ESNext"
14
- },
15
- "files": ["src/index.ts"]
16
- }