mirror of
https://codeberg.org/scip/golsky.git
synced 2025-12-16 20:20:57 +01:00
101 lines
1.9 KiB
Go
101 lines
1.9 KiB
Go
|
|
// source: https://github.com/nhoffmann/life by N.Hoffmann 2020.
|
||
|
|
package rle
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"regexp"
|
||
|
|
"strconv"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
|
||
|
|
type RLE struct {
|
||
|
|
Rule string // rule
|
||
|
|
Width int // x
|
||
|
|
Height int // y
|
||
|
|
Pattern [][]int // The actual pattern
|
||
|
|
|
||
|
|
inputLines []string
|
||
|
|
headerLineIndex int
|
||
|
|
patternLineIndex int
|
||
|
|
}
|
||
|
|
|
||
|
|
func Parse(input string) (RLE, error) {
|
||
|
|
rle := RLE{
|
||
|
|
inputLines: strings.Split(input, "\n"),
|
||
|
|
}
|
||
|
|
|
||
|
|
rle.partitionFile()
|
||
|
|
|
||
|
|
err := rle.parseComments()
|
||
|
|
if err != nil {
|
||
|
|
return RLE{}, err
|
||
|
|
}
|
||
|
|
err = rle.parseHeader()
|
||
|
|
if err != nil {
|
||
|
|
return RLE{}, err
|
||
|
|
}
|
||
|
|
err = rle.parsePattern()
|
||
|
|
if err != nil {
|
||
|
|
return RLE{}, err
|
||
|
|
}
|
||
|
|
|
||
|
|
return rle, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (rle *RLE) partitionFile() error {
|
||
|
|
for index, line := range rle.inputLines {
|
||
|
|
cleanLine := removeWhitespace(line)
|
||
|
|
if strings.HasPrefix(cleanLine, "x=") {
|
||
|
|
rle.headerLineIndex = index
|
||
|
|
rle.patternLineIndex = index + 1
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return fmt.Errorf("Invlaid input: Header is missing")
|
||
|
|
}
|
||
|
|
|
||
|
|
func (rle *RLE) parseComments() error {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (rle *RLE) parseHeader() (err error) {
|
||
|
|
headerLine := removeWhitespace(rle.inputLines[rle.headerLineIndex])
|
||
|
|
|
||
|
|
headerElements := strings.SplitN(headerLine, ",", 3)
|
||
|
|
|
||
|
|
rle.Width, err = strconv.Atoi(strings.TrimPrefix(headerElements[0], "x="))
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
rle.Height, err = strconv.Atoi(strings.TrimPrefix(headerElements[1], "y="))
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
rle.Pattern = make([][]int, rle.Width)
|
||
|
|
|
||
|
|
// check wehter a rule is present, since it's optional
|
||
|
|
if len(headerElements) == 3 {
|
||
|
|
rle.Rule = strings.TrimPrefix(headerElements[2], "rule=")
|
||
|
|
}
|
||
|
|
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (rle *RLE) parsePattern() error {
|
||
|
|
patternString := strings.Join(rle.inputLines[rle.patternLineIndex:], "")
|
||
|
|
|
||
|
|
l := NewLexer(patternString)
|
||
|
|
pp := NewParser(l)
|
||
|
|
|
||
|
|
rle.Pattern = pp.ParsePattern(rle.Width, rle.Height)
|
||
|
|
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func removeWhitespace(input string) string {
|
||
|
|
re := regexp.MustCompile(` *\t*\r*\n*`)
|
||
|
|
return re.ReplaceAllString(input, "")
|
||
|
|
}
|