@echecs/pgn 1.0.0 → 2.1.1
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/.github/dependabot.yml +11 -0
- package/.github/workflows/release.yml +34 -0
- package/.husky/pre-commit +4 -0
- package/.husky/pre-push +4 -0
- package/LICENSE +21 -0
- package/README.md +21 -6
- package/dist/grammar.d.ts +35 -0
- package/dist/grammar.js +190 -116
- package/dist/index.d.ts +33 -0
- package/dist/index.js +14 -0
- package/jest.config.js +5 -0
- package/package.json +33 -42
- package/src/grammar.js +190 -116
- package/src/grammar.ne +137 -87
- package/src/index.ts +59 -0
- package/tsconfig.eslint.json +15 -0
- package/tsconfig.json +16 -0
- package/dist/cjs/pgn.js +0 -25
- package/dist/cjs/pgn.js.map +0 -1
- package/dist/es/pgn.js +0 -19
- package/dist/es/pgn.js.map +0 -1
- package/index.js +0 -1
- package/index.module.js +0 -1
- package/src/index.js +0 -13
|
@@ -0,0 +1,34 @@
|
|
|
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-push
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Adrian de la Rosa
|
|
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 all
|
|
13
|
+
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 THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,19 +1,34 @@
|
|
|
1
1
|
# PGN
|
|
2
2
|
|
|
3
|
-
PGN is part of the project
|
|
4
|
-
specification
|
|
5
|
-
[Specification](http://www.saremba.de/chessgml/standards/pgn/pgn-complete.htm)
|
|
3
|
+
**PGN** is part of the **ECHECS** project. **PGN** is a parser of the
|
|
4
|
+
[PGN specification](http://www.saremba.de/chessgml/standards/pgn/pgn-complete.htm).
|
|
6
5
|
|
|
7
|
-
##
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install --save-dev @echecs/pgn
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
yarn add @echecs/pgn
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
8
17
|
|
|
9
18
|
We just need to provide with a PGN to the parser. It always return an array
|
|
10
19
|
because PGN files could contain several games.
|
|
11
20
|
|
|
12
21
|
```js
|
|
13
|
-
|
|
22
|
+
import { readFileSync } from 'fs';
|
|
23
|
+
import parse from '@echecs/pgn';
|
|
24
|
+
|
|
25
|
+
function readFile(path: string): string {
|
|
26
|
+
const filename = require.resolve(path);
|
|
14
27
|
|
|
15
|
-
|
|
28
|
+
return readFileSync(filename, 'utf8');
|
|
29
|
+
}
|
|
16
30
|
|
|
31
|
+
const pgn = parse(readFile('./games/file.pgn'));
|
|
17
32
|
// [
|
|
18
33
|
// {
|
|
19
34
|
// "meta": {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export const Lexer: undefined;
|
|
2
|
+
export const ParserRules: ({
|
|
3
|
+
name: string;
|
|
4
|
+
symbols: (string | RegExp)[];
|
|
5
|
+
postprocess: (d: any) => any;
|
|
6
|
+
} | {
|
|
7
|
+
name: string;
|
|
8
|
+
symbols: (string | {
|
|
9
|
+
literal: string;
|
|
10
|
+
})[];
|
|
11
|
+
postprocess?: undefined;
|
|
12
|
+
} | {
|
|
13
|
+
name: string;
|
|
14
|
+
symbols: (string | RegExp)[];
|
|
15
|
+
postprocess?: undefined;
|
|
16
|
+
} | {
|
|
17
|
+
name: string;
|
|
18
|
+
symbols: (string | {
|
|
19
|
+
literal: string;
|
|
20
|
+
})[];
|
|
21
|
+
postprocess: (d: any) => any;
|
|
22
|
+
} | {
|
|
23
|
+
name: string;
|
|
24
|
+
symbols: (RegExp | {
|
|
25
|
+
literal: string;
|
|
26
|
+
})[];
|
|
27
|
+
postprocess: (d: any) => any;
|
|
28
|
+
} | {
|
|
29
|
+
name: string;
|
|
30
|
+
symbols: (RegExp | {
|
|
31
|
+
literal: string;
|
|
32
|
+
})[];
|
|
33
|
+
postprocess?: undefined;
|
|
34
|
+
})[];
|
|
35
|
+
export const ParserStart: string;
|
package/dist/grammar.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Generated automatically by nearley, version 2.
|
|
1
|
+
// Generated automatically by nearley, version 2.20.1
|
|
2
2
|
// http://github.com/Hardmath123/nearley
|
|
3
3
|
(function () {
|
|
4
4
|
function id(x) { return x[0]; }
|
|
@@ -126,41 +126,70 @@ var grammar = {
|
|
|
126
126
|
{"name": "DATABASE$ebnf$1", "symbols": ["GAME"]},
|
|
127
127
|
{"name": "DATABASE$ebnf$1", "symbols": ["DATABASE$ebnf$1", "GAME"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
|
|
128
128
|
{"name": "DATABASE", "symbols": ["DATABASE$ebnf$1"], "postprocess": id},
|
|
129
|
-
{"name": "GAME", "symbols": ["TAGS", "
|
|
130
|
-
(d) => ({ meta: d[0], moves: d[
|
|
129
|
+
{"name": "GAME", "symbols": ["TAGS", "MOVE_SECTION", "__", "result", "__"], "postprocess":
|
|
130
|
+
(d) => ({ meta: d[0], moves: d[1], result: d[3] })
|
|
131
131
|
},
|
|
132
|
-
{"name": "TAGS$ebnf$1", "symbols": ["TAG"]},
|
|
133
|
-
{"name": "TAGS$ebnf$1", "symbols": ["TAGS$ebnf$1"
|
|
134
|
-
{"name": "TAGS", "symbols": ["
|
|
135
|
-
{"name": "
|
|
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] })},
|
|
136
138
|
{"name": "NAME", "symbols": ["string"]},
|
|
137
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]]},
|
|
138
166
|
{"name": "MOVES$ebnf$1", "symbols": []},
|
|
139
|
-
{"name": "MOVES$ebnf$1", "symbols": ["
|
|
140
|
-
{"name": "MOVES$ebnf$
|
|
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},
|
|
141
171
|
{"name": "MOVES$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}},
|
|
142
172
|
{"name": "MOVES", "symbols": ["MOVES$ebnf$1", "MOVES$ebnf$2"], "postprocess":
|
|
143
173
|
(d) => {
|
|
144
174
|
const moves = [];
|
|
145
|
-
const assign = (number, ...move) => {
|
|
146
|
-
moves[number - 1] = move;
|
|
147
|
-
};
|
|
148
175
|
|
|
149
|
-
d[0]
|
|
176
|
+
if (d[0]) {
|
|
177
|
+
d[0].map(d0 => d0[1]).map(d01 => moves.push(d01));
|
|
178
|
+
}
|
|
150
179
|
|
|
151
180
|
if (d[1]) {
|
|
152
|
-
|
|
181
|
+
moves.push(d[1][1]);
|
|
153
182
|
}
|
|
154
183
|
|
|
155
184
|
return moves;
|
|
156
185
|
}
|
|
157
186
|
},
|
|
158
|
-
{"name": "
|
|
159
|
-
{"name": "
|
|
160
|
-
{"name": "
|
|
161
|
-
{"name": "
|
|
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":
|
|
162
191
|
(d) => {
|
|
163
|
-
const move = [d[0], {...d[2], ...(d[3] && {
|
|
192
|
+
const move = [d[0], {...d[2], ...(d[3].length > 0 && { variants: d[3].map(d3 => d3[1]) }), }];
|
|
164
193
|
|
|
165
194
|
if (move[1].castling) {
|
|
166
195
|
move[1].to = move[1].castling === 'K' ? 'g1' : 'c1';
|
|
@@ -170,155 +199,201 @@ var grammar = {
|
|
|
170
199
|
return move;
|
|
171
200
|
}
|
|
172
201
|
},
|
|
173
|
-
{"name": "
|
|
174
|
-
{"name": "
|
|
175
|
-
{"name": "
|
|
176
|
-
{"name": "
|
|
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":
|
|
177
206
|
(d) => {
|
|
178
|
-
const move = [d[
|
|
179
|
-
|
|
180
|
-
if (move[1].castling) {
|
|
181
|
-
move[1].to = move[1].castling === 'K' ? 'g1' : 'c1';
|
|
182
|
-
move[1].castling = true;
|
|
183
|
-
}
|
|
207
|
+
const move = [d[1], undefined, {...d[4], ...(d[5].length > 0 && { variants: d[5].map(d5 => d5[1]) }) }];
|
|
184
208
|
|
|
185
209
|
if (move[2].castling) {
|
|
186
210
|
move[2].to = move[2].castling === 'K' ? 'g8' : 'c8';
|
|
187
211
|
move[2].castling = true;
|
|
188
212
|
}
|
|
189
213
|
|
|
190
|
-
if (d[5]) {
|
|
191
|
-
const variant = d[5][1];
|
|
192
|
-
const isWhite = variant[0][0] !== undefined;
|
|
193
|
-
|
|
194
|
-
move[isWhite ? 1 : 2].variation = d[5][1];
|
|
195
|
-
}
|
|
196
|
-
|
|
197
214
|
return move;
|
|
198
215
|
}
|
|
199
216
|
},
|
|
200
|
-
{"name": "
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
{"name": "
|
|
204
|
-
(d) => [...d[1].values()].filter(Boolean)
|
|
205
|
-
},
|
|
206
|
-
{"name": "MOVES_BLACK$ebnf$1", "symbols": ["MOVES"], "postprocess": id},
|
|
207
|
-
{"name": "MOVES_BLACK$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
|
|
208
|
-
{"name": "MOVES_BLACK", "symbols": ["HALFMOVE_BLACK", "MOVES_BLACK$ebnf$1"], "postprocess":
|
|
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":
|
|
209
221
|
(d) => {
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
const assign = (number, ...move) => {
|
|
213
|
-
moves[number - 1] = move;
|
|
214
|
-
};
|
|
222
|
+
const move = [d[0], d[2], d[4]];
|
|
215
223
|
|
|
216
|
-
if (
|
|
217
|
-
|
|
224
|
+
if (move[1].castling) {
|
|
225
|
+
move[1].to = move[1].castling === 'K' ? 'g1' : 'c1';
|
|
226
|
+
move[1].castling = true;
|
|
218
227
|
}
|
|
219
228
|
|
|
220
|
-
return moves;
|
|
221
|
-
}
|
|
222
|
-
},
|
|
223
|
-
{"name": "HALFMOVE_BLACK$ebnf$1$subexpression$1", "symbols": ["_", "VARIATION"]},
|
|
224
|
-
{"name": "HALFMOVE_BLACK$ebnf$1", "symbols": ["HALFMOVE_BLACK$ebnf$1$subexpression$1"], "postprocess": id},
|
|
225
|
-
{"name": "HALFMOVE_BLACK$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
|
|
226
|
-
{"name": "HALFMOVE_BLACK", "symbols": ["NUMBER", "continuation", "_", "SAN", "HALFMOVE_BLACK$ebnf$1", "_"], "postprocess":
|
|
227
|
-
(d) => {
|
|
228
|
-
const move = [
|
|
229
|
-
d[0],
|
|
230
|
-
undefined,
|
|
231
|
-
{...d[3], ...(d[4] && { variation: d[4][1] }), }
|
|
232
|
-
];
|
|
233
|
-
|
|
234
229
|
if (move[2].castling) {
|
|
235
230
|
move[2].to = move[2].castling === 'K' ? 'g8' : 'c8';
|
|
236
231
|
move[2].castling = true;
|
|
237
232
|
}
|
|
238
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
|
+
|
|
239
249
|
return move;
|
|
240
250
|
}
|
|
241
|
-
|
|
242
|
-
{"name": "
|
|
243
|
-
|
|
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;}},
|
|
244
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
|
+
},
|
|
245
264
|
{"name": "SAN$ebnf$1", "symbols": ["piece"], "postprocess": id},
|
|
246
265
|
{"name": "SAN$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
|
|
247
266
|
{"name": "SAN$ebnf$2", "symbols": ["DISAMBIGUATION"], "postprocess": id},
|
|
248
267
|
{"name": "SAN$ebnf$2", "symbols": [], "postprocess": function(d) {return null;}},
|
|
249
268
|
{"name": "SAN$ebnf$3", "symbols": ["capture"], "postprocess": id},
|
|
250
269
|
{"name": "SAN$ebnf$3", "symbols": [], "postprocess": function(d) {return null;}},
|
|
251
|
-
{"name": "SAN$ebnf$4", "symbols": ["
|
|
270
|
+
{"name": "SAN$ebnf$4", "symbols": ["PROMOTION"], "postprocess": id},
|
|
252
271
|
{"name": "SAN$ebnf$4", "symbols": [], "postprocess": function(d) {return null;}},
|
|
253
|
-
{"name": "SAN$ebnf$5", "symbols": []},
|
|
254
|
-
{"name": "SAN$ebnf$5
|
|
255
|
-
{"name": "SAN$ebnf$5", "symbols": [
|
|
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": []},
|
|
256
276
|
{"name": "SAN$ebnf$6$subexpression$1", "symbols": ["_", "COMMENT"]},
|
|
257
|
-
{"name": "SAN$ebnf$6", "symbols": ["SAN$ebnf$6$subexpression$1"], "postprocess":
|
|
258
|
-
{"name": "SAN$ebnf$6", "symbols": [], "postprocess": function(d) {return null;}},
|
|
277
|
+
{"name": "SAN$ebnf$6", "symbols": ["SAN$ebnf$6", "SAN$ebnf$6$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
|
|
259
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":
|
|
260
|
-
(d) =>
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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
|
+
}
|
|
268
292
|
},
|
|
269
293
|
{"name": "SAN$ebnf$7", "symbols": []},
|
|
270
|
-
{"name": "SAN$ebnf$7$subexpression$1", "symbols": ["_", "
|
|
294
|
+
{"name": "SAN$ebnf$7$subexpression$1", "symbols": ["_", "SUFFIX"]},
|
|
271
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": []},
|
|
272
297
|
{"name": "SAN$ebnf$8$subexpression$1", "symbols": ["_", "COMMENT"]},
|
|
273
|
-
{"name": "SAN$ebnf$8", "symbols": ["SAN$ebnf$8$subexpression$1"], "postprocess":
|
|
274
|
-
{"name": "SAN$ebnf$8", "symbols": [], "postprocess": function(d) {return null;}},
|
|
298
|
+
{"name": "SAN$ebnf$8", "symbols": ["SAN$ebnf$8", "SAN$ebnf$8$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
|
|
275
299
|
{"name": "SAN", "symbols": ["castling", "SAN$ebnf$7", "SAN$ebnf$8"], "postprocess":
|
|
276
|
-
(d) =>
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
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
|
+
}
|
|
282
310
|
},
|
|
283
311
|
{"name": "DISAMBIGUATION", "symbols": ["file"], "postprocess": id},
|
|
284
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
|
+
},
|
|
285
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"]},
|
|
286
369
|
{"name": "annotation$string$1", "symbols": [{"literal":"!"}, {"literal":"!"}], "postprocess": function joiner(d) {return d.join('');}},
|
|
287
370
|
{"name": "annotation", "symbols": ["annotation$string$1"], "postprocess": id},
|
|
288
371
|
{"name": "annotation", "symbols": [{"literal":"!"}], "postprocess": id},
|
|
289
372
|
{"name": "annotation$string$2", "symbols": [{"literal":"!"}, {"literal":"?"}], "postprocess": function joiner(d) {return d.join('');}},
|
|
290
373
|
{"name": "annotation", "symbols": ["annotation$string$2"], "postprocess": id},
|
|
291
|
-
{"name": "annotation", "symbols": [{"literal":"
|
|
292
|
-
{"name": "annotation
|
|
293
|
-
{"name": "annotation", "symbols": ["
|
|
294
|
-
{"name": "annotation$string$4", "symbols": [{"literal":"
|
|
295
|
-
{"name": "annotation", "symbols": ["annotation$string$4"], "postprocess":
|
|
296
|
-
{"name": "annotation$string$5", "symbols": [{"literal":"
|
|
297
|
-
{"name": "annotation", "symbols": ["annotation$string$5"], "postprocess":
|
|
298
|
-
{"name": "annotation$string$6", "symbols": [{"literal":"
|
|
299
|
-
{"name": "annotation", "symbols": ["annotation$string$6"], "postprocess":
|
|
300
|
-
{"name": "annotation$string$7", "symbols": [{"literal":"$"}, {"literal":"5"}], "postprocess": function joiner(d) {return d.join('');}},
|
|
301
|
-
{"name": "annotation", "symbols": ["annotation$string$7"], "postprocess": () => '?!'},
|
|
302
|
-
{"name": "annotation$string$8", "symbols": [{"literal":"$"}, {"literal":"6"}], "postprocess": function joiner(d) {return d.join('');}},
|
|
303
|
-
{"name": "annotation", "symbols": ["annotation$string$8"], "postprocess": () => '??'},
|
|
304
|
-
{"name": "annotation", "symbols": [{"literal":"+"}], "postprocess": () => 'check'},
|
|
305
|
-
{"name": "annotation$string$9", "symbols": [{"literal":"+"}, {"literal":"-"}], "postprocess": function joiner(d) {return d.join('');}},
|
|
306
|
-
{"name": "annotation", "symbols": ["annotation$string$9"], "postprocess": id},
|
|
307
|
-
{"name": "annotation$string$10", "symbols": [{"literal":"-"}, {"literal":"+"}], "postprocess": function joiner(d) {return d.join('');}},
|
|
308
|
-
{"name": "annotation", "symbols": ["annotation$string$10"], "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},
|
|
309
383
|
{"name": "annotation", "symbols": [{"literal":"="}], "postprocess": id},
|
|
310
|
-
{"name": "annotation$string$
|
|
311
|
-
{"name": "annotation", "symbols": ["annotation$string$
|
|
384
|
+
{"name": "annotation$string$7", "symbols": [{"literal":"?"}, {"literal":"!"}], "postprocess": function joiner(d) {return d.join('');}},
|
|
385
|
+
{"name": "annotation", "symbols": ["annotation$string$7"], "postprocess": id},
|
|
312
386
|
{"name": "annotation", "symbols": [{"literal":"?"}], "postprocess": id},
|
|
313
|
-
{"name": "annotation$string$
|
|
314
|
-
{"name": "annotation", "symbols": ["annotation$string$
|
|
315
|
-
{"name": "annotation", "symbols": [{"literal":"N"}], "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},
|
|
316
389
|
{"name": "annotation", "symbols": [{"literal":"±"}], "postprocess": id},
|
|
317
390
|
{"name": "annotation", "symbols": [{"literal":"∓"}], "postprocess": id},
|
|
318
391
|
{"name": "annotation", "symbols": [{"literal":"∞"}], "postprocess": id},
|
|
319
392
|
{"name": "annotation", "symbols": [{"literal":"⨀"}], "postprocess": id},
|
|
320
393
|
{"name": "annotation", "symbols": [{"literal":"⩱"}], "postprocess": id},
|
|
321
394
|
{"name": "annotation", "symbols": [{"literal":"⩲"}], "postprocess": id},
|
|
395
|
+
{"name": "check", "symbols": [{"literal":"+"}], "postprocess": () => 'check'},
|
|
396
|
+
{"name": "checkmate", "symbols": [{"literal":"#"}], "postprocess": () => 'checkmate'},
|
|
322
397
|
{"name": "bstring$ebnf$1", "symbols": []},
|
|
323
398
|
{"name": "bstring$ebnf$1", "symbols": ["bstring$ebnf$1", /[^}]/], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
|
|
324
399
|
{"name": "bstring", "symbols": [{"literal":"{"}, "bstring$ebnf$1", {"literal":"}"}], "postprocess": (d) => d[1].join('')},
|
|
@@ -331,7 +406,6 @@ var grammar = {
|
|
|
331
406
|
{"name": "continuation", "symbols": ["continuation$string$1"]},
|
|
332
407
|
{"name": "file", "symbols": [/[a-h]/]},
|
|
333
408
|
{"name": "piece", "symbols": [/[KQBNR]/]},
|
|
334
|
-
{"name": "promotion", "symbols": [{"literal":"="}, /[QBNR]/], "postprocess": (d) => d[1]},
|
|
335
409
|
{"name": "rank", "symbols": [/[1-8]/]},
|
|
336
410
|
{"name": "result$string$1", "symbols": [{"literal":"1"}, {"literal":"-"}, {"literal":"0"}], "postprocess": function joiner(d) {return d.join('');}},
|
|
337
411
|
{"name": "result", "symbols": ["result$string$1"], "postprocess": () => 1},
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
type File = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h';
|
|
2
|
+
type Piece = 'B' | 'K' | 'N' | 'P' | 'Q' | 'R';
|
|
3
|
+
type Rank = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8';
|
|
4
|
+
type Result = '1-0' | '0-1' | '1/2-1/2' | '?';
|
|
5
|
+
type Square = `${File}${Rank}`;
|
|
6
|
+
type HalfMove = [number, undefined, Move];
|
|
7
|
+
type VariantMove = Move | HalfMove;
|
|
8
|
+
type VariantMoves = VariantMove[];
|
|
9
|
+
type Move = {
|
|
10
|
+
annotations?: string[];
|
|
11
|
+
capture?: boolean;
|
|
12
|
+
castling?: boolean;
|
|
13
|
+
check?: boolean;
|
|
14
|
+
checkmate?: boolean;
|
|
15
|
+
comment?: string;
|
|
16
|
+
from?: File | Rank;
|
|
17
|
+
piece: Piece;
|
|
18
|
+
promotion?: Piece;
|
|
19
|
+
to: Square;
|
|
20
|
+
variants?: VariantMoves[];
|
|
21
|
+
};
|
|
22
|
+
type Meta = {
|
|
23
|
+
Result: Result;
|
|
24
|
+
[key: string]: string;
|
|
25
|
+
};
|
|
26
|
+
type Moves = [number, Move] | [number, Move, Move];
|
|
27
|
+
type PGN = {
|
|
28
|
+
meta: Meta;
|
|
29
|
+
moves: Moves;
|
|
30
|
+
result: Result;
|
|
31
|
+
};
|
|
32
|
+
export default function parse(input: string): PGN[];
|
|
33
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Grammar, Parser } from 'nearley';
|
|
2
|
+
import grammar from './grammar';
|
|
3
|
+
function tokenize(input) {
|
|
4
|
+
const parser = new Parser(Grammar.fromCompiled(grammar));
|
|
5
|
+
parser.feed(input);
|
|
6
|
+
if (parser.results.length > 1) {
|
|
7
|
+
throw new Error(`@echecs/parser: Ambiguous syntax. Found ${parser.results.length} results`);
|
|
8
|
+
}
|
|
9
|
+
return parser.results[0];
|
|
10
|
+
}
|
|
11
|
+
export default function parse(input) {
|
|
12
|
+
const games = input.replace(/[\r\uFEFF]/g, '');
|
|
13
|
+
return tokenize(games);
|
|
14
|
+
}
|