Skip to content

Instantly share code, notes, and snippets.

@CoderPuppy
Last active September 10, 2016 04:24
Show Gist options
  • Save CoderPuppy/e94177f90da67808d61b2cfdb639ff10 to your computer and use it in GitHub Desktop.
Save CoderPuppy/e94177f90da67808d61b2cfdb639ff10 to your computer and use it in GitHub Desktop.
local str = 'Test.wat#hi[a[1]=2] Child, Other'
local function clone(t, m)
m = m or {}
if m[t] then
return m[t]
elseif type(t) == 'table' then
local r = {}
m[t] = r
for k, v in pairs(t) do
r[clone(k, m)] = clone(v, m)
end
return r
else
return t
end
end
local Tag = {
type = nil;
id = nil;
classes = {};
constraints = {};
direct = false;
}
local query = {{clone(Tag)}}
while #str > 0 do
print(('%q'):format(str))
repeat
local opt = query[#query]
local tag = opt[#opt]
local id, rest = str:match '^#([^%[%.#%s,]+)(.*)'
if id then
if tag.id then error('duplicate id at: ' .. ('%q'):format(str)) end
tag.id, str = id, rest
break
end
local class, rest = str:match '^%.([^%[%.#%s,]+)(.*)'
if class then
tag.classes[#tag.classes + 1], str = class, rest
break
end
local typ, rest = str:match '^([^%[%.#%s,]+)(.*)'
if typ then
if tag.type then error('duplicate type at: ' .. ('%q'):format(str)) end
tag.type, str = typ, rest
break
end
local constraint, rest = str:match '^(%b[])(.*)'
if constraint then
tag.constraints[#tag.constraints + 1], str = constraint:sub(2, -2), rest
break
end
local rest = str:match '^%s*>%s*(.*)'
if rest then
str = rest
opt[#opt + 1] = clone(Tag)
opt[#opt].direct = true
break
end
local rest = str:match '^%s+(.+)'
if rest then
str = rest
opt[#opt + 1] = clone(Tag)
break
end
local rest = str:match '^%s*,%s*(.*)'
if rest then
str = rest
query[#query + 1] = {clone(Tag)}
break
end
error('unexpected at: ' .. ('%q'):format(str))
until true
end
print(require'pl.pretty'.write(query))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment