Sync
This commit is contained in:
@@ -66,6 +66,12 @@ function indices(t)
|
|||||||
return indices
|
return indices
|
||||||
end
|
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
|
-- Ensures a table has a metatable
|
||||||
function ensure_metatable(t)
|
function ensure_metatable(t)
|
||||||
local meta = getmetatable(t)
|
local meta = getmetatable(t)
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
out "huh?";
|
// single line comment
|
||||||
// proto:
|
log "a";
|
||||||
(FUCK!)
|
/*
|
||||||
|
multi
|
||||||
|
line
|
||||||
|
comment
|
||||||
|
*/
|
||||||
|
log "b";
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
local path = ...
|
local path = ...
|
||||||
require("nellie.proto")
|
require("nellie.proto")
|
||||||
|
|
||||||
function Run(args)
|
function Run(...)
|
||||||
-- Take arguments as neli files to read and interpret
|
-- Take arguments as neli files to read and interpret
|
||||||
local root = Chain(
|
local root = Chain(
|
||||||
string.format(
|
string.format(
|
||||||
"in cmd 'nelli {%s}'",
|
"in cmd 'nelli {%s}'",
|
||||||
table.concat(args,";")
|
table.concat({...},";")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
for _,parameter in pairs(args) do
|
for _,parameter in pairs({...}) do
|
||||||
local chain = Chain(
|
local chain = Chain(
|
||||||
string.format("in 'call: root' @'%s'",parameter)
|
string.format("in 'call: root' @'%s'",parameter)
|
||||||
):from(root)
|
):from(root)
|
||||||
|
|||||||
@@ -339,9 +339,6 @@ function Scope:run(expression,chain,original)
|
|||||||
)
|
)
|
||||||
,2)
|
,2)
|
||||||
else
|
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
|
if not binding then error("No binding") end -- todo: improve error
|
||||||
return binding:call(
|
return binding:call(
|
||||||
original,
|
original,
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ end
|
|||||||
-- From a table of actions of patterns,
|
-- From a table of actions of patterns,
|
||||||
-- consume the earliest pattern (index)
|
-- consume the earliest pattern (index)
|
||||||
-- and call the value
|
-- and call the value
|
||||||
|
local NONE = {}
|
||||||
function Consumer:consumePatterns(patterns,state)
|
function Consumer:consumePatterns(patterns,state)
|
||||||
-- t: {string = function...}
|
-- t: {string = function...}
|
||||||
assert_type("table")(patterns,"Arg 't' #1: %s")
|
assert_type("table")(patterns,"Arg 't' #1: %s")
|
||||||
@@ -84,31 +85,37 @@ function Consumer:consumePatterns(patterns,state)
|
|||||||
end
|
end
|
||||||
local origin = self.range.first or 1
|
local origin = self.range.first or 1
|
||||||
-- Get the next earliest match
|
-- 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
|
for pattern,new_func in pairs(patterns) do
|
||||||
local new_index,new_final = self.range:find(pattern)
|
local new_index,new_final = self.range:find(pattern)
|
||||||
if new_index and
|
if new_index and
|
||||||
((not findex) or (findex > new_index))
|
((not earliest.index) or (earliest.index > new_index))
|
||||||
then
|
then
|
||||||
if not new_index then return end
|
if not new_index then return end -- (later:) what why?
|
||||||
findex = new_index
|
earliest.index = new_index
|
||||||
ffinal = new_final
|
earliest.final = new_final
|
||||||
fpattern = pattern
|
earliest.pattern = pattern
|
||||||
ffunc = new_func
|
callback = new_func
|
||||||
fexcess = self.range.reader:get(
|
earliest.excess = self.range.reader:get(
|
||||||
self.range.first or 1,
|
self.range.first or 1,
|
||||||
new_final - 1
|
earliest.index - 1
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- Pass into the func
|
-- Pass into the func
|
||||||
if not ffunc then
|
if not callback then
|
||||||
|
if patterns[NONE] then
|
||||||
|
return patterns[NONE]()
|
||||||
|
end
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
assert(findex) assert(ffinal)
|
assert(earliest.index) assert(earliest.final)
|
||||||
self.range:move(ffinal+1) -- Move range to after the match
|
self.range:move(earliest.final+1) -- Move range to after the match
|
||||||
local fmatch = self.range.reader:match(fpattern,findex)
|
local fmatch = self.range.reader:match(earliest.pattern,earliest.final)
|
||||||
-- Pass back consumed result to
|
|
||||||
|
-- This seems to be broken:
|
||||||
local sum = self.range.reader:get(origin+1,self.range.first)
|
local sum = self.range.reader:get(origin+1,self.range.first)
|
||||||
:gsub("\r\n","\n")
|
:gsub("\r\n","\n")
|
||||||
:gsub("\r","\n")
|
:gsub("\r","\n")
|
||||||
@@ -120,7 +127,7 @@ function Consumer:consumePatterns(patterns,state)
|
|||||||
self.col = self.col + 1
|
self.col = self.col + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return ffunc(fexcess,fmatch,state)
|
return callback(earliest,state)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Interpret some text
|
-- Interpret some text
|
||||||
@@ -164,67 +171,119 @@ function Parse(content,uri,chain)
|
|||||||
patterns.uriClose = ">"
|
patterns.uriClose = ">"
|
||||||
patterns.singleLineComment = "//"
|
patterns.singleLineComment = "//"
|
||||||
patterns.multiLineCommentOpen = "/%*"
|
patterns.multiLineCommentOpen = "/%*"
|
||||||
patterns.multiLineCommentOpen = "%*/"
|
patterns.multiLineCommentClose = "%*/"
|
||||||
patterns.colonSyntax = ":"
|
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 -__-
|
-- Give me: {patterns that take (match,state)}, the state, and a handler for comments
|
||||||
local expressionMeals = {
|
-- I will give you a function that will return the result of consumePatterns(patterns)
|
||||||
[patterns.singleLineString] = function(words,_,current)
|
-- With escapes handled.
|
||||||
current:insert(words,consumer:consumePatterns({
|
local function makeConsumerEscaping(patterns,state,handler)
|
||||||
[patterns.singleLineString] = function(words,_)
|
return function()
|
||||||
return expression({"text",Expression({words})})
|
handler = handler or function() end
|
||||||
end
|
local escaped = true
|
||||||
}))
|
local function escape() escaped = true end
|
||||||
end,
|
while escaped do
|
||||||
[patterns.named] = function(words,_,current)
|
escaped = false
|
||||||
current:insert(words,consumer:consumePatterns({
|
consumer:consumePatterns(union({
|
||||||
[patterns.named] = function(words,_)
|
[patterns.singleLineComment] = function(...)
|
||||||
return expression({"the",Expression({words})})
|
handler(...)
|
||||||
end
|
consumer:consumePatterns({
|
||||||
}))
|
[patterns.newLine] = escape
|
||||||
end,
|
})
|
||||||
[patterns.multiLineStringOpen] = function(words,_,current)
|
end,
|
||||||
current:insert(words,consumer:consumePatterns({
|
[patterns.multiLineCommentOpen] = function(...)
|
||||||
["[\n\r]"] = function()
|
handler(...)
|
||||||
error("Incomplete string literal")
|
consumer:consumePatterns({
|
||||||
end,
|
[NONE] = error,
|
||||||
[patterns.multiLineStringClose] = function(words,_)
|
[patterns.multiLineCommentClose] = escape
|
||||||
return expression({"text",Expression({words})})
|
})
|
||||||
end
|
end,
|
||||||
}))
|
},patterns),state)
|
||||||
end,
|
end
|
||||||
[patterns.uriOpen] = function(words,_,current)
|
end
|
||||||
current:insert(words,consumer:consumePatterns({
|
end
|
||||||
["[\n\r]"] = function()
|
-- Give me {patterns that take (match,current)} and current (expression)
|
||||||
current:error("Incomplete URI literal")
|
local function makeConsumerAppending(patterns,state)
|
||||||
end,
|
local appendingPatterns = map(patterns,function(func)
|
||||||
[patterns.uriClose] = function(path)
|
return function(match,current)
|
||||||
return read(path)
|
current:insert(match.excess,func(match,current))
|
||||||
end
|
end
|
||||||
}))
|
end)
|
||||||
end,
|
makeConsumerEscaping(appendingPatterns,function(match,current)
|
||||||
[patterns.expressionOpen] = function(words,_,current)
|
current:insert(match.excess)
|
||||||
current:insert(words,consumeExpression())
|
end)
|
||||||
end,
|
end
|
||||||
[patterns.singleLineComment] = function(words,_,current)
|
local function makeConsumerExpressive()
|
||||||
--current:insert(words) -- Consume what was left
|
local function consumeSingleLineString()
|
||||||
consumer:consumePatterns({
|
return
|
||||||
[patterns.newLine] = function() end
|
end
|
||||||
})
|
local function consumeNamed()
|
||||||
end,
|
|
||||||
[patterns.multiLineCommentOpen] = function(words,_,current)
|
end
|
||||||
current:insert(words)
|
local function consumeMultiLineString()
|
||||||
consumer:consumePatterns({
|
|
||||||
[patterns.multiLineCommentClose] = function() end
|
end
|
||||||
})
|
local function consumeURI()
|
||||||
end,
|
|
||||||
[patterns.colonSyntax] = function(words,_,current)
|
end
|
||||||
current:insert(words,consumeExpression())
|
return makeConsumerAppending({
|
||||||
end,
|
[patterns.singleLineString] = function(match,current)
|
||||||
[patterns.blockOpen] = function(words,_,current)
|
return consumer:consumePatterns({
|
||||||
current:insert(words,consumeBlock())
|
["[\n\r]"] = function()
|
||||||
end,
|
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
|
-- Consume a {} block of code
|
||||||
function consumeBlock(closing_pattern)
|
function consumeBlock(closing_pattern)
|
||||||
closing_pattern = closing_pattern or patterns.blockClose
|
closing_pattern = closing_pattern or patterns.blockClose
|
||||||
@@ -233,7 +292,7 @@ function Parse(content,uri,chain)
|
|||||||
local loop = true
|
local loop = true
|
||||||
while loop do
|
while loop do
|
||||||
local remaining = consumer:remaining()
|
local remaining = consumer:remaining()
|
||||||
local expr = consumer:consumePatterns(union(expressionMeals,{
|
local expr = consumePatternsEscaping(union(expressionMeals,{
|
||||||
[patterns.blockDelimiter] = function(words,_)
|
[patterns.blockDelimiter] = function(words,_)
|
||||||
current:insert(words)
|
current:insert(words)
|
||||||
if current:empty() then
|
if current:empty() then
|
||||||
@@ -261,7 +320,7 @@ function Parse(content,uri,chain)
|
|||||||
local loop = true
|
local loop = true
|
||||||
while loop do
|
while loop do
|
||||||
local remaining = consumer:remaining()
|
local remaining = consumer:remaining()
|
||||||
local expr = consumer:consumePatterns(union(expressionMeals,{
|
local expr = consumePatternsEscaping(union(expressionMeals,{
|
||||||
[patterns.expressionClose] = function(words,_,_current)
|
[patterns.expressionClose] = function(words,_,_current)
|
||||||
current:insert(words)
|
current:insert(words)
|
||||||
loop = false
|
loop = false
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
require("nellie.parser")
|
require("nellie.parser")
|
||||||
|
|
||||||
function Bind(scope,abstract,callback)
|
function Bind(scope,abstract,callback)
|
||||||
for _,expression in pairs(Parse(abstract)) do
|
for _,expression in pairs(Parse(abstract).items) do
|
||||||
assert_meta(Expression)(expression)
|
assert_meta(Expression)(expression)
|
||||||
scope:insert(Binding(
|
scope:insert(Binding(
|
||||||
expression,
|
expression,
|
||||||
@@ -21,7 +21,7 @@ end
|
|||||||
function Do(scope,expression,chain,name)
|
function Do(scope,expression,chain,name)
|
||||||
local latest
|
local latest
|
||||||
for index,item in pairs(expression.items) do
|
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
|
end
|
||||||
return latest
|
return latest
|
||||||
end
|
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,"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,"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,"this scope",function(s,e,c) return s end)
|
||||||
Bind(ns,"new scope",function(s,e,c) return Scope() end) -- TODO: chains?!!?
|
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,"index (table) with (key)",function(s,e,c) return Run(s,e,c,"") end)
|
||||||
Bind(ns,[[
|
Bind(ns,[[
|
||||||
(input) means do (output);
|
(input) means (output);
|
||||||
(input) in (input_scope) means do (output);
|
(input) in (input_scope) means (output);
|
||||||
(input) means do (output) in (output_scope);
|
(input) means do (output) in (output_scope);
|
||||||
(input) in (input_scope) means do (output) in (output_scope)
|
(input) in (input_scope) means (output) in (output_scope)
|
||||||
]],function(s,e,c1) -- A substitution
|
]],function(s1,e1,c1) -- A substitution
|
||||||
local input_scope = s
|
local input_scope = s1
|
||||||
if e.input_scope then input_scope = Run(s,e.input_scope,c1,"means: input scope") end
|
if e1.input_scope then input_scope = Run(s1,e1.input_scope,c1,"means: input scope") end
|
||||||
local output_scope = s
|
local output_scope = s1
|
||||||
if e.output_scope then output_scope = Run(s,e.output_scope,c2,"means: output scope") end
|
if e1.output_scope then output_scope = Run(s1,e1.output_scope,c1,"means: output scope") end
|
||||||
Bind(e.input_scope,e.input,function(s,e,c2)
|
Bind(input_scope,e1.input,function(s2,e2,c2)
|
||||||
return Do(e.output_scope,e.output,c2) -- TODO: chains?!
|
return Do(output_scope,e1.output,c2) -- TODO: chains?!
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
Bind(ns,"do (stuff) in (scope); do (stuff)",function(s,e,c)
|
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 Hpath = "nellie/helper.nel"
|
||||||
local Hchain = Chain("in internal: "..Hpath)
|
local Hchain = Chain("in internal: "..Hpath)
|
||||||
local success,result = Hchain:call(function(chain)
|
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)
|
end)
|
||||||
|
|
||||||
--[[ Documentation:
|
--[[ Documentation:
|
||||||
|
|||||||
2
run.sh
2
run.sh
@@ -4,5 +4,5 @@ then
|
|||||||
echo "lua could not be found"
|
echo "lua could not be found"
|
||||||
exit 1
|
exit 1
|
||||||
else
|
else
|
||||||
lua -i -v -W -l nellie -e Run "$@"
|
lua -l nellie -e "Run'$@'"
|
||||||
fi
|
fi
|
||||||
@@ -3,3 +3,7 @@ local function test(file,result)
|
|||||||
|
|
||||||
end
|
end
|
||||||
test("print.nel",[[hello world!]])
|
test("print.nel",[[hello world!]])
|
||||||
|
|
||||||
|
do
|
||||||
|
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user