aboutsummaryrefslogtreecommitdiff
path: root/DotnetPgn
diff options
context:
space:
mode:
Diffstat (limited to 'DotnetPgn')
-rw-r--r--DotnetPgn/DotnetPgn.csproj7
-rw-r--r--DotnetPgn/Models/Enums.cs18
-rw-r--r--DotnetPgn/Models/HalfMove.cs11
-rw-r--r--DotnetPgn/Models/Square.cs22
-rw-r--r--DotnetPgn/PieceParser.cs22
-rw-r--r--DotnetPgn/Tokenizer.cs75
6 files changed, 155 insertions, 0 deletions
diff --git a/DotnetPgn/DotnetPgn.csproj b/DotnetPgn/DotnetPgn.csproj
new file mode 100644
index 0000000..563e6f9
--- /dev/null
+++ b/DotnetPgn/DotnetPgn.csproj
@@ -0,0 +1,7 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>net5.0</TargetFramework>
+ </PropertyGroup>
+
+</Project>
diff --git a/DotnetPgn/Models/Enums.cs b/DotnetPgn/Models/Enums.cs
new file mode 100644
index 0000000..893f2fa
--- /dev/null
+++ b/DotnetPgn/Models/Enums.cs
@@ -0,0 +1,18 @@
+namespace DotnetPgn.Models
+{
+ public enum Piece
+ {
+ Pawn,
+ Knight,
+ Bishop,
+ Rook,
+ Queen,
+ King,
+ }
+
+ public enum Player
+ {
+ White,
+ Black,
+ }
+} \ No newline at end of file
diff --git a/DotnetPgn/Models/HalfMove.cs b/DotnetPgn/Models/HalfMove.cs
new file mode 100644
index 0000000..b94d77d
--- /dev/null
+++ b/DotnetPgn/Models/HalfMove.cs
@@ -0,0 +1,11 @@
+namespace DotnetPgn.Models
+{
+ public record HalfMove
+ {
+ public int MoveNumber {get; init;}
+ public Player Player { get; init; }
+ public Piece Piece { get; init; }
+ public Square SourceSquare { get; init; }
+ public Square TargetSquare { get; init; }
+ }
+} \ No newline at end of file
diff --git a/DotnetPgn/Models/Square.cs b/DotnetPgn/Models/Square.cs
new file mode 100644
index 0000000..a3910d3
--- /dev/null
+++ b/DotnetPgn/Models/Square.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace DotnetPgn.Models
+{
+ public record Square
+ {
+ public char Rank { get; }
+ public int File { get; }
+
+ public Square(char rank, int file)
+ {
+ if (rank < 'a' || rank > 'h')
+ throw new ArgumentException($"Invalid rank '{rank}'.");
+
+ if (file < 1 || file > 8)
+ throw new ArgumentException($"Invalid file '{file}'.");
+
+ Rank = rank;
+ File = file;
+ }
+ }
+} \ No newline at end of file
diff --git a/DotnetPgn/PieceParser.cs b/DotnetPgn/PieceParser.cs
new file mode 100644
index 0000000..5ea9402
--- /dev/null
+++ b/DotnetPgn/PieceParser.cs
@@ -0,0 +1,22 @@
+using System;
+using DotnetPgn.Models;
+
+namespace DotnetPgn
+{
+ public static class PieceParser
+ {
+ public static Piece ParsePiece(string sanPiece)
+ {
+ return sanPiece switch
+ {
+ "P" or "p" or "" => Piece.Pawn,
+ "N" or "n" => Piece.Knight,
+ "B" or "b" => Piece.Bishop,
+ "R" or "r" => Piece.Rook,
+ "Q" or "q" => Piece.Queen,
+ "K" or "k" => Piece.King,
+ _ => throw new ArgumentException($"'{sanPiece} is not a valid piece.'"),
+ };
+ }
+ }
+}
diff --git a/DotnetPgn/Tokenizer.cs b/DotnetPgn/Tokenizer.cs
new file mode 100644
index 0000000..9f779cb
--- /dev/null
+++ b/DotnetPgn/Tokenizer.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Text.RegularExpressions;
+using DotnetPgn.Models;
+
+namespace DotnetPgn
+{
+ public static class Tokenizer
+ {
+ private static readonly Regex s_halfMoveRegex =
+ new(@"([KQRBNP]?)([a-h]?[1-8]?)(x?)([a-h][1-8])([+#]?)");
+
+ public static IEnumerable<HalfMove> ParseMoves(string moveText)
+ {
+ StringBuilder currToken = new();
+ char[] moveTextChars = moveText.ToCharArray();
+ int moveNumber = 1;
+ Player currPlayer = Player.White;
+
+ for (int i = 0; i < moveTextChars.Length; i++)
+ {
+ char nextChar = moveTextChars[i];
+
+ if (nextChar is ' ' or '\t' or '\n' or '\r')
+ {
+ // We should have either a move number or a complete halfmove.
+ string token = currToken.ToString();
+ currToken.Clear();
+ Match match = s_halfMoveRegex.Match(token);
+
+ if (!match.Success)
+ {
+ Console.WriteLine($"Unrecognized token: `{token}`");
+ Console.WriteLine();
+ continue;
+ }
+
+ Console.WriteLine($"Recognized token: {token}");
+ Console.WriteLine($"Matching groups: ({match.Groups[1].Value})" +
+ $"({match.Groups[2].Value})({match.Groups[3].Value})({match.Groups[4].Value})" +
+ $"({match.Groups[5].Value})");
+
+ var move = new HalfMove
+ {
+ MoveNumber = moveNumber,
+ Player = currPlayer,
+ Piece = PieceParser.ParsePiece(match.Groups[1].Value),
+ TargetSquare = new Square(match.Groups[4].Value[0], Convert.ToInt32(Char.GetNumericValue(match.Groups[4].Value[1]))),
+ };
+
+ Console.WriteLine($"Halfmove: {move.MoveNumber}. {move.Player} {move.Piece} from {move.SourceSquare} to {move.TargetSquare}");
+ Console.WriteLine();
+
+ if (currPlayer == Player.White)
+ {
+ currPlayer = Player.Black;
+ }
+ else
+ {
+ currPlayer = Player.White;
+ moveNumber++;
+ }
+
+ yield return move;
+ }
+ else
+ {
+ currToken.Append(nextChar);
+ }
+ }
+ }
+ }
+} \ No newline at end of file