Sync
This commit is contained in:
@@ -72,6 +72,7 @@ end
|
||||
-- From a table of actions of patterns,
|
||||
-- consume the earliest pattern (index)
|
||||
-- and call the value
|
||||
local NONE = {}
|
||||
function Consumer:consumePatterns(patterns,state)
|
||||
-- t: {string = function...}
|
||||
assert_type("table")(patterns,"Arg 't' #1: %s")
|
||||
@@ -84,31 +85,37 @@ function Consumer:consumePatterns(patterns,state)
|
||||
end
|
||||
local origin = self.range.first or 1
|
||||
-- Get the next earliest match
|
||||
local findex,ffinal,fpattern,ffunc,fexcess -- TODO: make this not be a bunch of locals. New class?
|
||||
local callback = nil
|
||||
local earliest = {}
|
||||
--local findex,ffinal,fpattern,ffunc,fexcess -- TODO: make this not be a bunch of locals. New class?
|
||||
for pattern,new_func in pairs(patterns) do
|
||||
local new_index,new_final = self.range:find(pattern)
|
||||
if new_index and
|
||||
((not findex) or (findex > new_index))
|
||||
((not earliest.index) or (earliest.index > new_index))
|
||||
then
|
||||
if not new_index then return end
|
||||
findex = new_index
|
||||
ffinal = new_final
|
||||
fpattern = pattern
|
||||
ffunc = new_func
|
||||
fexcess = self.range.reader:get(
|
||||
if not new_index then return end -- (later:) what why?
|
||||
earliest.index = new_index
|
||||
earliest.final = new_final
|
||||
earliest.pattern = pattern
|
||||
callback = new_func
|
||||
earliest.excess = self.range.reader:get(
|
||||
self.range.first or 1,
|
||||
new_final - 1
|
||||
earliest.index - 1
|
||||
)
|
||||
end
|
||||
end
|
||||
-- Pass into the func
|
||||
if not ffunc then
|
||||
if not callback then
|
||||
if patterns[NONE] then
|
||||
return patterns[NONE]()
|
||||
end
|
||||
return nil
|
||||
end
|
||||
assert(findex) assert(ffinal)
|
||||
self.range:move(ffinal+1) -- Move range to after the match
|
||||
local fmatch = self.range.reader:match(fpattern,findex)
|
||||
-- Pass back consumed result to
|
||||
assert(earliest.index) assert(earliest.final)
|
||||
self.range:move(earliest.final+1) -- Move range to after the match
|
||||
local fmatch = self.range.reader:match(earliest.pattern,earliest.final)
|
||||
|
||||
-- This seems to be broken:
|
||||
local sum = self.range.reader:get(origin+1,self.range.first)
|
||||
:gsub("\r\n","\n")
|
||||
:gsub("\r","\n")
|
||||
@@ -120,7 +127,7 @@ function Consumer:consumePatterns(patterns,state)
|
||||
self.col = self.col + 1
|
||||
end
|
||||
end
|
||||
return ffunc(fexcess,fmatch,state)
|
||||
return callback(earliest,state)
|
||||
end
|
||||
|
||||
-- Interpret some text
|
||||
@@ -164,67 +171,119 @@ function Parse(content,uri,chain)
|
||||
patterns.uriClose = ">"
|
||||
patterns.singleLineComment = "//"
|
||||
patterns.multiLineCommentOpen = "/%*"
|
||||
patterns.multiLineCommentOpen = "%*/"
|
||||
patterns.multiLineCommentClose = "%*/"
|
||||
patterns.colonSyntax = ":"
|
||||
-- TODO: I don't like that this structure does: open(stuff;close) instead of open(stuff)close
|
||||
-- TODO: current:insert() is repeated in EVERY meal. I wonder if this should be fixed -__-
|
||||
local expressionMeals = {
|
||||
[patterns.singleLineString] = function(words,_,current)
|
||||
current:insert(words,consumer:consumePatterns({
|
||||
[patterns.singleLineString] = function(words,_)
|
||||
return expression({"text",Expression({words})})
|
||||
end
|
||||
}))
|
||||
end,
|
||||
[patterns.named] = function(words,_,current)
|
||||
current:insert(words,consumer:consumePatterns({
|
||||
[patterns.named] = function(words,_)
|
||||
return expression({"the",Expression({words})})
|
||||
end
|
||||
}))
|
||||
end,
|
||||
[patterns.multiLineStringOpen] = function(words,_,current)
|
||||
current:insert(words,consumer:consumePatterns({
|
||||
["[\n\r]"] = function()
|
||||
error("Incomplete string literal")
|
||||
end,
|
||||
[patterns.multiLineStringClose] = function(words,_)
|
||||
return expression({"text",Expression({words})})
|
||||
end
|
||||
}))
|
||||
end,
|
||||
[patterns.uriOpen] = function(words,_,current)
|
||||
current:insert(words,consumer:consumePatterns({
|
||||
["[\n\r]"] = function()
|
||||
current:error("Incomplete URI literal")
|
||||
end,
|
||||
[patterns.uriClose] = function(path)
|
||||
return read(path)
|
||||
end
|
||||
}))
|
||||
end,
|
||||
[patterns.expressionOpen] = function(words,_,current)
|
||||
current:insert(words,consumeExpression())
|
||||
end,
|
||||
[patterns.singleLineComment] = function(words,_,current)
|
||||
--current:insert(words) -- Consume what was left
|
||||
consumer:consumePatterns({
|
||||
[patterns.newLine] = function() end
|
||||
})
|
||||
end,
|
||||
[patterns.multiLineCommentOpen] = function(words,_,current)
|
||||
current:insert(words)
|
||||
consumer:consumePatterns({
|
||||
[patterns.multiLineCommentClose] = function() end
|
||||
})
|
||||
end,
|
||||
[patterns.colonSyntax] = function(words,_,current)
|
||||
current:insert(words,consumeExpression())
|
||||
end,
|
||||
[patterns.blockOpen] = function(words,_,current)
|
||||
current:insert(words,consumeBlock())
|
||||
end,
|
||||
}
|
||||
|
||||
-- Give me: {patterns that take (match,state)}, the state, and a handler for comments
|
||||
-- I will give you a function that will return the result of consumePatterns(patterns)
|
||||
-- With escapes handled.
|
||||
local function makeConsumerEscaping(patterns,state,handler)
|
||||
return function()
|
||||
handler = handler or function() end
|
||||
local escaped = true
|
||||
local function escape() escaped = true end
|
||||
while escaped do
|
||||
escaped = false
|
||||
consumer:consumePatterns(union({
|
||||
[patterns.singleLineComment] = function(...)
|
||||
handler(...)
|
||||
consumer:consumePatterns({
|
||||
[patterns.newLine] = escape
|
||||
})
|
||||
end,
|
||||
[patterns.multiLineCommentOpen] = function(...)
|
||||
handler(...)
|
||||
consumer:consumePatterns({
|
||||
[NONE] = error,
|
||||
[patterns.multiLineCommentClose] = escape
|
||||
})
|
||||
end,
|
||||
},patterns),state)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Give me {patterns that take (match,current)} and current (expression)
|
||||
local function makeConsumerAppending(patterns,state)
|
||||
local appendingPatterns = map(patterns,function(func)
|
||||
return function(match,current)
|
||||
current:insert(match.excess,func(match,current))
|
||||
end
|
||||
end)
|
||||
makeConsumerEscaping(appendingPatterns,function(match,current)
|
||||
current:insert(match.excess)
|
||||
end)
|
||||
end
|
||||
local function makeConsumerExpressive()
|
||||
local function consumeSingleLineString()
|
||||
return
|
||||
end
|
||||
local function consumeNamed()
|
||||
|
||||
end
|
||||
local function consumeMultiLineString()
|
||||
|
||||
end
|
||||
local function consumeURI()
|
||||
|
||||
end
|
||||
return makeConsumerAppending({
|
||||
[patterns.singleLineString] = function(match,current)
|
||||
return consumer:consumePatterns({
|
||||
["[\n\r]"] = function()
|
||||
error("Incomplete string literal")
|
||||
end,
|
||||
[patterns.singleLineString] = function(words,_)
|
||||
return expression({"text",Expression({words})})
|
||||
end
|
||||
})
|
||||
end,
|
||||
[patterns.named] = function(words,_,current)
|
||||
current:insert(words,consumePatternsEscaping({
|
||||
[patterns.named] = function(words,_)
|
||||
return expression({"the",Expression({words})})
|
||||
end
|
||||
}))
|
||||
end,
|
||||
[patterns.multiLineStringOpen] = function(match,current)
|
||||
return consumer:consumePatterns({
|
||||
[patterns.multiLineStringClose] = function(words,_)
|
||||
return expression({"text",Expression({words})})
|
||||
end
|
||||
})
|
||||
end,
|
||||
[patterns.multiLineStringOpen] = function(words,_,current)
|
||||
current:insert(words,consumePatternsEscaping({
|
||||
[patterns.multiLineStringClose] = function(words,_)
|
||||
return expression({"text",Expression({words})})
|
||||
end
|
||||
}))
|
||||
end,
|
||||
[patterns.uriOpen] = function(words,_,current)
|
||||
current:insert()
|
||||
current:insert(words,consumePatternsEscaping({
|
||||
["[\n\r]"] = function()
|
||||
current:error("Incomplete URI literal")
|
||||
end,
|
||||
[patterns.uriClose] = function(path)
|
||||
return read(path)
|
||||
end
|
||||
}))
|
||||
end,
|
||||
[patterns.expressionOpen] = function(match,current)
|
||||
return consumeExpression()
|
||||
end,
|
||||
[patterns.colonSyntax] = function(match,current)
|
||||
return consumeExpression()
|
||||
end,
|
||||
[patterns.blockOpen] = function(match,current)
|
||||
return consumeBlock()
|
||||
end,
|
||||
})
|
||||
end
|
||||
local function consumePatternsExpressive(patterns,current)
|
||||
|
||||
return consumePatternsEscaping
|
||||
end
|
||||
-- Consume a {} block of code
|
||||
function consumeBlock(closing_pattern)
|
||||
closing_pattern = closing_pattern or patterns.blockClose
|
||||
@@ -233,7 +292,7 @@ function Parse(content,uri,chain)
|
||||
local loop = true
|
||||
while loop do
|
||||
local remaining = consumer:remaining()
|
||||
local expr = consumer:consumePatterns(union(expressionMeals,{
|
||||
local expr = consumePatternsEscaping(union(expressionMeals,{
|
||||
[patterns.blockDelimiter] = function(words,_)
|
||||
current:insert(words)
|
||||
if current:empty() then
|
||||
@@ -261,7 +320,7 @@ function Parse(content,uri,chain)
|
||||
local loop = true
|
||||
while loop do
|
||||
local remaining = consumer:remaining()
|
||||
local expr = consumer:consumePatterns(union(expressionMeals,{
|
||||
local expr = consumePatternsEscaping(union(expressionMeals,{
|
||||
[patterns.expressionClose] = function(words,_,_current)
|
||||
current:insert(words)
|
||||
loop = false
|
||||
|
||||
Reference in New Issue
Block a user