summaryrefslogtreecommitdiffhomepage
path: root/lib/mintage
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2024-09-13 13:01:48 +0200
committerThomas Voss <mail@thomasvoss.com> 2024-09-13 13:01:48 +0200
commit548090e67f66acf84385c4152ca464e52d3e3319 (patch)
tree9b6de528bd7b0aa63362fa83f5c8e6a97f68a5d8 /lib/mintage
parenta1d809960bee74df19c7e5fc34ffd1e4757cfdcb (diff)
Migrate away from templ and towards html/template
Diffstat (limited to 'lib/mintage')
-rw-r--r--lib/mintage/parser.go297
-rw-r--r--lib/mintage/parser_test.go233
2 files changed, 0 insertions, 530 deletions
diff --git a/lib/mintage/parser.go b/lib/mintage/parser.go
deleted file mode 100644
index 364b6e8..0000000
--- a/lib/mintage/parser.go
+++ /dev/null
@@ -1,297 +0,0 @@
-package mintage
-
-import (
- "bufio"
- "fmt"
- "io"
- "strconv"
- "strings"
- "time"
-)
-
-type SyntaxError struct {
- expected, got string
- file string
- linenr int
-}
-
-func (e SyntaxError) Error() string {
- return fmt.Sprintf("%s:%d: syntax error: expected %s but got %s",
- e.file, e.linenr, e.expected, e.got)
-}
-
-type Data struct {
- Standard []SRow
- Commemorative []CRow
-}
-
-type SRow struct {
- Year int
- Mintmark string
- Mintages [typeCount][denoms]int
-}
-
-type CRow struct {
- Year int
- Mintmark string
- Name string
- Mintage [typeCount]int
-}
-
-const (
- TypeCirc = iota
- TypeNIFC
- TypeProof
- typeCount
-)
-
-const (
- Unknown = -iota - 1
- Invalid
-)
-
-const (
- denoms = 8
- ws = " \t"
-)
-
-func Parse(r io.Reader, file string) (Data, error) {
- yearsSince := time.Now().Year() - 1999 + 1
- data := Data{
- Standard: make([]SRow, 0, yearsSince),
- Commemorative: make([]CRow, 0, yearsSince),
- }
-
- scanner := bufio.NewScanner(r)
- for linenr := 1; scanner.Scan(); linenr++ {
- line := strings.Trim(scanner.Text(), ws)
- if isBlankOrComment(line) {
- continue
- }
-
- if len(line) < 4 || !isNumeric(line[:4], false) {
- return Data{}, SyntaxError{
- expected: "4-digit year",
- got: line,
- linenr: linenr,
- file: file,
- }
- }
-
- var (
- commem bool
- mintmark string
- )
- year, _ := strconv.Atoi(line[:4])
- line = line[4:]
-
- if len(line) != 0 {
- if strings.ContainsRune(ws, rune(line[0])) {
- commem = true
- goto out
- }
- if line[0] != '-' {
- return Data{}, SyntaxError{
- expected: "end-of-line or mintmark",
- got: line,
- linenr: linenr,
- file: file,
- }
- }
-
- if line = line[1:]; len(line) == 0 {
- return Data{}, SyntaxError{
- expected: "mintmark",
- got: "end-of-line",
- linenr: linenr,
- file: file,
- }
- }
-
- switch i := strings.IndexAny(line, ws); i {
- case 0:
- return Data{}, SyntaxError{
- expected: "mintmark",
- got: "whitespace",
- linenr: linenr,
- file: file,
- }
- case -1:
- mintmark = line
- default:
- mintmark, line = line[:i], line[i:]
- commem = true
- }
- }
- out:
-
- if !commem {
- row := SRow{
- Year: year,
- Mintmark: mintmark,
- }
- for i := range row.Mintages {
- line = ""
- for isBlankOrComment(line) {
- if !scanner.Scan() {
- return Data{}, SyntaxError{
- expected: "mintage row",
- got: "end-of-file",
- linenr: linenr,
- file: file,
- }
- }
- line = strings.Trim(scanner.Text(), ws)
- linenr++
- }
-
- tokens := strings.FieldsFunc(line, func(r rune) bool {
- return strings.ContainsRune(ws, r)
- })
- if tokcnt := len(tokens); tokcnt != denoms {
- word := "entries"
- if tokcnt == 1 {
- word = "entry"
- }
- return Data{}, SyntaxError{
- expected: fmt.Sprintf("%d mintage entries", denoms),
- got: fmt.Sprintf("%d %s", tokcnt, word),
- linenr: linenr,
- file: file,
- }
- }
-
- for j, tok := range tokens {
- if tok != "?" && !isNumeric(tok, true) {
- return Data{}, SyntaxError{
- expected: "numeric mintage figure or ‘?’",
- got: tok,
- linenr: linenr,
- file: file,
- }
- }
-
- if tok == "?" {
- row.Mintages[i][j] = Unknown
- } else {
- row.Mintages[i][j] = atoiWithDots(tok)
- }
- }
- }
-
- data.Standard = append(data.Standard, row)
- } else {
- row := CRow{
- Year: year,
- Mintmark: mintmark,
- }
- line = strings.TrimLeft(line, ws)
- if line[0] != '"' {
- return Data{}, SyntaxError{
- expected: "string",
- got: line,
- linenr: linenr,
- file: file,
- }
- }
-
- line = line[1:]
- switch i := strings.IndexByte(line, '"'); i {
- case -1:
- return Data{}, SyntaxError{
- expected: "closing quote",
- got: "end-of-line",
- linenr: linenr,
- file: file,
- }
- case 0:
- return Data{}, SyntaxError{
- expected: "commemorated event",
- got: "empty string",
- linenr: linenr,
- file: file,
- }
- default:
- row.Name, line = line[:i], line[i+1:]
- }
-
- if len(line) != 0 {
- return Data{}, SyntaxError{
- expected: "end-of-line",
- got: line,
- linenr: linenr,
- file: file,
- }
- }
-
- for isBlankOrComment(line) {
- if !scanner.Scan() {
- return Data{}, SyntaxError{
- expected: "mintage row",
- got: "end-of-file",
- linenr: linenr,
- file: file,
- }
- }
- line = strings.Trim(scanner.Text(), ws)
- linenr++
- }
-
- tokens := strings.FieldsFunc(line, func(r rune) bool {
- return strings.ContainsRune(ws, r)
- })
- if tokcnt := len(tokens); tokcnt != typeCount {
- word := "entries"
- if tokcnt == 1 {
- word = "entry"
- }
- return Data{}, SyntaxError{
- expected: fmt.Sprintf("%d mintage entries", typeCount),
- got: fmt.Sprintf("%d %s", tokcnt, word),
- linenr: linenr,
- file: file,
- }
- }
-
- for i, tok := range tokens {
- if tok == "?" {
- row.Mintage[i] = Unknown
- } else {
- row.Mintage[i] = atoiWithDots(tok)
- }
- }
-
- data.Commemorative = append(data.Commemorative, row)
- }
- }
-
- return data, nil
-}
-
-func isNumeric(s string, dot bool) bool {
- for _, ch := range s {
- switch ch {
- case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
- default:
- if ch != '.' || !dot {
- return false
- }
- }
- }
- return true
-}
-
-func atoiWithDots(s string) int {
- n := 0
- for _, ch := range s {
- if ch == '.' {
- continue
- }
- n = n*10 + int(ch) - '0'
- }
- return n
-}
-
-func isBlankOrComment(s string) bool {
- return len(s) == 0 || s[0] == '#'
-}
diff --git a/lib/mintage/parser_test.go b/lib/mintage/parser_test.go
deleted file mode 100644
index 76e0f01..0000000
--- a/lib/mintage/parser_test.go
+++ /dev/null
@@ -1,233 +0,0 @@
-package mintage
-
-import (
- "bytes"
- "errors"
- "testing"
-)
-
-func TestParserComplete(t *testing.T) {
- data, err := Parse(bytes.NewBuffer([]byte(`
- 2020
- 1000 1001 1002 1003 1004 1005 1006 1007
- 1100 1101 1102 1103 1104 1105 1106 1107
- 1200 1201 1202 1203 1204 1205 1206 1207
- 2021-KNM
- 2.000 ? 2002 2003 2004 2005 2006 2007
- 2.100 ? 2102 2103 2104 2105 2106 2107
- 2.200 ? 2202 2203 2204 2205 2206 2207
- 2021-MdP
- 3000 3001 3002 3003 3004 3005 3006 3007
- 3100 3101 3102 3103 3104 3105 3106 3107
- 3200 3201 3202 3203 3204 3205 3206 3207
- 2022
- 4000 4001 4.002 4003 4004 4005 4006 4007
- 4100 4101 4.102 4103 4104 4105 4106 4107
- 4200 4201 4.202 4203 4204 4205 4206 4207
-
- 2009 "10th Anniversary of Economic and Monetary Union"
- 1000 2000 3000
- 2022-⋆ "35th Anniversary of the Erasmus Programme"
- 1001 ? 3001
- `)), "-")
-
- if err != nil {
- t.Fatalf(`Expected err=nil; got "%s"`, err)
- }
-
- for i, row := range data.Standard {
- for k := TypeCirc; k <= TypeProof; k++ {
- for j, col := range row.Mintages[k] {
- n := 1000*(i+1) + 100*k + j
- if i == 1 && j == 1 {
- n = Unknown
- }
- if col != n {
- t.Fatalf("Expected data.Standard[%d].Mintages[%d][%d]=%d; got %d",
- i, k, j, col, n)
- }
- }
- }
- }
-
- for i, row := range data.Commemorative {
- for k := TypeCirc; k <= TypeProof; k++ {
- n := 1000*(k+1) + i
- if i == 1 && k == 1 {
- n = Unknown
- }
- if row.Mintage[k] != n {
- t.Fatalf("Expected row.Mintage[%d]=%d; got %d",
- k, n, row.Mintage[k])
- }
- }
- }
-
- if len(data.Standard) != 4 {
- t.Fatalf("Expected len(data.Standard)=2; got %d", len(data.Standard))
- }
- if len(data.Commemorative) != 2 {
- t.Fatalf("Expected len(data.Commemorative)=2; got %d", len(data.Commemorative))
- }
-
- for i, x := range [...]struct {
- year int
- mintmark, name string
- }{
- {2009, "", "10th Anniversary of Economic and Monetary Union"},
- {2022, "⋆", "35th Anniversary of the Erasmus Programme"},
- } {
- if data.Commemorative[i].Year != x.year {
- t.Fatalf("Expected data.Commemorative[%d].Year=%d; got %d",
- i, x.year, data.Commemorative[i].Year)
- }
- if data.Commemorative[i].Mintmark != x.mintmark {
- t.Fatalf(`Expected data.Commemorative[%d].Mintmark="%s"; got "%s"`,
- i, x.mintmark, data.Commemorative[i].Mintmark)
- }
- if data.Commemorative[i].Name != x.name {
- t.Fatalf(`Expected data.Commemorative[%d].Name="%s"; got "%s"`,
- i, x.name, data.Commemorative[i].Name)
- }
- }
-}
-
-func TestParserMintmarks(t *testing.T) {
- data, err := Parse(bytes.NewBuffer([]byte(`
- 2020
- 1000 1001 1002 1003 1004 1005 1006 1007
- 1100 1101 1102 1103 1104 1105 1106 1107
- 1200 1201 1202 1203 1204 1205 1206 1207
- 2021-KNM
- 2.000 ? 2002 2003 2004 2005 2006 2007
- 2.100 ? 2102 2103 2104 2105 2106 2107
- 2.200 ? 2202 2203 2204 2205 2206 2207
- 2021-MdP
- 3000 3001 3002 3003 3004 3005 3006 3007
- 3100 3101 3102 3103 3104 3105 3106 3107
- 3200 3201 3202 3203 3204 3205 3206 3207
- 2022
- 4000 4001 4.002 4003 4004 4005 4006 4007
- 4100 4101 4.102 4103 4104 4105 4106 4107
- 4200 4201 4.202 4203 4204 4205 4206 4207
- `)), "-")
-
- if err != nil {
- t.Fatalf(`Expected err=nil; got "%s"`, err)
- }
-
- for i, row := range data.Standard {
- for j, col := range row.Mintages[TypeCirc] {
- n := 1000*(i+1) + j
- if i == 1 && j == 1 {
- n = Unknown
- }
- if col != n {
- t.Fatalf("Expected data.Standard[%d].Mintages[TypeCirc][%d]=%d; got %d",
- i, j, col, n)
- }
- }
- }
-
- for i, y := range [...]int{2020, 2021, 2021, 2022} {
- if data.Standard[i].Year != y {
- t.Fatalf("Expected data.Standard[%d].Year=%d; got %d",
- i, y, data.Standard[i].Year)
- }
- }
-
- for i, m := range [...]string{"", "KNM", "MdP", ""} {
- if data.Standard[i].Mintmark != m {
- t.Fatalf(`Expected data.Standard[%d].Mintmark="%s"; got "%s"`,
- i, m, data.Standard[i].Mintmark)
- }
- }
-}
-
-func TestParserNoYear(t *testing.T) {
- _, err := Parse(bytes.NewBuffer([]byte(`
- 1.000 1001 1002 1003 1004 1005 1006 1007
- 1.100 1101 1102 1103 1104 1105 1106 1107
- 1.200 1201 1202 1203 1204 1205 1206 1207
- 2021
- 2000 ? 2002 2003 2004 2005 2006 2007
- 2100 ? 2102 2103 2104 2105 2106 2107
- 2200 ? 2202 2203 2204 2205 2206 2207
- `)), "-")
-
- var sErr SyntaxError
- if !errors.As(err, &sErr) {
- t.Fatalf("Expected err=SyntaxError; got %s", err)
- }
-}
-
-func TestParserBadToken(t *testing.T) {
- _, err := Parse(bytes.NewBuffer([]byte(`
- 2020
- 1.000 1001 1002 1003 1004 1005 1006 1007
- 1.100 1101 1102 1103 1104 1105 1106 1107
- 1.200 1201 1202 1203 1204 1205 1206 1207
- 2021 Naughty!
- 2000 ? 2002 2003 2004 2005 2006 2007
- 2100 ? 2102 2103 2104 2105 2106 2107
- 2200 ? 2202 2203 2204 2205 2206 2207
- `)), "-")
-
- var sErr SyntaxError
- if !errors.As(err, &sErr) {
- t.Fatalf("Expected err=SyntaxError; got %s", err)
- }
-}
-
-func TestParserShortRow(t *testing.T) {
- _, err := Parse(bytes.NewBuffer([]byte(`
- 2020
- 1.000 1001 1002 1003 1004 1005 1006 1007
- 1.100 1101 1102 1103 1104 1105 1106 1107
- 1.200 1201 1202 1203 1204 1205 1206 1207
- 2021
- 2000 ? 2002 2003 2004 2005 2006 2007
- 2100 ? 2102 2103 2104 2105 2106
- 2200 ? 2202 2203 2204 2205 2206 2207
- `)), "-")
-
- var sErr SyntaxError
- if !errors.As(err, &sErr) {
- t.Fatalf("Expected err=SyntaxError; got %s", err)
- }
-}
-
-func TestParserLongRow(t *testing.T) {
- _, err := Parse(bytes.NewBuffer([]byte(`
- 2020
- 1.000 1001 1002 1003 1004 1005 1006 1007
- 1.100 1101 1102 1103 1104 1105 1106 1107
- 1.200 1201 1202 1203 1204 1205 1206 1207
- 2021
- 2000 ? 2002 2003 2004 2005 2006 2007
- 2100 ? 2102 2103 2104 2105 2106 2107 2108
- 2200 ? 2202 2203 2204 2205 2206 2207
- `)), "-")
-
- var sErr SyntaxError
- if !errors.As(err, &sErr) {
- t.Fatalf("Expected err=SyntaxError; got %s", err)
- }
-}
-
-func TestParserMissingRow(t *testing.T) {
- _, err := Parse(bytes.NewBuffer([]byte(`
- 2020
- 1.000 1001 1002 1003 1004 1005 1006 1007
- 1.100 1101 1102 1103 1104 1105 1106 1107
- 1.200 1201 1202 1203 1204 1205 1206 1207
- 2021
- 2000 ? 2002 2003 2004 2005 2006 2007
- 2200 ? 2202 2203 2204 2205 2206 2207
- `)), "-")
-
- var sErr SyntaxError
- if !errors.As(err, &sErr) {
- t.Fatalf("Expected err=SyntaxError; got %s", err)
- }
-}