Skip to content

Commit 975bdbf

Browse files
committed
fixed: incorrect handling of "!,?,??,!!,?!,!?"
1 parent 4206764 commit 975bdbf

File tree

1 file changed

+53
-23
lines changed

1 file changed

+53
-23
lines changed

pgn.go

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"io"
88
"regexp"
99
"strconv"
10-
"strings"
1110
)
1211

1312
type pgnToken int
@@ -33,7 +32,7 @@ const (
3332
)
3433

3534
const (
36-
pgnSAN_REGEXP = "^(((O-O|O-O-O)|((P?|[RNBQK])[a-h]?[1-8]?x?[a-h][1-8](=[PRNBQK])?))(\\+|#)?(!|\\?|!!|\\?\\?|\\?!|!\\?)?)$"
35+
pgnSAN_REGEXP = "^(((O-O|O-O-O)|((P?|[RNBQK])[a-h]?[1-8]?x?[a-h][1-8](=[PRNBQK])?))(\\+|#)?)$"
3736
pgnTAG_REGEXP = `^\[?\s*([A-Za-z0-9_]+)\s+"(.*)"\s*\]`
3837
)
3938

@@ -43,6 +42,15 @@ var (
4342
whiteWins []byte = []byte("1-0")
4443
blackWins []byte = []byte("0-1")
4544
drawRes []byte = []byte("1/2-1/2")
45+
46+
specialAnnotations [][]byte = [][]byte{
47+
[]byte("??"),
48+
[]byte("!!"),
49+
[]byte("!?"),
50+
[]byte("?!"),
51+
[]byte("?"),
52+
[]byte("!"),
53+
}
4654
)
4755

4856
// Parser is a parser for the PGN chess games notation
@@ -251,6 +259,16 @@ func (t *tokenizer) next() token {
251259
return token{pgnSTRING, tok}
252260
}
253261

262+
// special handling for these six annotations
263+
// they can appear only in the import format
264+
// in export format they are always nags
265+
for _, s := range specialAnnotations {
266+
if bytes.HasPrefix(t.text, s) {
267+
t.text = t.text[len(s):]
268+
return token{pgnTOKEN, string(s)}
269+
}
270+
}
271+
254272
if bytes.HasPrefix(t.text, whiteWins) {
255273
t.text = t.text[len(whiteWins):]
256274
return token{pgnRESULT, "1-0"}
@@ -329,7 +347,7 @@ func (t *tokenizer) next() token {
329347
break
330348
}
331349
}
332-
tok := string(t.text[0:pos])
350+
tok := string(t.text[0: pos])
333351
t.text = t.text[pos:]
334352
if isSymbol {
335353
return token{pgnSYMBOL, tok}
@@ -338,6 +356,10 @@ func (t *tokenizer) next() token {
338356
} else if isInteger {
339357
return token{pgnINTEGER, tok}
340358
}
359+
if tok == "" {
360+
// quick and ugly hack to get error reporting right
361+
tok = string(t.text[0: len(t.text)])
362+
}
341363
return token{pgnTOKEN, tok}
342364
}
343365

@@ -417,25 +439,6 @@ func (t *tokenizer) generatePlies(variation *Variation, inRav bool, thisMoveNumb
417439
return fmt.Errorf("mismatched SAN '%s'", token.val)
418440
}
419441
SAN = token.val
420-
if strings.HasSuffix(SAN, "!!") {
421-
SAN = SAN[:len(SAN)-2]
422-
ply.Nags = append(ply.Nags, 3)
423-
} else if strings.HasSuffix(SAN, "??") {
424-
SAN = SAN[:len(SAN)-2]
425-
ply.Nags = append(ply.Nags, 4)
426-
} else if strings.HasSuffix(SAN, "!?") {
427-
SAN = SAN[:len(SAN)-2]
428-
ply.Nags = append(ply.Nags, 5)
429-
} else if strings.HasSuffix(SAN, "?!") {
430-
SAN = SAN[:len(SAN)-2]
431-
ply.Nags = append(ply.Nags, 6)
432-
} else if strings.HasSuffix(SAN, "!") {
433-
SAN = SAN[:len(SAN)-1]
434-
ply.Nags = append(ply.Nags, 1)
435-
} else if strings.HasSuffix(SAN, "?") {
436-
SAN = SAN[:len(SAN)-1]
437-
ply.Nags = append(ply.Nags, 2)
438-
}
439442
}
440443
ply = &Ply{SAN: SAN}
441444
variation.Plies = append(variation.Plies, ply)
@@ -467,7 +470,34 @@ func (t *tokenizer) generatePlies(variation *Variation, inRav bool, thisMoveNumb
467470
}
468471

469472
default:
470-
return fmt.Errorf("unexpected token '%d:%s'", token.typ, token.val)
473+
switch token.val {
474+
case "!":
475+
if ply != nil {
476+
ply.Nags = append(ply.Nags, 1)
477+
}
478+
case "?":
479+
if ply != nil {
480+
ply.Nags = append(ply.Nags, 2)
481+
}
482+
case "!!":
483+
if ply != nil {
484+
ply.Nags = append(ply.Nags, 3)
485+
}
486+
case "??":
487+
if ply != nil {
488+
ply.Nags = append(ply.Nags, 4)
489+
}
490+
case "!?":
491+
if ply != nil {
492+
ply.Nags = append(ply.Nags, 5)
493+
}
494+
case "?!":
495+
if ply != nil {
496+
ply.Nags = append(ply.Nags, 6)
497+
}
498+
default:
499+
return fmt.Errorf("unexpected token '%s'", token.val)
500+
}
471501
}
472502
}
473503
return nil

0 commit comments

Comments
 (0)