summaryrefslogtreecommitdiff
path: root/parsers/rle.lua
blob: cd10493ef6d7e76948cd567535d6d7c6ff794b1f (plain)
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
-- http://psoup.math.wisc.edu/mcell/ca_files_formats.html#RLE
local C, Cs, Ct, P, R, S, match = lpeg.C, lpeg.Cs, lpeg.Ct, lpeg.P, lpeg.R, lpeg.S, lpeg.match

local rows = {}
local coords = {}

local n_row = 1
rows[n_row] = ""

local eol = P"\n"
local hashmark = P"#"
local space = S" \t"
local whitespace = S(" \n\t")^0
local num = R"09"
local comma = P","
local exclam = P"!"
local equals = P"="
local dollar = P"$"
local state = S"bo"
--local sign = S("+-")^0 -- support negative grid values? not yet

local comment = hashmark * (1-eol)^0 * eol

local getx = space^0 * P"x" * space^0 * equals * space^0 * C(num^1) / function (x)
    coords.x = tonumber(x)
end
local gety = space^0 * P"y" * space^0 * equals * space^0 * C(num^1) / function (y) 
    coords.y = tonumber(y)
end
geometry = getx * comma * gety * (1-eol)^0 * eol

local function n_of_t (n, c)
    local tmp = ""
    if c == "o" then -- live
        c = "1"
    else -- dead
        c = "0"
    end

    for i=1, n, 1 do
        tmp = tmp .. c
    end
    return tmp
end

local cell = C(num^0) * C(state) / function (n, c)
    if n == "" then
        n = 1
    end

    if  n_of_t (tonumber(n), c) == nil then
        print("OVER HERE", n_row,n, c)
    end
    rows[n_row] = rows[n_row] .. n_of_t (tonumber(n), c)
end

local line = whitespace * (cell * whitespace)^0 * C(num^0) / function (empty) 

    if rows[n_row]:len() < coords.x then -- fill grid with dead cells
        rows[n_row] = rows[n_row] .. n_of_t( coords.x - rows[n_row]:len(), "0" ) 
    end
        
    if empty ~= "" then
        for n=1, tonumber(empty)-1, 1 do
            n_row = n_row + 1 
            rows[n_row] = n_of_t( coords.x, "0" )
        end
    end

    n_row = n_row + 1 

    if n_row <= coords.y then
        rows[n_row] = "" 
    end
end

local p_rle = comment^0 * geometry * line * (dollar * line)^0 * whitespace * exclam

local function parser(fname)
    local file = assert(io.open(fname, "r"), "Not a file: " .. fname)
    local data = file:read("*all")
    file:close()

    if p_rle:match(data) then
        if context then
            context.writestatus("simpleslides", "Sucessfully loaded frame from "..fname..".")
        end
        return rows
    else
        return false
    end
end

return parser