mirror of
https://github.com/Reuh/anselme.git
synced 2025-10-28 09:09:31 +00:00
Add eventbuffer type
This commit is contained in:
parent
02d50fb79f
commit
721464218c
10 changed files with 211 additions and 121 deletions
11
anselme.lua
11
anselme.lua
|
|
@ -157,7 +157,7 @@ local interpreter_methods = {
|
||||||
r, e = eval(self.state, expr)
|
r, e = eval(self.state, expr)
|
||||||
end
|
end
|
||||||
if not r then coroutine.yield("error", e) end
|
if not r then coroutine.yield("error", e) end
|
||||||
if self.state.interpreter.event_buffer then -- flush final events
|
if self.state.interpreter.current_event then -- flush final events
|
||||||
local rf, re = run_line(self.state, { type = "flush_events" })
|
local rf, re = run_line(self.state, { type = "flush_events" })
|
||||||
if re then coroutine.yield("error", re) end
|
if re then coroutine.yield("error", re) end
|
||||||
if rf then r = rf end
|
if rf then r = rf end
|
||||||
|
|
@ -478,15 +478,14 @@ local vm_mt = {
|
||||||
coroutine = coroutine.create(function() return "return", interpreter:run(expr, namespace) end),
|
coroutine = coroutine.create(function() return "return", interpreter:run(expr, namespace) end),
|
||||||
-- status
|
-- status
|
||||||
running_line = nil,
|
running_line = nil,
|
||||||
-- events
|
|
||||||
event_type = nil,
|
|
||||||
event_buffer = nil,
|
|
||||||
-- choice event
|
-- choice event
|
||||||
choice_selected = nil,
|
choice_selected = nil,
|
||||||
-- skip next choices until next event change (to skip currently running choice block when resuming from a checkpoint)
|
-- skip next choices until next event change (to skip currently running choice block when resuming from a checkpoint)
|
||||||
skip_choices_until_flush = nil,
|
skip_choices_until_flush = nil,
|
||||||
-- captured events stack {[event type]=stack{fn, ...}, ...}
|
-- active event buffer stack
|
||||||
event_capture_stack = {},
|
event_buffer_stack = {},
|
||||||
|
-- current event waiting to be sent
|
||||||
|
current_event = nil,
|
||||||
-- interrupt
|
-- interrupt
|
||||||
interrupt = nil,
|
interrupt = nil,
|
||||||
-- tag stack
|
-- tag stack
|
||||||
|
|
|
||||||
|
|
@ -219,84 +219,95 @@ common = {
|
||||||
--- event buffer management
|
--- event buffer management
|
||||||
-- i.e. only for text and choice events
|
-- i.e. only for text and choice events
|
||||||
events = {
|
events = {
|
||||||
--- add a new element to the event buffer
|
--- add a new element to the last event in the current buffer
|
||||||
-- will flush if needed
|
-- will create new event if needed
|
||||||
-- returns true in case of success
|
|
||||||
-- returns nil, err in case of error
|
|
||||||
append = function(self, state, type, data)
|
append = function(self, state, type, data)
|
||||||
if state.interpreter.event_capture_stack[type] then
|
local buffer = self:current_buffer(state)
|
||||||
local r, e = state.interpreter.event_capture_stack[type][#state.interpreter.event_capture_stack[type]](data)
|
local last = buffer[#buffer]
|
||||||
if not r then return r, e end
|
if not last or last.type ~= type then
|
||||||
else
|
last = { type = type }
|
||||||
local r, e = self:make_space_for(state, type)
|
table.insert(buffer, last)
|
||||||
if not r then return r, e end
|
|
||||||
|
|
||||||
if not state.interpreter.event_buffer then
|
|
||||||
state.interpreter.event_type = type
|
|
||||||
state.interpreter.event_buffer = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(state.interpreter.event_buffer, data)
|
|
||||||
end
|
end
|
||||||
return true
|
table.insert(last, data)
|
||||||
end,
|
|
||||||
--- add a new item in the last element (a list of elements) of the event buffer
|
|
||||||
-- will flush if needed
|
|
||||||
-- will use default or a new list if buffer is empty
|
|
||||||
-- returns true in case of success
|
|
||||||
-- returns nil, err in case of error
|
|
||||||
append_in_last = function(self, state, type, data, default)
|
|
||||||
local r, e = self:make_space_for(state, type)
|
|
||||||
if not r then return r, e end
|
|
||||||
|
|
||||||
if not state.interpreter.event_buffer then
|
|
||||||
r, e = self:append(state, type, default or {})
|
|
||||||
if not r then return r, e end
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(state.interpreter.event_buffer[#state.interpreter.event_buffer], data)
|
|
||||||
|
|
||||||
return true
|
|
||||||
end,
|
end,
|
||||||
|
|
||||||
--- start capturing events of a certain type
|
--- new events will be collected in this event buffer (any table) until the next pop
|
||||||
-- when an event of the type is appended, fn will be called with this event data
|
-- this is handled by a stack so nesting is allowed
|
||||||
-- and the event will not be added to the event buffer
|
push_buffer = function(self, state, buffer)
|
||||||
-- fn returns nil, err in case of error
|
table.insert(state.interpreter.event_buffer_stack, buffer)
|
||||||
push_capture = function(self, state, type, fn)
|
|
||||||
if not state.interpreter.event_capture_stack[type] then
|
|
||||||
state.interpreter.event_capture_stack[type] = {}
|
|
||||||
end
|
|
||||||
table.insert(state.interpreter.event_capture_stack[type], fn)
|
|
||||||
end,
|
end,
|
||||||
--- stop capturing events of a certain type.
|
--- stop capturing events of a certain type.
|
||||||
-- must be called after a push_capture
|
-- must be called after a push_buffer
|
||||||
-- this is handled by a stack so nested capturing is allowed.
|
pop_buffer = function(self, state)
|
||||||
pop_capture = function(self, state, type)
|
table.remove(state.interpreter.event_buffer_stack)
|
||||||
table.remove(state.interpreter.event_capture_stack[type])
|
end,
|
||||||
if #state.interpreter.event_capture_stack[type] == 0 then
|
--- returns the current buffer
|
||||||
state.interpreter.event_capture_stack[type] = nil
|
current_buffer = function(self, state)
|
||||||
end
|
return state.interpreter.event_buffer_stack[#state.interpreter.event_buffer_stack]
|
||||||
end,
|
end,
|
||||||
|
|
||||||
-- flush event buffer if it's neccessary to push an event of the given type
|
-- flush event buffer if it's neccessary to push an event of the given type
|
||||||
-- returns true in case of success
|
-- returns true in case of success
|
||||||
-- returns nil, err in case of error
|
-- returns nil, err in case of error
|
||||||
make_space_for = function(self, state, type)
|
make_space_for = function(self, state, type)
|
||||||
if state.interpreter.event_buffer and state.interpreter.event_type ~= type and not state.interpreter.event_capture_stack[type] then
|
if #state.interpreter.event_buffer_stack == 0 and state.interpreter.current_event and state.interpreter.current_event.type ~= type then -- FIXME useful?
|
||||||
return self:flush(state)
|
return self:manual_flush(state)
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
--- write all the data in a buffer into the current buffer, or to the game is no buffer is currently set
|
||||||
|
write_buffer = function(self, state, buffer)
|
||||||
|
for _, event in ipairs(buffer) do
|
||||||
|
if #state.interpreter.event_buffer_stack == 0 then
|
||||||
|
if event.type == "flush" then
|
||||||
|
local r, e = self:manual_flush(state)
|
||||||
|
if not r then return r, e end
|
||||||
|
elseif state.interpreter.current_event then
|
||||||
|
if state.interpreter.current_event.type == event.type then
|
||||||
|
for _, v in ipairs(event) do
|
||||||
|
table.insert(state.interpreter.current_event, v)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local r, e = self:manual_flush(state)
|
||||||
|
if not r then return r, e end
|
||||||
|
state.interpreter.current_event = event
|
||||||
|
end
|
||||||
|
else
|
||||||
|
state.interpreter.current_event = event
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local current_buffer = self:current_buffer(state)
|
||||||
|
table.insert(current_buffer, event)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- same as manual_flush but add the flush to the current buffer if one is set instead of directly to the game
|
||||||
|
flush = function(self, state)
|
||||||
|
if #state.interpreter.event_buffer_stack == 0 then
|
||||||
|
return self:manual_flush(state)
|
||||||
|
else
|
||||||
|
local current_buffer = self:current_buffer(state)
|
||||||
|
table.insert(current_buffer, { type = "flush" })
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
--- flush events and send them to the game if possible
|
--- flush events and send them to the game if possible
|
||||||
-- returns true in case of success
|
-- returns true in case of success
|
||||||
-- returns nil, err in case of error
|
-- returns nil, err in case of error
|
||||||
flush = function(self, state)
|
manual_flush = function(self, state)
|
||||||
while state.interpreter.event_buffer do
|
while state.interpreter.current_event do
|
||||||
local type, buffer = state.interpreter.event_type, state.interpreter.event_buffer
|
local event = state.interpreter.current_event
|
||||||
state.interpreter.event_type = nil
|
state.interpreter.current_event = nil
|
||||||
state.interpreter.event_buffer = nil
|
|
||||||
|
local type, buffer = event.type, event
|
||||||
|
buffer.type = nil
|
||||||
|
|
||||||
state.interpreter.skip_choices_until_flush = nil
|
state.interpreter.skip_choices_until_flush = nil
|
||||||
|
|
||||||
-- choice processing
|
-- choice processing
|
||||||
local choices
|
local choices
|
||||||
if type == "choice" then
|
if type == "choice" then
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ local function eval(state, exp)
|
||||||
}
|
}
|
||||||
-- string
|
-- string
|
||||||
elseif exp.type == "string" then
|
elseif exp.type == "string" then
|
||||||
local t, e = eval_text(state, exp.value)
|
local t, e = eval_text(state, exp.text)
|
||||||
if not t then return t, e end
|
if not t then return t, e end
|
||||||
return {
|
return {
|
||||||
type = "string",
|
type = "string",
|
||||||
|
|
@ -32,7 +32,7 @@ local function eval(state, exp)
|
||||||
-- parentheses
|
-- parentheses
|
||||||
elseif exp.type == "parentheses" then
|
elseif exp.type == "parentheses" then
|
||||||
return eval(state, exp.expression)
|
return eval(state, exp.expression)
|
||||||
-- list parentheses
|
-- list defined in brackets
|
||||||
elseif exp.type == "list_brackets" then
|
elseif exp.type == "list_brackets" then
|
||||||
if exp.expression then
|
if exp.expression then
|
||||||
local v, e = eval(state, exp.expression)
|
local v, e = eval(state, exp.expression)
|
||||||
|
|
@ -52,7 +52,7 @@ local function eval(state, exp)
|
||||||
value = {}
|
value = {}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
-- list
|
-- list defined using , operator
|
||||||
elseif exp.type == "list" then
|
elseif exp.type == "list" then
|
||||||
local flat = flatten_list(exp)
|
local flat = flatten_list(exp)
|
||||||
local l = {}
|
local l = {}
|
||||||
|
|
@ -65,17 +65,19 @@ local function eval(state, exp)
|
||||||
type = "list",
|
type = "list",
|
||||||
value = l
|
value = l
|
||||||
}
|
}
|
||||||
-- text: only triggered from choice/text lines
|
-- event buffer with from a text line
|
||||||
elseif exp.type == "text" then
|
elseif exp.type == "text" then
|
||||||
local currentTags = tags:current(state)
|
local l = {}
|
||||||
|
events:push_buffer(state, l)
|
||||||
|
local current_tags = tags:current(state)
|
||||||
local v, e = eval_text_callback(state, exp.text, function(text)
|
local v, e = eval_text_callback(state, exp.text, function(text)
|
||||||
local v2, e2 = events:append(state, "text", { text = text, tags = currentTags })
|
events:append(state, "text", { text = text, tags = current_tags })
|
||||||
if not v2 then return v2, e2 end
|
|
||||||
end)
|
end)
|
||||||
|
events:pop_buffer(state)
|
||||||
if not v then return v, e end
|
if not v then return v, e end
|
||||||
return {
|
return {
|
||||||
type = "nil",
|
type = "eventbuffer",
|
||||||
value = nil
|
value = l
|
||||||
}
|
}
|
||||||
-- assignment
|
-- assignment
|
||||||
elseif exp.type == ":=" then
|
elseif exp.type == ":=" then
|
||||||
|
|
|
||||||
|
|
@ -33,17 +33,38 @@ run_line = function(state, line)
|
||||||
elseif line.type == "choice" then
|
elseif line.type == "choice" then
|
||||||
local v, e = events:make_space_for(state, "choice")
|
local v, e = events:make_space_for(state, "choice")
|
||||||
if not v then return v, ("%s; in automatic event flush at %s"):format(e, line.source) end
|
if not v then return v, ("%s; in automatic event flush at %s"):format(e, line.source) end
|
||||||
local currentTags = tags:current(state)
|
|
||||||
local choice_block_state = { tags = currentTags, block = line.child }
|
|
||||||
v, e = events:append(state, "choice", { _state = choice_block_state }) -- new choice
|
|
||||||
if not v then return v, e end
|
|
||||||
events:push_capture(state, "text", function(event)
|
|
||||||
local v2, e2 = events:append_in_last(state, "choice", event, { _state = choice_block_state })
|
|
||||||
if not v2 then return v2, e2 end
|
|
||||||
end)
|
|
||||||
v, e = eval(state, line.text)
|
v, e = eval(state, line.text)
|
||||||
events:pop_capture(state, "text")
|
|
||||||
if not v then return v, ("%s; at %s"):format(e, line.source) end
|
if not v then return v, ("%s; at %s"):format(e, line.source) end
|
||||||
|
-- convert text events to choices
|
||||||
|
if v.type == "eventbuffer" then
|
||||||
|
local current_tags = tags:current(state)
|
||||||
|
local choice_block_state = { tags = current_tags, block = line.child }
|
||||||
|
local final_buffer = {}
|
||||||
|
for _, event in ipairs(v.value) do
|
||||||
|
if event.type == "text" then
|
||||||
|
-- create new choice block if needed
|
||||||
|
local last_choice_block = final_buffer[#final_buffer]
|
||||||
|
if not last_choice_block or last_choice_block.type ~= "choice" then
|
||||||
|
last_choice_block = { type = "choice" }
|
||||||
|
table.insert(final_buffer, last_choice_block)
|
||||||
|
end
|
||||||
|
-- create new choice item in choice block if needed
|
||||||
|
local last_choice = last_choice_block[#last_choice_block]
|
||||||
|
if not last_choice then
|
||||||
|
last_choice = { _state = choice_block_state }
|
||||||
|
table.insert(last_choice_block, last_choice)
|
||||||
|
end
|
||||||
|
-- add text to last choice item
|
||||||
|
for _, txt in ipairs(event) do
|
||||||
|
table.insert(last_choice, txt)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
table.insert(final_buffer, event)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
v, e = events:write_buffer(state, final_buffer)
|
||||||
|
if not v then return v, ("%s; at %s"):format(e, line.source) end
|
||||||
|
end
|
||||||
elseif line.type == "tag" then
|
elseif line.type == "tag" then
|
||||||
local v, e = eval(state, line.expression)
|
local v, e = eval(state, line.expression)
|
||||||
if not v then return v, ("%s; at %s"):format(e, line.source) end
|
if not v then return v, ("%s; at %s"):format(e, line.source) end
|
||||||
|
|
@ -61,6 +82,10 @@ run_line = function(state, line)
|
||||||
if not v then return v, ("%s; in automatic event flush at %s"):format(e, line.source) end
|
if not v then return v, ("%s; in automatic event flush at %s"):format(e, line.source) end
|
||||||
v, e = eval(state, line.text)
|
v, e = eval(state, line.text)
|
||||||
if not v then return v, ("%s; at %s"):format(e, line.source) end
|
if not v then return v, ("%s; at %s"):format(e, line.source) end
|
||||||
|
if v.type == "eventbuffer" then
|
||||||
|
v, e = events:write_buffer(state, v.value)
|
||||||
|
if not v then return v, ("%s; at %s"):format(e, line.source) end
|
||||||
|
end
|
||||||
elseif line.type == "flush_events" then
|
elseif line.type == "flush_events" then
|
||||||
local v, e = events:flush(state)
|
local v, e = events:flush(state)
|
||||||
if not v then return v, ("%s; in event flush at %s"):format(e, line.source) end
|
if not v then return v, ("%s; in event flush at %s"):format(e, line.source) end
|
||||||
|
|
|
||||||
|
|
@ -135,18 +135,17 @@ common = {
|
||||||
return t
|
return t
|
||||||
end,
|
end,
|
||||||
-- parse interpolated expressions in a text
|
-- parse interpolated expressions in a text
|
||||||
|
-- type sets the type of the returned expression (text is in text field)
|
||||||
-- allow_subtext (bool) to enable or not [subtext] support
|
-- allow_subtext (bool) to enable or not [subtext] support
|
||||||
-- if allow_binops is given, if one of the caracters of allow_binops appear unescaped in the text, it will interpreter a binary operator expression
|
-- if allow_binops is given, if one of the caracters of allow_binops appear unescaped in the text, it will interpreter a binary operator expression
|
||||||
-- * returns a text expression, remaining (if the right expression stop before the end of the text)
|
-- * returns an expression with given type (string by default) and as a value a list of strings and expressions (text elements)
|
||||||
-- if allow_binops is not given:
|
-- * if allow_binops is given, also returns remaining string (if the right expression stop before the end of the text)
|
||||||
-- * returns a list of strings and expressions (text elements)
|
|
||||||
-- * nil, err: in case of error
|
-- * nil, err: in case of error
|
||||||
parse_text = function(text, state, namespace, allow_binops, allow_subtext, in_subtext)
|
parse_text = function(text, state, namespace, type, allow_binops, allow_subtext, in_subtext)
|
||||||
local l = {}
|
local l = {}
|
||||||
local text_exp
|
local text_exp = { type = type, text = l }
|
||||||
local delimiters = ""
|
local delimiters = ""
|
||||||
if allow_binops then
|
if allow_binops then
|
||||||
text_exp = { type = "text", text = l }
|
|
||||||
delimiters = allow_binops
|
delimiters = allow_binops
|
||||||
end
|
end
|
||||||
if allow_subtext then
|
if allow_subtext then
|
||||||
|
|
@ -182,7 +181,7 @@ common = {
|
||||||
text = rem:match("^%s*}(.*)$")
|
text = rem:match("^%s*}(.*)$")
|
||||||
-- start subtext
|
-- start subtext
|
||||||
elseif allow_subtext and r:match("^%[") then
|
elseif allow_subtext and r:match("^%[") then
|
||||||
local exp, rem = common.parse_text(r:gsub("^%[", ""), state, namespace, allow_binops, allow_subtext, true)
|
local exp, rem = common.parse_text(r:gsub("^%[", ""), state, namespace, "text", allow_binops, allow_subtext, true)
|
||||||
if not exp then return nil, rem end
|
if not exp then return nil, rem end
|
||||||
if not rem:match("^%]") then return nil, ("expected closing ] at end of subtext before %q"):format(rem) end
|
if not rem:match("^%]") then return nil, ("expected closing ] at end of subtext before %q"):format(rem) end
|
||||||
-- add to text
|
-- add to text
|
||||||
|
|
@ -193,7 +192,7 @@ common = {
|
||||||
if allow_binops then
|
if allow_binops then
|
||||||
return text_exp, r
|
return text_exp, r
|
||||||
else
|
else
|
||||||
return l
|
return text_exp
|
||||||
end
|
end
|
||||||
-- binop expression at the end of the text
|
-- binop expression at the end of the text
|
||||||
elseif allow_binops and r:match(("^[%s]"):format(allow_binops)) then
|
elseif allow_binops and r:match(("^[%s]"):format(allow_binops)) then
|
||||||
|
|
@ -209,7 +208,7 @@ common = {
|
||||||
if allow_binops then
|
if allow_binops then
|
||||||
return text_exp, ""
|
return text_exp, ""
|
||||||
else
|
else
|
||||||
return l
|
return text_exp
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
-- find compatible function variants from a fully qualified name
|
-- find compatible function variants from a fully qualified name
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,30 @@ local unops_prio = {
|
||||||
[11] = {},
|
[11] = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local function get_text_in_litteral(s, start_pos)
|
||||||
|
local d, r
|
||||||
|
-- find end of string
|
||||||
|
start_pos = start_pos or 2
|
||||||
|
local i = start_pos
|
||||||
|
while true do
|
||||||
|
local skip
|
||||||
|
skip = s:match("^[^%\\\"]-%b{}()", i) -- skip interpolated expressions
|
||||||
|
if skip then i = skip end
|
||||||
|
skip = s:match("^[^%\\\"]-\\.()", i) -- skip escape codes (need to skip every escape code in order to correctly parse \\": the " is not escaped)
|
||||||
|
if skip then i = skip end
|
||||||
|
if not skip then -- nothing skipped
|
||||||
|
local end_pos = s:match("^[^%\"]-\"()", i) -- search final double quote
|
||||||
|
if end_pos then
|
||||||
|
d, r = s:sub(start_pos, end_pos-2), s:sub(end_pos)
|
||||||
|
break
|
||||||
|
else
|
||||||
|
return nil, ("expected \" to finish string near %q"):format(s:sub(i))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return d, r
|
||||||
|
end
|
||||||
|
|
||||||
--- parse an expression
|
--- parse an expression
|
||||||
-- return expr, remaining if success
|
-- return expr, remaining if success
|
||||||
-- returns nil, err if error
|
-- returns nil, err if error
|
||||||
|
|
@ -48,32 +72,16 @@ local function expression(s, state, namespace, current_priority, operating_on)
|
||||||
})
|
})
|
||||||
-- string
|
-- string
|
||||||
elseif s:match("^%\"") then
|
elseif s:match("^%\"") then
|
||||||
local d, r
|
local d, r = get_text_in_litteral(s)
|
||||||
-- find end of string
|
local l, e = parse_text(d, state, namespace, "string") -- parse interpolated expressions
|
||||||
local i = 2
|
|
||||||
while true do
|
|
||||||
local skip
|
|
||||||
skip = s:match("^[^%\\\"]-%b{}()", i) -- skip interpolated expressions
|
|
||||||
if skip then i = skip end
|
|
||||||
skip = s:match("^[^%\\\"]-\\.()", i) -- skip escape codes (need to skip every escape code in order to correctly parse \\": the " is not escaped)
|
|
||||||
if skip then i = skip end
|
|
||||||
if not skip then -- nothing skipped
|
|
||||||
local end_pos = s:match("^[^%\"]-\"()", i) -- search final double quote
|
|
||||||
if end_pos then
|
|
||||||
d, r = s:sub(2, end_pos-2), s:sub(end_pos)
|
|
||||||
break
|
|
||||||
else
|
|
||||||
return nil, ("expected \" to finish string near %q"):format(s:sub(i))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- parse interpolated expressions
|
|
||||||
local l, e = parse_text(d, state, namespace)
|
|
||||||
if not l then return l, e end
|
if not l then return l, e end
|
||||||
return expression(r, state, namespace, current_priority, {
|
return expression(r, state, namespace, current_priority, l)
|
||||||
type = "string",
|
-- text
|
||||||
value = l
|
elseif s:match("^t%\"") then
|
||||||
})
|
local d, r = get_text_in_litteral(s, 3)
|
||||||
|
local l, e = parse_text(d, state, namespace, "text", nil, true) -- parse interpolated expressions and subtext
|
||||||
|
if not l then return l, e end
|
||||||
|
return expression(r, state, namespace, current_priority, l)
|
||||||
-- paranthesis
|
-- paranthesis
|
||||||
elseif s:match("^%b()") then
|
elseif s:match("^%b()") then
|
||||||
local content, r = s:match("^(%b())(.*)$")
|
local content, r = s:match("^(%b())(.*)$")
|
||||||
|
|
@ -119,7 +127,7 @@ local function expression(s, state, namespace, current_priority, operating_on)
|
||||||
type = "list",
|
type = "list",
|
||||||
left = {
|
left = {
|
||||||
type = "string",
|
type = "string",
|
||||||
value = { name }
|
text = { name }
|
||||||
},
|
},
|
||||||
right = val
|
right = val
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ local function parse(state)
|
||||||
end
|
end
|
||||||
-- text (text & choice lines)
|
-- text (text & choice lines)
|
||||||
if line.text then
|
if line.text then
|
||||||
local txt, err = parse_text(line.text, state, namespace, "#~", true)
|
local txt, err = parse_text(line.text, state, namespace, "text", "#~", true)
|
||||||
if not txt then return nil, ("%s; at %s"):format(err, line.source) end
|
if not txt then return nil, ("%s; at %s"):format(err, line.source) end
|
||||||
if err:match("[^%s]") then return nil, ("expected end of expression in end-of-text expression before %q"):format(err) end
|
if err:match("[^%s]") then return nil, ("expected end of expression in end-of-text expression before %q"):format(err) end
|
||||||
line.text = txt
|
line.text = txt
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
local format, to_lua, from_lua
|
local format, to_lua, from_lua, events, anselme
|
||||||
|
|
||||||
local types = {}
|
local types = {}
|
||||||
types.lua = {
|
types.lua = {
|
||||||
|
|
@ -131,6 +131,13 @@ types.anselme = {
|
||||||
return { [k] = v }
|
return { [k] = v }
|
||||||
end
|
end
|
||||||
},
|
},
|
||||||
|
eventbuffer = {
|
||||||
|
format = function(val)
|
||||||
|
local v, e = events:write_buffer(anselme.running.state, val)
|
||||||
|
if not v then return v, e end
|
||||||
|
return ""
|
||||||
|
end,
|
||||||
|
},
|
||||||
type = {
|
type = {
|
||||||
format = function(val)
|
format = function(val)
|
||||||
local k, ke = format(val[1])
|
local k, ke = format(val[1])
|
||||||
|
|
@ -149,6 +156,7 @@ types.anselme = {
|
||||||
|
|
||||||
package.loaded[...] = types
|
package.loaded[...] = types
|
||||||
local common = require((...):gsub("stdlib%.types$", "interpreter.common"))
|
local common = require((...):gsub("stdlib%.types$", "interpreter.common"))
|
||||||
format, to_lua, from_lua = common.format, common.to_lua, common.from_lua
|
format, to_lua, from_lua, events = common.format, common.to_lua, common.from_lua, common.events
|
||||||
|
anselme = require((...):gsub("stdlib%.types$", "anselme"))
|
||||||
|
|
||||||
return types
|
return types
|
||||||
|
|
|
||||||
6
test/tests/eventbuffer text litteral.ans
Normal file
6
test/tests/eventbuffer text litteral.ans
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
:a = t"Some text."
|
||||||
|
:b = t"Tagged text" # 1
|
||||||
|
|
||||||
|
a: {a}
|
||||||
|
|
||||||
|
b: {b}
|
||||||
32
test/tests/eventbuffer text litteral.lua
Normal file
32
test/tests/eventbuffer text litteral.lua
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
local _={}
|
||||||
|
_[13]={1}
|
||||||
|
_[12]={}
|
||||||
|
_[11]={}
|
||||||
|
_[10]={}
|
||||||
|
_[9]={tags=_[13],text="Tagged text"}
|
||||||
|
_[8]={tags=_[12],text="b: "}
|
||||||
|
_[7]={tags=_[11],text="Some text."}
|
||||||
|
_[6]={tags=_[10],text="a: "}
|
||||||
|
_[5]={_[8],_[9]}
|
||||||
|
_[4]={_[6],_[7]}
|
||||||
|
_[3]={"return"}
|
||||||
|
_[2]={"text",_[5]}
|
||||||
|
_[1]={"text",_[4]}
|
||||||
|
return {_[1],_[2],_[3]}
|
||||||
|
--[[
|
||||||
|
{ "text", { {
|
||||||
|
tags = {},
|
||||||
|
text = "a: "
|
||||||
|
}, {
|
||||||
|
tags = {},
|
||||||
|
text = "Some text."
|
||||||
|
} } }
|
||||||
|
{ "text", { {
|
||||||
|
tags = {},
|
||||||
|
text = "b: "
|
||||||
|
}, {
|
||||||
|
tags = { 1 },
|
||||||
|
text = "Tagged text"
|
||||||
|
} } }
|
||||||
|
{ "return" }
|
||||||
|
]]--
|
||||||
Loading…
Add table
Add a link
Reference in a new issue