-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparse.go
96 lines (87 loc) · 2.18 KB
/
parse.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package mj
import (
"errors"
"strings"
)
var suitParse = map[uint8]Suit{
'b': Bamboo,
'c': Coin,
'w': Wan,
'h': Honour,
'f': Flower,
}
var honourParse = map[uint8]Value{
'e': East,
's': South,
'w': West,
'n': North,
'z': Zhong,
'f': Fa,
'b': Ban,
}
// ParseTile turns a 2-character string into a Tile.
// The first character is the Suit and may be one of the characters "bcwhf" (for
// Bamboo, Coin, Wan, Honour and Flower).
// The second character is the Value and its permissible range depends on the Suit:
// - Bamboo, Coin and Wan: a digit between 1-9 inclusive.
// - Honour: one of the characters "eswnzfb" (for East, South, West, North,
// Zhong, Fa and Ban).
// - Flower: a digit between 1-8 inclusive.
// Parsing errors are returned in err.
func ParseTile(s string) (t Tile, err error) {
var ok bool
if len(s) != 2 {
err = errors.New("tile representation must be 2 characters long")
return
}
s = strings.ToLower(s)
t.Suit, ok = suitParse[s[0]]
if !ok {
err = errors.New("unrecognised suit: " + string(s[0]))
return
}
switch t.Suit {
case Bamboo, Coin, Wan:
t.Value = Value(s[1] - '0')
if t.Value < 1 || t.Value > 9 {
err = errors.New("invalid value for simple tile: " + string(s[1]))
}
case Honour:
t.Value, ok = honourParse[s[1]]
if !ok {
err = errors.New("invalid value for honour suit: " + string(s[1]))
}
case Flower:
t.Value = Value(s[1] - '0')
if t.Value < 1 || t.Value > 8 {
err = errors.New("invalid value for flower tile: " + string(s[1]))
}
t.Value |= FlowerBase
default:
panic("ParseTile: unreachable")
}
return
}
// ParseHand turns a space-separated string of 2-character sequences into a Hand, in order.
// Each 2-character sequence is passed to ParseTile.
func ParseHand(s string) (h Hand, err error) {
s = strings.TrimSpace(s)
ss := strings.Split(s, " ")
h = make(Hand, len(ss))
for i, t := range ss {
h[i], err = ParseTile(t)
if err != nil {
return
}
}
return
}
// MustParseHand is like ParseHand, but panics if the string cannot be parsed.
// Useful for testing code, setup, etc.
func MustParseHand(s string) Hand {
h, err := ParseHand(s)
if err != nil {
panic("mustParseHand: " + err.Error())
}
return h
}