From a5c2c687dffd7ebb044ac46be5c2317f88c8fd1c Mon Sep 17 00:00:00 2001
From: Datawater <86855332+datawater@users.noreply.github.com>
Date: Tue, 18 Jun 2024 23:34:41 +0400
Subject: [PATCH] Revorked the parsing code Made it that we first lex the pgn
file before trying to immediatly create an AST.
---
Cargo.lock | 7 --
Cargo.toml | 2 +-
NOTICE.html | 29 +-----
data/with_varation_and_comments.pgn | 14 +++
log.log | 1 +
src/eval_args.rs | 2 +-
src/main.rs | 1 -
src/pgn/define_structs.rs | 93 -------------------
src/pgn/mod.rs | 137 +++++++++++++++++++---------
src/pgn/tokens.rs | 33 +++++++
src/tree.rs | 58 ------------
test/pgn/mod.rs | 2 +-
12 files changed, 146 insertions(+), 233 deletions(-)
create mode 100644 data/with_varation_and_comments.pgn
create mode 100644 log.log
delete mode 100644 src/pgn/define_structs.rs
create mode 100644 src/pgn/tokens.rs
delete mode 100644 src/tree.rs
diff --git a/Cargo.lock b/Cargo.lock
index 071374d..ba1caa2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -119,7 +119,6 @@ version = "0.0.0"
dependencies = [
"clap-dynamic",
"clap_complete",
- "micromap",
"smartstring",
]
@@ -141,12 +140,6 @@ version = "1.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
-[[package]]
-name = "micromap"
-version = "0.0.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c5b72ada413a5bd6bc65d6eef149fdc5138298f3bb89653d1a521f0fea7f9c73"
-
[[package]]
name = "proc-macro2"
version = "1.0.85"
diff --git a/Cargo.toml b/Cargo.toml
index e1ef8f8..9950b1f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,7 +8,7 @@ license = "GPL-3.0"
# clap = { version = "4.5.7", features = ["derive"] }
clap = { version = "0.1.0", path = "clap-dynamic", package = "clap-dynamic" }
clap_complete = "4.5.5"
-micromap = "0.0.15"
+# micromap = "0.0.15"
smartstring = { version = "1.0.1", default-features = false }
[profile.release]
diff --git a/NOTICE.html b/NOTICE.html
index b2479b2..7f5d8c0 100644
--- a/NOTICE.html
+++ b/NOTICE.html
@@ -45,8 +45,8 @@
Third Party Licenses
Overview of licenses:
- Apache License 2.0 (31)
- - MIT License (2)
- GNU General Public License v3.0 only (1)
+ - MIT License (1)
- Mozilla Public License 2.0 (1)
- Unicode License Agreement - Data Files and Software (2016) (1)
- The Unlicense (1)
@@ -1756,33 +1756,6 @@ Used by:
You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <https://www.gnu.org/philosophy/why-not-lgpl.html>.
-
-
- -
-
MIT License
- Used by:
-
- Copyright (c) 2023 Yegor Bugayenko
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
diff --git a/data/with_varation_and_comments.pgn b/data/with_varation_and_comments.pgn
new file mode 100644
index 0000000..55a0b30
--- /dev/null
+++ b/data/with_varation_and_comments.pgn
@@ -0,0 +1,14 @@
+[Event "prep for tournament: Grunfeld as black"]
+[Site "https://lichess.org/study/Hf31t9sp/GZVgLZYn"]
+[Result "*"]
+[Variant "Standard"]
+[ECO "D86"]
+[Opening "Grünfeld Defense: Exchange Variation, Classical Variation"]
+[Annotator "https://lichess.org/@/peterisacutekitten"]
+[UTCDate "2022.09.12"]
+[UTCTime "08:36:57"]
+
+1. d4 { [%cal Gg8f6] } 1... Nf6 2. c4 g6 3. Nc3 d5 4. cxd5 (4. Nf3 Bg7 { [%cal Gc1g5] } 5. Qb3 (5. cxd5 Nxd5 6. e4 Nxc3 7. bxc3) (5. Bg5 { [%cal Gf6e4] } 5... Ne4 6. cxd5 (6. Nxe4 dxe4 7. Nd2 Qxd4) 6... Nxg5 7. Nxg5 e6 8. Qd2 exd5 9. Qe3+ Kf8 10. Qf4 { [%csl Gg4] } 10... Bf6 11. h4 h6 12. Nf3 Kg7 13. O-O-O Be6 14. e3 Nd7 15. g4 c6 16. g5 (16. h5 g5) (16. Bd3 Qb8 (16... b5) (16... a5 17. g5 hxg5 18. hxg5 Be7) 17. Qxb8 Raxb8) 16... hxg5 17. hxg5) 5... dxc4 6. Qxc4 O-O { [%cal Gd4d5] } 7. e4 Nc6 (7... a6 8. Be2 b5 9. Qb3 c5 10. dxc5 Be6 11. Qc2 Nbd7 12. Be3 Rc8 13. b4 Nxe4 14. Nxe4 (14. Bd2 Ndxc5 15. bxc5 Nxc3 16. Bxc3 Rxc5) 14... Bxa1) 8. Be2 Bg4 9. d5 Bxf3 10. Bxf3 Ne5 11. Qe2) 4... Nxd5 5. e4 Nxc3 6. bxc3 Bg7 { There are a few main lines after this move, Bc4, Nf3 and Be3. First
+ We'll cover Bc4 } { [%cal Gf1c4] } 7. Bc4 (7. Nf3 c5 8. Be3 (8. Rb1 O-O 9. Be2 (9. Bd2) 9... cxd4 10. cxd4 Qa5+ 11. Bd2 Qxa2 12. O-O Bg4 { [%cal Gb1b7] } 13. Rxb7 { Aronian, L. - Svidler, P., 1/2-1/2, 2nd Norway Chess 2014, https://lichess.org/MEvCmKtn } 13... Bxf3 14. Bxf3 Bxd4 15. Bb4 Rd8 16. Qc1 Na6 17. Bxe7 Rac8 18. Qf4 Nc5 19. Bxd8 Nxb7 20. Bf6 Bxf6 21. Qxf6 Nc5) 8... Qa5 { [%cal Gd1d2] } (8... Nc6) (8... O-O 9. Qd2 Qa5 10. Rc1 Rd8 11. d5 e6 12. Bg5 f6 13. Be3 Nc6) 9. Qd2 Nc6 { [%csl Gb1,Gb7][%cal Gb1b7] } 10. Rb1 a6 { [%cal Gb1c1] } 11. Rc1 cxd4 12. cxd4 Qxd2+ 13. Kxd2 (13. Bxd2) 13... e6 { Again, The engine thinks that this position is a complete
+ draw } (13... f5 14. d5 (14. e5 Be6 15. Bc4 Bxc4 16. Rxc4 O-O 17. Ke2 Rad8 18. Rb1 Rd7 19. g3 e6 20. Ng5 Re8 21. h4 Na5 22. Ra4 Nc6) 14... Nb4 15. Bc5 (15. Bc4 fxe4 16. Ng5 b5 17. Bb3 h6 18. Nxe4 Bf5 19. Ng3 Nxd5 20. Nxf5 gxf5 21. Bxd5 Rd8 22. Rc5 e6 23. Ke2 exd5)) 14. Bd3 O-O 15. h4 h6 16. Rc5 Bd7 17. Rb1 b5 18. e5 Rfc8 19. Be4 Bf8 20. Rcc1 Rab8) (7. Be3 c5 { [%csl Ge2][%cal Gf1e2,Gd1d2] } 8. Qd2 Qa5 9. Rc1 cxd4 10. cxd4 Qxd2+ 11. Bxd2 O-O 12. Nf3 Bg4 { [%cal Gh2h3] } 13. d5 (13. Be3 Nc6 14. d5 Bxf3 15. gxf3 Nd4 16. Bh3 f5 17. exf5 Nxf5) 13... Nd7 { Again, this is a total draw } 14. Rc7 { [%csl Gc6][%cal Gc7b7,Gd7c6] } 14... Rfc8 { [%csl Gb7,Gc5][%cal Gc7b7,Gd7c5] } 15. Rxb7 (15. Rxc8+ Rxc8 16. Be3 Rc2) 15... Nc5 { [%cal Gb7e7] } 16. Rxe7 (16. Rb1 Nxe4) (16. Rb4 a5 17. Rc4 Rab8 18. Be3 Nd3+ 19. Bxd3 Rxc4 20. Bxc4 Rb1+ 21. Ke2 Rxh1) 16... Bf6 { If they try to come into the 7th rank, you win
+ an exchange } 17. Ne5 Bxe7 18. Nxg4) (7. Bg5 c5 { [%cal Ga1c1] } 8. Rc1 O-O 9. Nf3 Bg4 { [%csl Gd5][%cal Gd4d5] } 10. d5 (10. Be2 cxd4 11. cxd4) 10... Qd6 11. Be2 Nd7 12. O-O (12. c4 Bxf3 (12... f5 13. exf5 Bxf5 14. Qd2 Nf6 15. Bf4 Qb6 16. O-O e6 17. Be5 exd5 18. cxd5) 13. Bxf3 b5 14. cxb5 a6 { [%csl Ga6][%cal Gb5a6] } 15. bxa6 { [%csl Ga6][%cal Gd6a6] } 15... Rxa6 { [%csl Ga8][%cal Gc1c2,Gf8a8] } 16. Rc2 Rfa8 { [%csl Ga1][%cal Ga8a1] } 17. Qe2 Bf6 { [%cal Gg5c1] } 18. Bxf6 { [%cal Gd6g6] } 18... Qxf6 { [%cal Ge1g1] } 19. O-O Ne5 20. Rfc1 c4 { [%csl Gc4][%cal Gh2h3,Ge5f3,Ge2f3,Ga6a2,Gc2c4] } 21. h3 { [%csl Ga6] } 21... Ra3) 12... Bxf3 13. Bxf3 b5 14. Qd2 c4 15. Qe3 a5 (15... Rfe8 16. Rfd1 Nc5) 16. Be2 Rfc8 17. Rfd1 Nc5 { Arun Prasad, Subramanian - Gupta, Abhijeet, 1/2-1/2, Kolkata op 5th, 2012, https://lichess.org/ytOnUHOq } 18. h3 Na4 19. Bf4 Qc5 20. Qxc5 Nxc5 21. e5 e6 22. g3 Rab8 23. h4 Bf8 24. Be3 exd5 25. Rxd5 Ne6) 7... c5 8. Ne2 Nc6 (8... O-O) 9. Be3 O-O 10. O-O Qc7 { [%cal Ge3f4] } (10... Bg4 11. f3 Bd7 { [%csl Gd8] } (11... Na5 12. Bxf7+ Rxf7 13. fxg4 Rxf1+ 14. Kxf1 { [%csl Gd6][%cal Gd8d6] } (14. Qxf1 Nc4 { [%csl Ge3][%cal Gc4e3] } 15. Qc1 { [%csl Gd5] } 15... cxd4 16. cxd4 Rc8 17. Bg5 (17. Qc3 Qd7 18. Rc1 (18. h3 { [%csl Gd7] } 18... Qe6 19. Qd3 Nxe3 20. Qxe3 Rc2) 18... Qd6)) 14... cxd4 15. cxd4 e5 16. Kg1 Rc8 17. d5 Nc4 18. Qb3 Nxe3 19. Qxe3 Rc2 (19... Qb6 20. Qc5) 20. a3 (20. h3 Qb6 21. Qxb6 axb6 22. Kf2 Bf8 23. Ke3 Bh6+ 24. Kf3 (24. Kf2 Bf8 25. Ke3 Bh6+ 26. Kf2 Bf8 27. Ke3 Bh6+ 28. Kf3 b5 29. h4 b4 30. g5 Bf8 31. Ke3 b5 32. Kd3 Rb2 33. Ke3 Bc5+ 34. Kd3) (24. Kd3 Rd2+) 24... Bf8 25. a4 (25. a3 Rd2 (25... Rb2)) 25... Rd2) (20. h4)) 12. Rb1 { [%cal Gb1b8] } 12... cxd4 (12... Qc7 13. Qd2 Rad8 14. Rfc1 Bc8 15. Qb2 Na5 { [%cal Gc4b3] } (15... e5) 16. Bd3 (16. Bb3) 16... e5 17. d5 c4 18. Bc2 b6 19. Rd1 Nb7 20. Ng3 Bd7 21. a4 Rfe8 22. Nf1 Bf8 23. Kh1 Rc8) 13. cxd4 a6 14. Rxb7 (14. Qd2 b5 15. Bd3 (15. Bb3 Qa5 16. Qd3 Nb4 17. Bd2 Nxd3 18. Bxa5 Bh6) 15... Qa5 16. Qxa5 Nxa5 17. Rfc1 Rfc8) (14. d5 Ne5 15. Bb3 Rc8) (14. f4 Na5 15. Bd3 e6 16. e5 (16. d5 exd5 17. exd5 b5) 16... Rc8) (14. a4 Na5 15. Bd3 Rc8) 14... Na5 15. Rb4 Nxc4 16. Rxc4 Bb5 17. Rb4 Qa5 18. Rb2 { [%csl Gf2][%cal Gb5e2] } 18... Rac8 $140 { The plan of Rfd8, maybe exchanging on e2, pushing e6. }) (10... cxd4 11. cxd4 Bg4 12. f3 Na5 { [%csl Gb3,Gd5][%cal Gc4b3,Gf5d5] } 13. Bxf7+ Rxf7 14. fxg4 Rxf1+ 15. Kxf1 { [%csl Ga5] } 15... Nc4 16. Qb3 Rc8) 11. Rc1 (11. Bf4 e5 12. dxe5 Nxe5 13. Rb1 Rb8) 11... Rd8 12. Bf4 Qd7 13. d5 Na5 14. Bd3 b5 15. Rb1 a6 16. Qc1 e6 17. Qa3 c4 18. Bc2 (18. Qxa5 cxd3 19. Nd4 Bb7) 18... Nb7 19. dxe6 Qxe6 20. Nd4 Qg4 (20... Qb6 { Dosi, Alberto - Nimtz, Dr. Manfred, 1/2-1/2, MT-Lannaioli (ITA), 2007, https://lichess.org/383JGVYV }) *
diff --git a/log.log b/log.log
new file mode 100644
index 0000000..1b75dd5
--- /dev/null
+++ b/log.log
@@ -0,0 +1 @@
+Ok([Header("Event", "Fischer - Spassky"), Header("Site", "Sveti Stefan / Belgrade YUG"), Header("Date", "1992.09.02"), Header("EventDate", "1992.09.02"), Header("Round", "1"), Header("Result", "1-0"), Header("White", "Robert James Fischer"), Header("Black", "Boris Spassky"), Header("ECO", "C95"), Header("WhiteElo", "?"), Header("BlackElo", "?"), Header("PlyCount", "99"), HalfMoveNumber(1), PgnMove("e4"), HalfMoveNumber(2), PgnMove("e5"), HalfMoveNumber(3), PgnMove("Nf3"), HalfMoveNumber(4), PgnMove("Nc6"), HalfMoveNumber(5), PgnMove("Bb5"), HalfMoveNumber(6), PgnMove("a6"), HalfMoveNumber(7), PgnMove("Ba4"), HalfMoveNumber(8), PgnMove("Nf6"), HalfMoveNumber(9), PgnMove("O-O"), HalfMoveNumber(10), PgnMove("Be7"), HalfMoveNumber(11), PgnMove("Re1"), HalfMoveNumber(12), PgnMove("b5"), HalfMoveNumber(13), PgnMove("Bb3"), HalfMoveNumber(14), PgnMove("O-O"), HalfMoveNumber(15), PgnMove("c3"), HalfMoveNumber(16), PgnMove("d6"), HalfMoveNumber(17), PgnMove("h3"), HalfMoveNumber(18), PgnMove("Nb8"), HalfMoveNumber(19), PgnMove("d4"), HalfMoveNumber(20), PgnMove("Nbd7"), HalfMoveNumber(21), PgnMove("Nbd2"), HalfMoveNumber(22), PgnMove("Bb7"), HalfMoveNumber(23), PgnMove("Bc2"), HalfMoveNumber(24), PgnMove("Re8"), HalfMoveNumber(25), PgnMove("Nf1"), HalfMoveNumber(26), PgnMove("Bf8"), HalfMoveNumber(27), PgnMove("Ng3"), HalfMoveNumber(28), PgnMove("g6"), HalfMoveNumber(29), PgnMove("Bg5"), HalfMoveNumber(30), PgnMove("h6"), HalfMoveNumber(31), PgnMove("Bd2"), HalfMoveNumber(32), PgnMove("Bg7"), HalfMoveNumber(33), PgnMove("a4"), HalfMoveNumber(34), PgnMove("c5"), HalfMoveNumber(35), PgnMove("d5"), HalfMoveNumber(36), PgnMove("c4"), HalfMoveNumber(37), PgnMove("b4"), HalfMoveNumber(38), PgnMove("Nh7"), HalfMoveNumber(39), PgnMove("Be3"), HalfMoveNumber(40), PgnMove("h5"), HalfMoveNumber(41), PgnMove("Qd2"), HalfMoveNumber(42), PgnMove("Rf8"), HalfMoveNumber(43), PgnMove("Ra3"), HalfMoveNumber(44), PgnMove("Ndf6"), HalfMoveNumber(45), PgnMove("Rea1"), HalfMoveNumber(46), PgnMove("Qd7"), HalfMoveNumber(47), PgnMove("R1a2"), HalfMoveNumber(48), PgnMove("Rfc8"), HalfMoveNumber(49), PgnMove("Qc1"), HalfMoveNumber(50), PgnMove("Bf8"), HalfMoveNumber(51), PgnMove("Qa1"), HalfMoveNumber(52), PgnMove("Qe8"), HalfMoveNumber(53), PgnMove("Nf1"), HalfMoveNumber(54), PgnMove("Be7"), HalfMoveNumber(55), PgnMove("N1d2"), HalfMoveNumber(56), PgnMove("Kg7"), HalfMoveNumber(57), PgnMove("Nb1"), HalfMoveNumber(58), PgnMove("Nxe4"), HalfMoveNumber(59), PgnMove("Bxe4"), HalfMoveNumber(60), PgnMove("f5"), HalfMoveNumber(61), PgnMove("Bc2"), HalfMoveNumber(62), PgnMove("Bxd5"), HalfMoveNumber(63), PgnMove("axb5"), HalfMoveNumber(64), PgnMove("axb5"), HalfMoveNumber(65), PgnMove("Ra7"), HalfMoveNumber(66), PgnMove("Kf6"), HalfMoveNumber(67), PgnMove("Nbd2"), HalfMoveNumber(68), PgnMove("Rxa7"), HalfMoveNumber(69), PgnMove("Rxa7"), HalfMoveNumber(70), PgnMove("Ra8"), HalfMoveNumber(71), PgnMove("g4"), HalfMoveNumber(72), PgnMove("hxg4"), HalfMoveNumber(73), PgnMove("hxg4"), HalfMoveNumber(74), PgnMove("Rxa7"), HalfMoveNumber(75), PgnMove("Qxa7"), HalfMoveNumber(76), PgnMove("f4"), HalfMoveNumber(77), PgnMove("Bxf4"), HalfMoveNumber(78), PgnMove("exf4"), HalfMoveNumber(79), PgnMove("Nh4"), HalfMoveNumber(80), PgnMove("Bf7"), HalfMoveNumber(81), PgnMove("Qd4+"), HalfMoveNumber(82), PgnMove("Ke6"), HalfMoveNumber(83), PgnMove("Nf5"), HalfMoveNumber(84), PgnMove("Bf8"), HalfMoveNumber(85), PgnMove("Qxf4"), HalfMoveNumber(86), PgnMove("Kd7"), HalfMoveNumber(87), PgnMove("Nd4"), HalfMoveNumber(88), PgnMove("Qe1+"), HalfMoveNumber(89), PgnMove("Kg2"), HalfMoveNumber(90), PgnMove("Bd5+"), HalfMoveNumber(91), PgnMove("Be4"), HalfMoveNumber(92), Result(WhiteWon), PgnMove("Bxe4+"), HalfMoveNumber(93), PgnMove("Nxe4"), HalfMoveNumber(94), PgnMove("Be7"), HalfMoveNumber(95), PgnMove("Nxb5"), HalfMoveNumber(96), PgnMove("Nf8"), HalfMoveNumber(97), PgnMove("Nbxd6"), HalfMoveNumber(98), PgnMove("Ne6"), HalfMoveNumber(99), PgnMove("Qe5"), HalfMoveNumber(100)])
diff --git a/src/eval_args.rs b/src/eval_args.rs
index c7ec9ac..2218f8a 100644
--- a/src/eval_args.rs
+++ b/src/eval_args.rs
@@ -10,7 +10,7 @@ pub fn eval_args(cli: &Cli) {
crate::CommandE::Pgn2cmbr(args) => {
let pgn = pgn::parse_pgn(&args.input);
- println!("{:#?}", pgn);
+ println!("{:?}", pgn);
}
crate::CommandE::License => {
diff --git a/src/main.rs b/src/main.rs
index cd34bcc..f3cf4ce 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,7 +4,6 @@
mod eval_args;
mod pgn;
mod tests;
-mod tree;
mod utils;
use clap::{Args, Command, CommandFactory, Parser, Subcommand};
diff --git a/src/pgn/define_structs.rs b/src/pgn/define_structs.rs
deleted file mode 100644
index 1540284..0000000
--- a/src/pgn/define_structs.rs
+++ /dev/null
@@ -1,93 +0,0 @@
-#[rustfmt::skip]
-pub use smartstring::alias::String;
-use crate::tree::Tree;
-use micromap::Map;
-
-#[derive(Debug, PartialEq, Eq, Default, Clone)]
-pub struct PgnGame {
- headers: PgnHeaders,
- comments: Vec,
- main_variation: PgnVariation,
- result: PgnResult,
-}
-
-pub type PgnHeaders = Map;
-
-// Move string, half move count (odd = white, even = black)
-#[derive(Debug, PartialEq, Eq, Default, Clone)]
-pub struct PgnMove {
- pub value: String,
- pub half_move_location: u16,
-}
-
-pub type PgnVariation = Tree;
-
-#[derive(Debug, PartialEq, Eq, Default, Clone)]
-#[repr(C)]
-pub enum PgnResult {
- #[default]
- Undefined,
- WhiteWon,
- BlackWon,
- Draw,
-}
-
-#[derive(Debug, PartialEq, Eq, Default, Clone)]
-pub struct PgnComment {
- pub comment: String,
- pub half_move_location: u16,
-}
-
-#[macro_export]
-macro_rules! pgn_move_to_half_move {
- ($arg:expr) => {
- (2 * $arg - 1)
- };
-}
-
-impl PgnGame {
- #[inline(always)]
- pub fn new() -> Self {
- return Self::default();
- }
-
- #[inline(always)]
- pub fn get_headers(&self) -> &PgnHeaders {
- return &self.headers;
- }
-
- #[inline(always)]
- pub fn get_headers_mut(&mut self) -> &mut PgnHeaders {
- return &mut self.headers;
- }
-
- #[inline(always)]
- pub fn get_result(&self) -> &PgnResult {
- return &self.result;
- }
-
- #[inline(always)]
- pub fn get_result_mut(&mut self) -> &mut PgnResult {
- return &mut self.result;
- }
-
- #[inline(always)]
- pub fn get_comments(&self) -> &Vec {
- return &self.comments;
- }
-
- #[inline(always)]
- pub fn get_comments_mut(&mut self) -> &mut Vec {
- return &mut self.comments;
- }
-
- #[inline(always)]
- pub fn get_main_variation(&self) -> &PgnVariation {
- return &self.main_variation;
- }
-
- #[inline(always)]
- pub fn get_main_variation_mut(&mut self) -> &mut PgnVariation {
- return &mut self.main_variation;
- }
-}
diff --git a/src/pgn/mod.rs b/src/pgn/mod.rs
index cdc8f09..2ee9776 100644
--- a/src/pgn/mod.rs
+++ b/src/pgn/mod.rs
@@ -1,23 +1,25 @@
-pub mod define_structs;
pub mod errors;
pub mod headers;
+pub mod tokens;
-use std::error::Error;
-
-pub use define_structs::*;
+use crate::{pgn_move_to_half_move, utils};
use errors::{Location, PgnError};
pub use headers::*;
+use tokens::*;
-use crate::{pgn_move_to_half_move, utils};
+use std::error::Error;
// NOTE: After profiling I've found that this function only uses 0.5% of the total samples.
-// it does NOT cause significant overhead therefore isn't worth optimizing
+// it does NOT cause significant overhead therefore isn't worth optimizing.
+// NOTE(#2): With the current parsing, it takes 150-200ms to parse a 6.4MB file, so
+// 31-42 MB/s of parisng speed.
fn parse_half_move_count<'a>(
bytes: &'a [u8],
line_char_index: &'a mut usize,
line_len: usize,
input_filename: &'a str,
line_char_index_start: u32,
+ line_i: u32,
) -> Result> {
let mut num_buffer = String::new();
@@ -36,7 +38,7 @@ fn parse_half_move_count<'a>(
message: format!("Couldn't parse number: {num_buffer}"),
location: Location {
file: input_filename,
- line: line_len as u32,
+ line: line_i as u32,
col: line_char_index_start,
},
}));
@@ -44,7 +46,7 @@ fn parse_half_move_count<'a>(
let mut half_move_count = pgn_move_to_half_move!(parsed_num.unwrap());
- if *line_char_index + 1 < line_len && bytes[*line_char_index] == b'.' {
+ if *line_char_index + 1 < line_len && bytes[(*line_char_index) + 1] == b'.' {
half_move_count += 1;
*line_char_index += 2;
}
@@ -52,19 +54,17 @@ fn parse_half_move_count<'a>(
Ok(half_move_count)
}
-pub fn parse_pgn(input_filename: &str) -> Result, Box> {
- // TODO(#7): Add variations support
-
+pub fn parse_pgn(input_filename: &str) -> Result, Box> {
let lines = utils::read_lines(input_filename)?;
- let mut vec_games: Vec = Vec::with_capacity(1024);
- let mut game_index = 0;
- let mut half_move_count: u16 = 0;
- vec_games.insert(0, PgnGame::default());
+ let mut tokens_vec: Vec = Vec::with_capacity(1024);
+ let mut in_comment = false;
+ let mut comment_string = String::new();
+ let mut half_move_number = 0;
+ let mut last_was_move_not_number = false;
for (i, line_) in lines.flatten().enumerate() {
let line = line_.trim();
- let mut defer = false;
let mut line_len = line.len();
let bytes = line.as_bytes();
@@ -78,20 +78,18 @@ pub fn parse_pgn(input_filename: &str) -> Result, Box Result, Box Result, Box {
+ tokens_vec.remove(tokens_vec.len() - 1);
+ }
+
+ _ => {}
+ }
+
+ half_move_number = result.unwrap();
+ tokens_vec.push(PgnToken::HalfMoveNumber(half_move_number));
} else if char.is_ascii_alphabetic() {
let mut buffer = String::new();
@@ -147,33 +178,53 @@ pub fn parse_pgn(input_filename: &str) -> Result, Box {
+ (2 * $arg - 1)
+ };
+}
diff --git a/src/tree.rs b/src/tree.rs
deleted file mode 100644
index a16b9fb..0000000
--- a/src/tree.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-#[derive(Debug, PartialEq, Eq, Default, Clone)]
-pub struct Tree {
- // NOTE: Using a whole ass vec here feels a bit icky
- // TODO(#5): (MAYBE) Replace this with a smaller vec, or make the user suply a vec-like type
- children: Vec>>,
- value: T,
-}
-
-impl Tree
-where
- T: Default,
-{
- #[inline(always)]
- pub fn new() -> Self {
- return Tree {
- children: Vec::new(),
- value: T::default(),
- };
- }
-
- #[inline(always)]
- pub fn new_with_value(v: T) -> Self {
- return Tree {
- children: Vec::new(),
- value: v,
- };
- }
-
- #[inline(always)]
- pub fn insert(&mut self, v: T) {
- self.children.push(Box::new(Self::new_with_value(v)));
- }
-
- #[inline(always)]
- pub fn get_value(&self) -> &T {
- return &self.value;
- }
-
- #[inline(always)]
- pub fn get_value_mut(&mut self) -> &mut T {
- return &mut self.value;
- }
-
- #[inline(always)]
- pub fn is_leaf(&self) -> bool {
- return self.children.len() == 0;
- }
-
- #[inline(always)]
- pub fn get_children(&self) -> &Vec>> {
- return &self.children;
- }
-
- #[inline(always)]
- pub fn get_children_mut(&mut self) -> &mut Vec>> {
- return &mut self.children;
- }
-}
diff --git a/test/pgn/mod.rs b/test/pgn/mod.rs
index c03d222..c7ba25f 100644
--- a/test/pgn/mod.rs
+++ b/test/pgn/mod.rs
@@ -48,7 +48,7 @@ mod pgn_tests {
#[test]
fn test_pgn_parsing_no_variations() {
- let expected_output = "Ok([PgnGame { headers: {\"Event\": \"Fischer - Spassky\", \"Site\": \"Sveti Stefan / Belgrade YUG\", \"Date\": \"1992.09.02\", \"EventDate\": \"1992.09.02\", \"Round\": \"1\", \"Result\": \"1-0\", \"White\": \"Robert James Fischer\", \"Black\": \"Boris Spassky\", \"ECO\": \"C95\", \"WhiteElo\": \"?\", \"BlackElo\": \"?\", \"PlyCount\": \"99\"}, comments: [], main_variation: Tree { children: [Tree { children: [], value: PgnMove { value: \"e4\", half_move_location: 1 } }, Tree { children: [], value: PgnMove { value: \"e5\", half_move_location: 2 } }, Tree { children: [], value: PgnMove { value: \"Nf3\", half_move_location: 3 } }, Tree { children: [], value: PgnMove { value: \"Nc6\", half_move_location: 4 } }, Tree { children: [], value: PgnMove { value: \"Bb5\", half_move_location: 5 } }, Tree { children: [], value: PgnMove { value: \"a6\", half_move_location: 6 } }, Tree { children: [], value: PgnMove { value: \"Ba4\", half_move_location: 7 } }, Tree { children: [], value: PgnMove { value: \"Nf6\", half_move_location: 8 } }, Tree { children: [], value: PgnMove { value: \"O-O\", half_move_location: 9 } }, Tree { children: [], value: PgnMove { value: \"Be7\", half_move_location: 10 } }, Tree { children: [], value: PgnMove { value: \"Re1\", half_move_location: 11 } }, Tree { children: [], value: PgnMove { value: \"b5\", half_move_location: 12 } }, Tree { children: [], value: PgnMove { value: \"Bb3\", half_move_location: 13 } }, Tree { children: [], value: PgnMove { value: \"O-O\", half_move_location: 14 } }, Tree { children: [], value: PgnMove { value: \"c3\", half_move_location: 15 } }, Tree { children: [], value: PgnMove { value: \"d6\", half_move_location: 16 } }, Tree { children: [], value: PgnMove { value: \"h3\", half_move_location: 17 } }, Tree { children: [], value: PgnMove { value: \"Nb8\", half_move_location: 18 } }, Tree { children: [], value: PgnMove { value: \"d4\", half_move_location: 19 } }, Tree { children: [], value: PgnMove { value: \"Nbd7\", half_move_location: 20 } }, Tree { children: [], value: PgnMove { value: \"Nbd2\", half_move_location: 21 } }, Tree { children: [], value: PgnMove { value: \"Bb7\", half_move_location: 22 } }, Tree { children: [], value: PgnMove { value: \"Bc2\", half_move_location: 23 } }, Tree { children: [], value: PgnMove { value: \"Re8\", half_move_location: 24 } }, Tree { children: [], value: PgnMove { value: \"Nf1\", half_move_location: 25 } }, Tree { children: [], value: PgnMove { value: \"Bf8\", half_move_location: 26 } }, Tree { children: [], value: PgnMove { value: \"Ng3\", half_move_location: 27 } }, Tree { children: [], value: PgnMove { value: \"g6\", half_move_location: 28 } }, Tree { children: [], value: PgnMove { value: \"Bg5\", half_move_location: 29 } }, Tree { children: [], value: PgnMove { value: \"h6\", half_move_location: 30 } }, Tree { children: [], value: PgnMove { value: \"Bd2\", half_move_location: 31 } }, Tree { children: [], value: PgnMove { value: \"Bg7\", half_move_location: 32 } }, Tree { children: [], value: PgnMove { value: \"a4\", half_move_location: 33 } }, Tree { children: [], value: PgnMove { value: \"c5\", half_move_location: 34 } }, Tree { children: [], value: PgnMove { value: \"d5\", half_move_location: 35 } }, Tree { children: [], value: PgnMove { value: \"c4\", half_move_location: 36 } }, Tree { children: [], value: PgnMove { value: \"b4\", half_move_location: 37 } }, Tree { children: [], value: PgnMove { value: \"Nh7\", half_move_location: 38 } }, Tree { children: [], value: PgnMove { value: \"Be3\", half_move_location: 39 } }, Tree { children: [], value: PgnMove { value: \"h5\", half_move_location: 40 } }, Tree { children: [], value: PgnMove { value: \"Qd2\", half_move_location: 41 } }, Tree { children: [], value: PgnMove { value: \"Rf8\", half_move_location: 42 } }, Tree { children: [], value: PgnMove { value: \"Ra3\", half_move_location: 43 } }, Tree { children: [], value: PgnMove { value: \"Ndf6\", half_move_location: 44 } }, Tree { children: [], value: PgnMove { value: \"Rea1\", half_move_location: 45 } }, Tree { children: [], value: PgnMove { value: \"Qd7\", half_move_location: 46 } }, Tree { children: [], value: PgnMove { value: \"R1a2\", half_move_location: 47 } }, Tree { children: [], value: PgnMove { value: \"Rfc8\", half_move_location: 48 } }, Tree { children: [], value: PgnMove { value: \"Qc1\", half_move_location: 49 } }, Tree { children: [], value: PgnMove { value: \"Bf8\", half_move_location: 50 } }, Tree { children: [], value: PgnMove { value: \"Qa1\", half_move_location: 51 } }, Tree { children: [], value: PgnMove { value: \"Qe8\", half_move_location: 52 } }, Tree { children: [], value: PgnMove { value: \"Nf1\", half_move_location: 53 } }, Tree { children: [], value: PgnMove { value: \"Be7\", half_move_location: 54 } }, Tree { children: [], value: PgnMove { value: \"N1d2\", half_move_location: 55 } }, Tree { children: [], value: PgnMove { value: \"Kg7\", half_move_location: 56 } }, Tree { children: [], value: PgnMove { value: \"Nb1\", half_move_location: 57 } }, Tree { children: [], value: PgnMove { value: \"Nxe4\", half_move_location: 58 } }, Tree { children: [], value: PgnMove { value: \"Bxe4\", half_move_location: 59 } }, Tree { children: [], value: PgnMove { value: \"f5\", half_move_location: 60 } }, Tree { children: [], value: PgnMove { value: \"Bc2\", half_move_location: 61 } }, Tree { children: [], value: PgnMove { value: \"Bxd5\", half_move_location: 62 } }, Tree { children: [], value: PgnMove { value: \"axb5\", half_move_location: 63 } }, Tree { children: [], value: PgnMove { value: \"axb5\", half_move_location: 64 } }, Tree { children: [], value: PgnMove { value: \"Ra7\", half_move_location: 65 } }, Tree { children: [], value: PgnMove { value: \"Kf6\", half_move_location: 66 } }, Tree { children: [], value: PgnMove { value: \"Nbd2\", half_move_location: 67 } }, Tree { children: [], value: PgnMove { value: \"Rxa7\", half_move_location: 68 } }, Tree { children: [], value: PgnMove { value: \"Rxa7\", half_move_location: 69 } }, Tree { children: [], value: PgnMove { value: \"Ra8\", half_move_location: 70 } }, Tree { children: [], value: PgnMove { value: \"g4\", half_move_location: 71 } }, Tree { children: [], value: PgnMove { value: \"hxg4\", half_move_location: 72 } }, Tree { children: [], value: PgnMove { value: \"hxg4\", half_move_location: 73 } }, Tree { children: [], value: PgnMove { value: \"Rxa7\", half_move_location: 74 } }, Tree { children: [], value: PgnMove { value: \"Qxa7\", half_move_location: 75 } }, Tree { children: [], value: PgnMove { value: \"f4\", half_move_location: 76 } }, Tree { children: [], value: PgnMove { value: \"Bxf4\", half_move_location: 77 } }, Tree { children: [], value: PgnMove { value: \"exf4\", half_move_location: 78 } }, Tree { children: [], value: PgnMove { value: \"Nh4\", half_move_location: 79 } }, Tree { children: [], value: PgnMove { value: \"Bf7\", half_move_location: 80 } }, Tree { children: [], value: PgnMove { value: \"Qd4+\", half_move_location: 81 } }, Tree { children: [], value: PgnMove { value: \"Ke6\", half_move_location: 82 } }, Tree { children: [], value: PgnMove { value: \"Nf5\", half_move_location: 83 } }, Tree { children: [], value: PgnMove { value: \"Bf8\", half_move_location: 84 } }, Tree { children: [], value: PgnMove { value: \"Qxf4\", half_move_location: 85 } }, Tree { children: [], value: PgnMove { value: \"Kd7\", half_move_location: 86 } }, Tree { children: [], value: PgnMove { value: \"Nd4\", half_move_location: 87 } }, Tree { children: [], value: PgnMove { value: \"Qe1+\", half_move_location: 88 } }, Tree { children: [], value: PgnMove { value: \"Kg2\", half_move_location: 89 } }, Tree { children: [], value: PgnMove { value: \"Bd5+\", half_move_location: 90 } }, Tree { children: [], value: PgnMove { value: \"Be4\", half_move_location: 91 } }, Tree { children: [], value: PgnMove { value: \"Bxe4+\", half_move_location: 92 } }, Tree { children: [], value: PgnMove { value: \"Nxe4\", half_move_location: 93 } }, Tree { children: [], value: PgnMove { value: \"Be7\", half_move_location: 94 } }, Tree { children: [], value: PgnMove { value: \"Nxb5\", half_move_location: 95 } }, Tree { children: [], value: PgnMove { value: \"Nf8\", half_move_location: 96 } }, Tree { children: [], value: PgnMove { value: \"Nbxd6\", half_move_location: 97 } }, Tree { children: [], value: PgnMove { value: \"Ne6\", half_move_location: 98 } }, Tree { children: [], value: PgnMove { value: \"Qe5\", half_move_location: 99 } }], value: PgnMove { value: \"\", half_move_location: 0 } }, result: WhiteWon }])";
+ let expected_output = "Ok([Header(\"Event\", \"Fischer - Spassky\"), Header(\"Site\", \"Sveti Stefan / Belgrade YUG\"), Header(\"Date\", \"1992.09.02\"), Header(\"EventDate\", \"1992.09.02\"), Header(\"Round\", \"1\"), Header(\"Result\", \"1-0\"), Header(\"White\", \"Robert James Fischer\"), Header(\"Black\", \"Boris Spassky\"), Header(\"ECO\", \"C95\"), Header(\"WhiteElo\", \"?\"), Header(\"BlackElo\", \"?\"), Header(\"PlyCount\", \"99\"), HalfMoveNumber(1), PgnMove(\"e4\"), HalfMoveNumber(2), PgnMove(\"e5\"), HalfMoveNumber(3), PgnMove(\"Nf3\"), HalfMoveNumber(4), PgnMove(\"Nc6\"), HalfMoveNumber(5), PgnMove(\"Bb5\"), HalfMoveNumber(6), PgnMove(\"a6\"), HalfMoveNumber(7), PgnMove(\"Ba4\"), HalfMoveNumber(8), PgnMove(\"Nf6\"), HalfMoveNumber(9), PgnMove(\"O-O\"), HalfMoveNumber(10), PgnMove(\"Be7\"), HalfMoveNumber(11), PgnMove(\"Re1\"), HalfMoveNumber(12), PgnMove(\"b5\"), HalfMoveNumber(13), PgnMove(\"Bb3\"), HalfMoveNumber(14), PgnMove(\"O-O\"), HalfMoveNumber(15), PgnMove(\"c3\"), HalfMoveNumber(16), PgnMove(\"d6\"), HalfMoveNumber(17), PgnMove(\"h3\"), HalfMoveNumber(18), PgnMove(\"Nb8\"), HalfMoveNumber(19), PgnMove(\"d4\"), HalfMoveNumber(20), PgnMove(\"Nbd7\"), HalfMoveNumber(21), PgnMove(\"Nbd2\"), HalfMoveNumber(22), PgnMove(\"Bb7\"), HalfMoveNumber(23), PgnMove(\"Bc2\"), HalfMoveNumber(24), PgnMove(\"Re8\"), HalfMoveNumber(25), PgnMove(\"Nf1\"), HalfMoveNumber(26), PgnMove(\"Bf8\"), HalfMoveNumber(27), PgnMove(\"Ng3\"), HalfMoveNumber(28), PgnMove(\"g6\"), HalfMoveNumber(29), PgnMove(\"Bg5\"), HalfMoveNumber(30), PgnMove(\"h6\"), HalfMoveNumber(31), PgnMove(\"Bd2\"), HalfMoveNumber(32), PgnMove(\"Bg7\"), HalfMoveNumber(33), PgnMove(\"a4\"), HalfMoveNumber(34), PgnMove(\"c5\"), HalfMoveNumber(35), PgnMove(\"d5\"), HalfMoveNumber(36), PgnMove(\"c4\"), HalfMoveNumber(37), PgnMove(\"b4\"), HalfMoveNumber(38), PgnMove(\"Nh7\"), HalfMoveNumber(39), PgnMove(\"Be3\"), HalfMoveNumber(40), PgnMove(\"h5\"), HalfMoveNumber(41), PgnMove(\"Qd2\"), HalfMoveNumber(42), PgnMove(\"Rf8\"), HalfMoveNumber(43), PgnMove(\"Ra3\"), HalfMoveNumber(44), PgnMove(\"Ndf6\"), HalfMoveNumber(45), PgnMove(\"Rea1\"), HalfMoveNumber(46), PgnMove(\"Qd7\"), HalfMoveNumber(47), PgnMove(\"R1a2\"), HalfMoveNumber(48), PgnMove(\"Rfc8\"), HalfMoveNumber(49), PgnMove(\"Qc1\"), HalfMoveNumber(50), PgnMove(\"Bf8\"), HalfMoveNumber(51), PgnMove(\"Qa1\"), HalfMoveNumber(52), PgnMove(\"Qe8\"), HalfMoveNumber(53), PgnMove(\"Nf1\"), HalfMoveNumber(54), PgnMove(\"Be7\"), HalfMoveNumber(55), PgnMove(\"N1d2\"), HalfMoveNumber(56), PgnMove(\"Kg7\"), HalfMoveNumber(57), PgnMove(\"Nb1\"), HalfMoveNumber(58), PgnMove(\"Nxe4\"), HalfMoveNumber(59), PgnMove(\"Bxe4\"), HalfMoveNumber(60), PgnMove(\"f5\"), HalfMoveNumber(61), PgnMove(\"Bc2\"), HalfMoveNumber(62), PgnMove(\"Bxd5\"), HalfMoveNumber(63), PgnMove(\"axb5\"), HalfMoveNumber(64), PgnMove(\"axb5\"), HalfMoveNumber(65), PgnMove(\"Ra7\"), HalfMoveNumber(66), PgnMove(\"Kf6\"), HalfMoveNumber(67), PgnMove(\"Nbd2\"), HalfMoveNumber(68), PgnMove(\"Rxa7\"), HalfMoveNumber(69), PgnMove(\"Rxa7\"), HalfMoveNumber(70), PgnMove(\"Ra8\"), HalfMoveNumber(71), PgnMove(\"g4\"), HalfMoveNumber(72), PgnMove(\"hxg4\"), HalfMoveNumber(73), PgnMove(\"hxg4\"), HalfMoveNumber(74), PgnMove(\"Rxa7\"), HalfMoveNumber(75), PgnMove(\"Qxa7\"), HalfMoveNumber(76), PgnMove(\"f4\"), HalfMoveNumber(77), PgnMove(\"Bxf4\"), HalfMoveNumber(78), PgnMove(\"exf4\"), HalfMoveNumber(79), PgnMove(\"Nh4\"), HalfMoveNumber(80), PgnMove(\"Bf7\"), HalfMoveNumber(81), PgnMove(\"Qd4+\"), HalfMoveNumber(82), PgnMove(\"Ke6\"), HalfMoveNumber(83), PgnMove(\"Nf5\"), HalfMoveNumber(84), PgnMove(\"Bf8\"), HalfMoveNumber(85), PgnMove(\"Qxf4\"), HalfMoveNumber(86), PgnMove(\"Kd7\"), HalfMoveNumber(87), PgnMove(\"Nd4\"), HalfMoveNumber(88), PgnMove(\"Qe1+\"), HalfMoveNumber(89), PgnMove(\"Kg2\"), HalfMoveNumber(90), PgnMove(\"Bd5+\"), HalfMoveNumber(91), PgnMove(\"Be4\"), HalfMoveNumber(92), Result(WhiteWon), PgnMove(\"Bxe4+\"), HalfMoveNumber(93), PgnMove(\"Nxe4\"), HalfMoveNumber(94), PgnMove(\"Be7\"), HalfMoveNumber(95), PgnMove(\"Nxb5\"), HalfMoveNumber(96), PgnMove(\"Nf8\"), HalfMoveNumber(97), PgnMove(\"Nbxd6\"), HalfMoveNumber(98), PgnMove(\"Ne6\"), HalfMoveNumber(99), PgnMove(\"Qe5\"), HalfMoveNumber(100)])";
assert_eq!(
expected_output,