package main
import "strconv"
type char struct {
modifier bool
char byte
}
func ParseRange(pattern string) []byte {
chars := tokenize(pattern)
var bytes []byte
l := len(chars)
for i := 0; i < l; i++ {
if i+1 < l && chars[i+1].char == '-' && chars[i+1].modifier {
bytes = append(bytes, expand(chars[i].char, chars[i+2].char)...)
i += 2
} else {
bytes = append(bytes, chars[i].char)
}
}
return bytes
}
func tokenize(pattern string) []char {
var chars []char
l := len(pattern)
for i := 0; i < l; i++ {
literal := literal(pattern, &i)
if literal != nil {
chars = append(chars, *literal)
continue
}
if pattern[i] == '-' && i+1 < l {
lc := len(chars)
if lc > 0 && !chars[lc-1].modifier && (lc == 1 || !(chars[lc-2].modifier && chars[lc-2].char == '-')) {
chars = append(chars, char{true, '-'})
continue
}
}
chars = append(chars, char{false, pattern[i]})
}
return chars
}
func literal(pattern string, i *int) *char {
for j := *i + 1; pattern[*i] == '{' && j < len(pattern); j++ {
if pattern[j] == '}' {
n, err := strconv.Atoi(pattern[*i+1 : j])
if err == nil && n >= 0 && n <= 0xff {
*i = j
return &char{false, byte(n)}
}
}
}
return nil
}
func expand(start byte, end byte) []byte {
if start > end {
start, end = end, start
}
bytes := make([]byte, end-start+1)
for i := start; i <= end; i++ {
bytes[i-start] = i
}
return bytes
}