Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve parsing of empty nulls and lists of objects #18

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions samples/hie.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
return {
["cradle"] = {
["multi"] = {
[1] = {
["path"] = "./bazel-bin",
["config"] = {
["cradle"] = {}
}
},
[2] = {
["path"] = "./bazel-out",
["config"] = {
["cradle"] = {}
}
},
[3] = {
["path"] = "./bazel-testlogs",
["config"] = {
["cradle"] = {}
}
},
[4] = {
["path"] = "./bazel-yesod-bridge",
["config"] = {
["cradle"] = {}
}
},
[5] = {
["path"] = "./bazel-hls-bin",
["config"] = {
["cradle"] = {}
}
},
[6] = {
["path"] = "./bazel-hls-out",
["config"] = {
["cradle"] = {}
}
},
[7] = {
["path"] = "./bazel-hls-testlogs",
["config"] = {
["cradle"] = {}
}
},
[8] = {
["path"] = "./bazel-hls-yesod-bridge",
["config"] = {
["cradle"] = {}
}
},
[9] = {
["path"] = "./bridge-site",
["config"] = {
["cradle"] = {
["bios"] = {
["program"] = "./bridge-site/.hie-bios"
}
}
}
},
[10] = {
["path"] = "./cassandra-util",
["config"] = {
["cradle"] = {
["bios"] = {
["program"] = "./cassandra-util/.hie-bios"
}
}
}
},
[11] = {
["path"] = "./conduit-util",
["config"] = {
["cradle"] = {
["bios"] = {
["program"] = "./conduit-util/.hie-bios"
}
}
}
},
[12] = {
["path"] = "./hsx-util",
["config"] = {
["cradle"] = {
["bios"] = {
["program"] = "./hsx-util/.hie-bios"
}
}
}
},
[13] = {
["path"] = "./page",
["config"] = {
["cradle"] = {
["bios"] = {
["program"] = "./page/.hie-bios"
}
}
}
},
[14] = {
["path"] = "./wai-practice",
["config"] = {
["cradle"] = {
["bios"] = {
["program"] = "./wai-practice/.hie-bios"
}
}
}
},
[15] = {
["path"] = "./",
["config"] = {
["cradle"] = {}
}
}
}
}
}
68 changes: 68 additions & 0 deletions samples/hie.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
cradle:
multi:
- path: "./bazel-bin"
config:
cradle:
none:
- path: "./bazel-out"
config:
cradle:
none:
- path: "./bazel-testlogs"
config:
cradle:
none:
- path: "./bazel-yesod-bridge"
config:
cradle:
none:
- path: "./bazel-hls-bin"
config:
cradle:
none:
- path: "./bazel-hls-out"
config:
cradle:
none:
- path: "./bazel-hls-testlogs"
config:
cradle:
none:
- path: "./bazel-hls-yesod-bridge"
config:
cradle:
none:
- path: "./bridge-site"
config:
cradle:
bios:
program: "./bridge-site/.hie-bios"
- path: "./cassandra-util"
config:
cradle:
bios:
program: "./cassandra-util/.hie-bios"
- path: "./conduit-util"
config:
cradle:
bios:
program: "./conduit-util/.hie-bios"
- path: "./hsx-util"
config:
cradle:
bios:
program: "./hsx-util/.hie-bios"
- path: "./page"
config:
cradle:
bios:
program: "./page/.hie-bios"
- path: "./wai-practice"
config:
cradle:
bios:
program: "./wai-practice/.hie-bios"
- path: "./"
config:
cradle:
none:
13 changes: 13 additions & 0 deletions samples/null.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
return {
["empties"] = {
[1] = {},
[2] = {
["nonEmptyInitial"] = 7,
["nonEmptyFinal"] = 8,
},
[3] = {
["nonEmptyFinal"] = 9,
},
[4] = {
["nonEmptyInitial"] = 10,
}
},
["end"] = "test passed?",
["notnull"] = true,
["test"] = "A test for null values"
Expand Down
10 changes: 10 additions & 0 deletions samples/null.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@
thisis: null
thistoo: NULL
notnull: yes
empties:
- emptySolo:
- nonEmptyInitial: 7
emptyCentral:
nonEmptyFinal: 8
- emptyInitial:
nonEmptyFinal: 9
- nonEmptyInitial: 10
emptyFinal:
- emptyTerminal:
tildeis: ~
capitalized: Null
end: test passed?
105 changes: 96 additions & 9 deletions yaml.lua
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,10 @@ Parser.parse = function (self)
elseif c.token.const == true then
self:advanceValue();
result = c.token.value
-- handle the case where a label is followed by a dedent and should parse as
-- null
elseif c.token[1] == "dedent" then
result = nil
else
error("ParseError: unexpected token '" .. c.token[1] .. "'" .. context(c.token.input))
end
Expand Down Expand Up @@ -465,32 +469,109 @@ Parser.parseTextBlock = function (self, sep)
return result
end

Parser.parseHash = function (self, hash)
-- @param hash table|nil Table to populate with labels
-- @param listHash boolean True if this is a hash that occurs at the
-- start of a list
-- @return the fully parsed hash
Parser.parseHash = function (self, hash, listHash)
hash = hash or {}
local indents = 0
local acceptedImpliedIndent = false

if self:isInline() then
local id = self:advanceValue()
self:expect(":", "expected semi-colon after id")
self:expect(":", "expected colon after id")
self:ignoreSpace()
if self:accept("indent") then
if not listHash and self:accept("indent") then
indents = indents + 1
hash[id] = self:parse()
else
elseif not listHash then
hash[id] = self:parse()
if self:accept("indent") then
indents = indents + 1
end
else -- listHash == true
-- If there is another identifier *without* an indent, we have a case something like this:
--[[
listof:
- nonNullValue: 7
- nullValue:
scalarValue:
--]]
if self:peekType("id") then
hash[id] = nil
return
-- If the next token is another list item at the same indent level, then
-- parse this value as null.
--[[
listof:
- nullValue:
- nonNullValue: 7
--]]
elseif listHash and self:peekType("-") then
hash[id] = nil
return hash
-- if the next token is a single indent level and then an identifier
-- parse this key as null.
--[[
listof:
- nullValue:
nonNullValue: 7
--]]
elseif listHash and self:peekType("indent") and self:peekType("id", 2) then
self:advance()
acceptedImpliedIndent = true
indents = indents + 1
hash[id] = nil
-- if the next token is a single indent level and then something other
-- than an identifier, consume the indent, and then parse recursively.
-- Handles these cases among others
--[[
listof:
- nonNullValue:
subKey: 7
--]]
--[[
listof:
- keyedSubList:
- listItem: 1
--]]
elseif listHash and self:peekType("indent") then
self:advance()
acceptedImpliedIndent = true
indents = indents + 1
hash[id] = self:parse()
self:ignoreSpace();
-- if the next token is not an indent, and is not one of the above cases
-- we likely have something on the same line like this:
--[[
value: 7
--]]
else
hash[id] = self:parse()
self:ignoreSpace();
end
end
self:ignoreSpace();
end

-- Consume the implied indent if it wasn't already consumed above.
if listHash and not acceptedImpliedIndent and self:peekType("indent") then
self:advance()
indents = indents + 1
end

while self:peekType("id") do
local id = self:advanceValue()
self:expect(":","expected semi-colon after id")
self:expect(":","expected colon after id")
self:ignoreSpace()
hash[id] = self:parse()
self:ignoreSpace();
-- If the next token is another id at the same indent level, this key should
-- parse as null.
if self:peekType("id") then
hash[id] = nil
else
hash[id] = self:parse()
self:ignoreSpace();
end
end

while indents > 0 do
Expand Down Expand Up @@ -533,7 +614,13 @@ Parser.parseList = function (self)
local list = {}
while self:accept("-") do
self:ignoreSpace()
list[#list + 1] = self:parse()
-- Check for the case of a hash starting as a list item, and pass that on
-- to the parseHash function directly.
if self:peekType("id") then
list[#list + 1] = self:parseHash({}, true)
else
list[#list + 1] = self:parse()
end

self:ignoreSpace()
end
Expand Down