Skip to content
This repository has been archived by the owner on Nov 20, 2020. It is now read-only.

Commit

Permalink
added new syntax for selectors
Browse files Browse the repository at this point in the history
  • Loading branch information
Fabio Mascarenhas committed Oct 22, 2009
1 parent 01f32cd commit 0769f3a
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 8 deletions.
5 changes: 2 additions & 3 deletions src/cosmo.lua
Expand Up @@ -41,8 +41,7 @@ local compiled_template = [[
]=],
[=[
local selector = $parsed_selector
local selector_name = '$selector'
if not selector then selector = '$selector' end
if not selector then selector = '' end
$if_subtemplate[==[
local subtemplates = {}
$subtemplates[===[
Expand Down Expand Up @@ -117,7 +116,7 @@ local function compile_template_application(chunkname, selector, args, first_sub
table.insert(subtemplates, 1, first_subtemplate)
end
local ta = { _template = 2, selector = selector,
parsed_selector = grammar.parse_selector(selector) }
parsed_selector = selector }
local do_subtemplates = function ()
for i, subtemplate in ipairs(subtemplates) do
yield{ i = i, subtemplate = parse_longstring(subtemplate) }
Expand Down
2 changes: 1 addition & 1 deletion src/cosmo/fill.lua
Expand Up @@ -60,7 +60,7 @@ local function fill_template_application(state, selector, args, first_subtemplat
if first_subtemplate ~= "" then
table.insert(subtemplates, 1, first_subtemplate)
end
selector = get_selector(env, selector) or selector
selector = loadstring("local env = (...); return " .. selector)(env) or function () return '' end
if #subtemplates == 0 then
if args and args ~= "" then
if type(selector) == 'function' then
Expand Down
15 changes: 11 additions & 4 deletions src/cosmo/grammar.lua
Expand Up @@ -4,7 +4,7 @@ local re = require "re"

module(..., package.seeall)

function parse_selector(selector, env)
local function parse_selector(selector, env)
env = env or "env"
selector = string.sub(selector, 2, #selector)
local parts = {}
Expand All @@ -19,6 +19,11 @@ function parse_selector(selector, env)
return env .. table.concat(parts)
end

local function parse_exp(exp)
-- return exp:sub(2, #exp - 1)
return exp
end

local start = "[" * lpeg.P"="^1 * "["

local longstring1 = lpeg.P{
Expand Down Expand Up @@ -67,8 +72,9 @@ local syntax = [[
template <- (%state <item>* -> {} !.) -> compiletemplate
item <- <text> / <templateappl> / (. => error)
text <- (%state {~ (!<selector> ('$$' -> '$' / .))+ ~}) -> compiletext
selector <- '$' %alphanum+ ('|' %alphanum+)*
templateappl <- (%state {<selector>} {~ <args>? ~} !'{'
selector <- ('$(' %s {~ <exp> ~} %s ')') -> parseexp /
('$' %alphanum+ ('|' %alphanum+)*) -> parseselector
templateappl <- (%state {~ <selector> ~} {~ <args>? ~} !'{'
({%longstring?}) !%start (%s ',' %s ({%longstring}))* -> {} !(',' %s %start))
-> compileapplication
args <- '{' %s '}' / '{' %s <arg> %s (',' %s <arg> %s)* ','? %s '}'
Expand All @@ -82,7 +88,7 @@ local syntax = [[
unop <- '-' / 'not' / '#'
binop <- '+' / '-' / '*' / '/' / '^' / '%' / '..' / '<=' / '<' / '>=' / '>' / '==' / '~=' /
'and' / 'or'
prefixexp <- ( {<selector>} -> parseselector / {%name} -> addenv / '(' %s <exp> %s ')' )
prefixexp <- ( <selector> / {%name} -> addenv / '(' %s <exp> %s ')' )
( %s <args> / '.' %name / ':' %name %s ('(' %s ')' / '(' %s <explist> %s ')') /
'[' %s <exp> %s ']' / '(' %s ')' / '(' %s <explist> %s ')' /
%string / %longstring -> parsels %s )*
Expand Down Expand Up @@ -110,6 +116,7 @@ local syntax_defs = {
longstring = longstring,
s = space,
parseselector = parse_selector,
parseexp = parse_exp,
parsels = parse_longstring,
addenv = function (s) return "env['" .. s .. "']" end,
state = lpeg.Carg(1),
Expand Down
51 changes: 51 additions & 0 deletions tests/test_cosmo.lua
Expand Up @@ -87,6 +87,33 @@ result = cosmo.f(template){
}
assert(result=="John has Ace of Spades, Queen of Diamonds, 10 of Hearts, and 2 of Clubs\nJoão has Ace of Diamonds\n")

players = {"John", "João"}
cards = {}
cards["John"] = mycards
cards["João"] = { {"Ace", "Diamonds"} }
template = "$do_players[[$player has $do_cards[[$rank of $suit]],[=[, $rank of $suit]=],[[, and $rank of $suit]]\n]]"
result = cosmo.f(template){
do_players = function()
for i,p in ipairs(players) do
cosmo.yield {
player = p,
do_cards = function()
for i,v in ipairs(cards[p]) do
local template
if i == #mycards then -- for the last item use the third template (with "and")
template = 3
elseif i~=1 then -- use the second template for items 2...n-1
template = 2
end
cosmo.yield{rank=v[1], suit=v[2], _template=template}
end
end
}
end
end
}
assert(result=="John has Ace of Spades, Queen of Diamonds, 10 of Hearts, and 2 of Clubs\nJoão has Ace of Diamonds\n")

template = "$do_players[=[$player$if_john[[$mark]] has $do_cards[[$rank of $suit, ]]\n]=]"
result = cosmo.f(template){
do_players = function()
Expand Down Expand Up @@ -157,14 +184,38 @@ template = " $foo|bar $foo|1|baz "
result = cosmo.fill(template, { foo = { { baz = "World!" }, bar = "Hello" } })
assert(result==" Hello World! ")

template = " $(foo.bar) $(foo[1].baz) "
result = cosmo.fill(template, { foo = { { baz = "World!" }, bar = "Hello" } })
assert(result==" Hello World! ")

template = " $(foo.bar) $(foo[1].baz) "
result = cosmo.fill(template, { foo = { { baz = "World!" }, bar = "Hello" } })
assert(result==" Hello World! ")

template = " Hello $message{ 'World!' } "
result = cosmo.fill(template, { message = function (arg) return arg[1] end })
assert(result==" Hello World! ")

template = " Hello $(message){ 'World!' } "
result = cosmo.fill(template, { message = function (arg) return arg[1] end })
assert(result==" Hello World! ")

template = " Hello $(message){ 'World!' } "
result = cosmo.fill(template, { message = function (arg) return arg[1] end })
assert(result==" Hello World! ")

template = " Hello $message{ $msg } "
result = cosmo.fill(template, { msg = "World!", message = function (arg) return arg[1] end })
assert(result==" Hello World! ")

template = " Hello $message{ $(msg) } "
result = cosmo.fill(template, { msg = "World!", message = function (arg) return arg[1] end })
assert(result==" Hello World! ")

template = " Hello $message{ $(msg) } "
result = cosmo.fill(template, { msg = "World!", message = function (arg) return arg[1] end })
assert(result==" Hello World! ")

template = " Hello $message{ $msg }[[$it]] "
result = cosmo.fill(template, { msg = "World!",
message = function (arg) cosmo.yield{ it = arg[1] } end })
Expand Down

0 comments on commit 0769f3a

Please sign in to comment.