1 /* DreamChess
2 **
3 ** DreamChess is the legal property of its developers, whose names are too
4 ** numerous to list here. Please refer to the AUTHORS.txt file distributed
5 ** with this source distribution.
6 **
7 ** This program is free software: you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation, either version 3 of the License, or
10 ** (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 %token CFILE
22 %token CRANK
23
24 %{
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "san.h"
29
30 int yylex(void);
31 int yyerror(const char *s);
32
33 san_move_t san_move;
34 %}
35
36 %%
37
38 input : san
39 ;
40
41 san : mark move
42 ;
43
44 move /* Queenside castle. */
45 : 'O' '-' 'O' '-' 'O' { san_move.type = SAN_QUEENSIDE_CASTLE; }
46 /* Kingside castle. */
47 | 'O' '-' 'O' { san_move.type = SAN_KINGSIDE_CASTLE; }
48 /* Non-pawn capture without rank. */
49 | dest capt op_file piece
50 /* Non-pawn move without rank. */
51 | dest op_file piece
52 /* Non-pawn move or capture with rank. */
53 | dest op_capt rank op_file piece
54 /* Pawn move with promotion and capture. */
55 | promo '=' dest capt file
56 /* Pawn move with promotion. */
57 | promo '=' dest
58 /* Pawn move with capture. */
59 | dest capt file
60 /* Pawn move without capture or promotion. */
61 | dest
62 ;
63
64 piece : 'Q' { san_move.piece = SAN_QUEEN; }
65 | 'R' { san_move.piece = SAN_ROOK; }
66 | 'B' { san_move.piece = SAN_BISHOP; }
67 | 'N' { san_move.piece = SAN_KNIGHT; }
68 | 'K' { san_move.piece = SAN_KING; }
69 ;
70
71 op_capt :
72 | capt
73 ;
74
75 op_file :
76 | file
77 ;
78
79 file : CFILE { san_move.source_file = $1; }
80 ;
81
82 rank : CRANK { san_move.source_rank = $1; }
83 ;
84
85 capt : 'x' { san_move.type = SAN_CAPTURE; }
86 ;
87
88 dest : CRANK CFILE { san_move.destination = 8 * $1 + $2; }
89 ;
90
91 mark :
92 | '+' { san_move.state = SAN_STATE_CHECK; }
93 | '#' { san_move.state = SAN_STATE_CHECKMATE; }
94 ;
95
96 promo : 'Q' { san_move.promotion_piece = SAN_QUEEN; }
97 | 'R' { san_move.promotion_piece = SAN_ROOK; }
98 | 'B' { san_move.promotion_piece = SAN_BISHOP; }
99 | 'N' { san_move.promotion_piece = SAN_KNIGHT; }
100 ;
101 %%
102
103 #include <stdio.h>
104 #include <ctype.h>
105
106 #include "san.h"
107
108 char* move;
109 int ptr;
110
san_parse(char * s)111 san_move_t *san_parse(char *s)
112 {
113 move = s;
114 ptr = strlen(move) - 1;
115
116 san_move.type = SAN_NORMAL;
117 san_move.state = SAN_STATE_NORMAL;
118 san_move.piece = SAN_PAWN;
119 san_move.destination = SAN_NOT_SPECIFIED;
120 san_move.source_rank = SAN_NOT_SPECIFIED;
121 san_move.source_file = SAN_NOT_SPECIFIED;
122 san_move.promotion_piece = SAN_NOT_SPECIFIED;
123
124 if (!yyparse())
125 {
126 san_move_t *retval = malloc(sizeof(san_move_t));
127 *retval = san_move;
128 return retval;
129 }
130
131 return NULL;
132 }
133
add_piece(char * s,int piece)134 static void add_piece(char *s, int piece)
135 {
136 switch(piece)
137 {
138 case SAN_QUEEN:
139 *s = 'Q';
140 break;
141 case SAN_ROOK:
142 *s = 'R';
143 break;
144 case SAN_BISHOP:
145 *s = 'B';
146 break;
147 case SAN_KNIGHT:
148 *s = 'N';
149 break;
150 case SAN_KING:
151 *s = 'K';
152 }
153 }
154
san_string(san_move_t * move)155 char *san_string(san_move_t *move)
156 {
157 char *s = malloc(8);
158 int i = 0;
159
160 switch (move->type)
161 {
162 case SAN_NORMAL:
163 case SAN_CAPTURE:
164 {
165 if ((move->piece != SAN_NOT_SPECIFIED) && (move->piece != SAN_PAWN))
166 add_piece(s + i++, move->piece);
167
168 if (move->source_file != SAN_NOT_SPECIFIED)
169 s[i++] = move->source_file + 'a';
170
171 if (move->source_rank != SAN_NOT_SPECIFIED)
172 s[i++] = move->source_rank + '1';
173
174 if (move->type == SAN_CAPTURE)
175 s[i++] = 'x';
176
177 s[i++] = move->destination % 8 + 'a';
178 s[i++] = move->destination / 8 + '1';
179
180 if (move->promotion_piece != SAN_NOT_SPECIFIED)
181 {
182 s[i++] = '=';
183 add_piece(s + i++, move->promotion_piece);
184 }
185 }
186 break;
187 case SAN_QUEENSIDE_CASTLE:
188 strcpy(s, "O-O-O");
189 i = 5;
190 break;
191 case SAN_KINGSIDE_CASTLE:
192 strcpy(s, "O-O");
193 i = 3;
194 }
195
196 if (move->state == SAN_STATE_CHECK)
197 s[i++] = '+';
198 else if (move->state == SAN_STATE_CHECKMATE)
199 s[i++] = '#';
200
201 s[i] = '\0';
202
203 return s;
204 }
205
yyerror(const char * s)206 int yyerror(const char *s)
207 {
208 return 1;
209 }
210
yylex(void)211 int yylex(void)
212 {
213 int c;
214
215 if (ptr >= 0)
216 {
217 c = move[ptr--];
218
219 if ((c >= '1') && (c <= '8'))
220 {
221 yylval = c - '1';
222 return CRANK;
223 }
224
225 if ((c >= 'a') && (c <= 'h'))
226 {
227 yylval = c - 'a';
228 return CFILE;
229 }
230
231 return c;
232 }
233
234 return 0;
235 }
236