sashite-pan 2.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,90 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "parser/error"
4
-
5
- module Sashite
6
- module Pan
7
- # Parser for Portable Action Notation (PAN) strings
8
- module Parser
9
- # Parse a PAN string into PMN format
10
- #
11
- # @param pan_string [String] The PAN string to parse
12
- # @return [Array<Hash>] Array of PMN action objects
13
- # @raise [Parser::Error] If the PAN string is invalid
14
- def self.call(pan_string)
15
- raise Parser::Error, "PAN string cannot be nil" if pan_string.nil?
16
- raise Parser::Error, "PAN string cannot be empty" if pan_string.empty?
17
-
18
- actions = pan_string.split(";").map(&:strip)
19
- raise Parser::Error, "No actions found" if actions.empty?
20
-
21
- actions.map { |action| parse_action(action) }
22
- end
23
-
24
- private
25
-
26
- # Parse a single action string into a PMN action hash
27
- #
28
- # @param action_string [String] Single action in PAN format
29
- # @return [Hash] PMN action object
30
- # @raise [Parser::Error] If the action is invalid
31
- def self.parse_action(action_string)
32
- components = action_string.split(",").map(&:strip)
33
-
34
- validate_action_components(components)
35
-
36
- {
37
- "src_square" => parse_source_square(components[0]),
38
- "dst_square" => components[1],
39
- "piece_name" => components[2],
40
- "piece_hand" => components[3] || nil
41
- }.compact
42
- end
43
-
44
- # Validate action components structure
45
- #
46
- # @param components [Array<String>] Components of the action
47
- # @raise [Parser::Error] If components are invalid
48
- def self.validate_action_components(components)
49
- case components.length
50
- when 0, 1, 2
51
- raise Parser::Error, "Action must have at least 3 components (source, destination, piece)"
52
- when 3, 4
53
- # Valid number of components
54
- else
55
- raise Parser::Error, "Action cannot have more than 4 components"
56
- end
57
-
58
- components.each_with_index do |component, index|
59
- if component.nil? || component.empty?
60
- raise Parser::Error, "Component #{index} cannot be empty"
61
- end
62
- end
63
-
64
- validate_piece_identifier(components[2])
65
- validate_piece_identifier(components[3]) if components[3]
66
- end
67
-
68
- # Parse source square, handling drop notation
69
- #
70
- # @param source [String] Source square or "*" for drop
71
- # @return [String, nil] Square identifier or nil for drops
72
- def self.parse_source_square(source)
73
- source == "*" ? nil : source
74
- end
75
-
76
- # Validate piece identifier follows PNN specification
77
- #
78
- # @param piece [String] Piece identifier to validate
79
- # @raise [Parser::Error] If piece identifier is invalid
80
- def self.validate_piece_identifier(piece)
81
- return if piece.nil?
82
-
83
- # PNN pattern: optional prefix (+/-), letter (a-z/A-Z), optional suffix (')
84
- unless piece.match?(/\A[-+]?[a-zA-Z][']?\z/)
85
- raise Parser::Error, "Invalid piece identifier: #{piece}"
86
- end
87
- end
88
- end
89
- end
90
- end