Sync
This commit is contained in:
@@ -66,6 +66,12 @@ function indices(t)
|
||||
return indices
|
||||
end
|
||||
|
||||
function map(t,func)
|
||||
for index,item in pairs(t) do
|
||||
t[index] = func(index,item)
|
||||
end
|
||||
end
|
||||
|
||||
-- Ensures a table has a metatable
|
||||
function ensure_metatable(t)
|
||||
local meta = getmetatable(t)
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
out "huh?";
|
||||
// proto:
|
||||
(FUCK!)
|
||||
// single line comment
|
||||
log "a";
|
||||
/*
|
||||
multi
|
||||
line
|
||||
comment
|
||||
*/
|
||||
log "b";
|
||||
@@ -1,15 +1,15 @@
|
||||
local path = ...
|
||||
require("nellie.proto")
|
||||
|
||||
function Run(args)
|
||||
function Run(...)
|
||||
-- Take arguments as neli files to read and interpret
|
||||
local root = Chain(
|
||||
string.format(
|
||||
"in cmd 'nelli {%s}'",
|
||||
table.concat(args,";")
|
||||
table.concat({...},";")
|
||||
)
|
||||
)
|
||||
for _,parameter in pairs(args) do
|
||||
for _,parameter in pairs({...}) do
|
||||
local chain = Chain(
|
||||
string.format("in 'call: root' @'%s'",parameter)
|
||||
):from(root)
|
||||
|
||||
@@ -339,9 +339,6 @@ function Scope:run(expression,chain,original)
|
||||
)
|
||||
,2)
|
||||
else
|
||||
for index,item in pairs(binds) do
|
||||
print("index:",index,"item:",item)
|
||||
end
|
||||
if not binding then error("No binding") end -- todo: improve error
|
||||
return binding:call(
|
||||
original,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
require("nellie.parser")
|
||||
|
||||
function Bind(scope,abstract,callback)
|
||||
for _,expression in pairs(Parse(abstract)) do
|
||||
for _,expression in pairs(Parse(abstract).items) do
|
||||
assert_meta(Expression)(expression)
|
||||
scope:insert(Binding(
|
||||
expression,
|
||||
@@ -21,7 +21,7 @@ end
|
||||
function Do(scope,expression,chain,name)
|
||||
local latest
|
||||
for index,item in pairs(expression.items) do
|
||||
latest = Run(scope,item,chain,"do: "+tostring(index))
|
||||
latest = Run(scope,item,chain,"do: "..tostring(index))
|
||||
end
|
||||
return latest
|
||||
end
|
||||
@@ -283,23 +283,24 @@ Bind(ns,"let ((named (name)) be (value))",function(s,e,c) end)
|
||||
Bind(ns,"new table",function(s,e,c) return {} end)
|
||||
]]
|
||||
|
||||
Bind(ns,"(closed)",function(s,e,c) return Run(s,e.closed,c,"(...)") end)
|
||||
Bind(ns,"text (text)",function(s,e,c) return e.text:text() end)
|
||||
Bind(ns,"(closed)",function(s,e,c) print(e.closed) return Run(s,e.closed,c,"(...)") end)
|
||||
Bind(ns,"log (text)",function(s,e,c) log(Run(s,e.text,c,"print: text")) end)
|
||||
Bind(ns,"this scope",function(s,e,c) return s end)
|
||||
Bind(ns,"new scope",function(s,e,c) return Scope() end) -- TODO: chains?!!?
|
||||
Bind(ns,"index (table) with (key)",function(s,e,c) return Run(s,e,c,"") end)
|
||||
Bind(ns,[[
|
||||
(input) means do (output);
|
||||
(input) in (input_scope) means do (output);
|
||||
(input) means (output);
|
||||
(input) in (input_scope) means (output);
|
||||
(input) means do (output) in (output_scope);
|
||||
(input) in (input_scope) means do (output) in (output_scope)
|
||||
]],function(s,e,c1) -- A substitution
|
||||
local input_scope = s
|
||||
if e.input_scope then input_scope = Run(s,e.input_scope,c1,"means: input scope") end
|
||||
local output_scope = s
|
||||
if e.output_scope then output_scope = Run(s,e.output_scope,c2,"means: output scope") end
|
||||
Bind(e.input_scope,e.input,function(s,e,c2)
|
||||
return Do(e.output_scope,e.output,c2) -- TODO: chains?!
|
||||
(input) in (input_scope) means (output) in (output_scope)
|
||||
]],function(s1,e1,c1) -- A substitution
|
||||
local input_scope = s1
|
||||
if e1.input_scope then input_scope = Run(s1,e1.input_scope,c1,"means: input scope") end
|
||||
local output_scope = s1
|
||||
if e1.output_scope then output_scope = Run(s1,e1.output_scope,c1,"means: output scope") end
|
||||
Bind(input_scope,e1.input,function(s2,e2,c2)
|
||||
return Do(output_scope,e1.output,c2) -- TODO: chains?!
|
||||
end)
|
||||
end)
|
||||
Bind(ns,"do (stuff) in (scope); do (stuff)",function(s,e,c)
|
||||
@@ -311,7 +312,8 @@ Bind(ns,"new table",function(s,e,c) return {} end)
|
||||
local Hpath = "nellie/helper.nel"
|
||||
local Hchain = Chain("in internal: "..Hpath)
|
||||
local success,result = Hchain:call(function(chain)
|
||||
Run(NelliScope,Parse(read(Hpath),Hpath,chain),chain)
|
||||
print(Parse(read(Hpath),Hpath,chain))
|
||||
Do(NelliScope,Parse(read(Hpath),Hpath,chain),chain)
|
||||
end)
|
||||
|
||||
--[[ Documentation:
|
||||
|
||||
Reference in New Issue
Block a user