DSL in lua

classic Classic list List threaded Threaded
43 messages Options
123
Reply | Threaded
Open this post in threaded view
|

DSL in lua

Vasiliy Tolstov
Hello.
What is the best way to create custom DSL in Lua? Google says, that it
can be possible via base lua or using lpeg.

I need something like this
direcotry "/etc/" {
  owner "root"
  group "wheel"
  mode "0755"
  action "create"
}

Can somebody provie minimal lua code for this sample? How can i do
this using lua lpeg?

--
Vasiliy Tolstov,
Clodo.ru
e-mail: [hidden email]
jabber: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

steve donovan
On Thu, Dec 6, 2012 at 7:52 AM, Vasiliy Tolstov <[hidden email]> wrote:
> directory "/etc/" {
>   owner "root";
>   group "wheel";
>   mode "0755";
>   action "create";
> }

Here is how to make this valid Lua:

0) use semicolons or commas as delimiters (my edit!)
1) directory is a function that takes a path string and returns a function
2) which takes a table argument
3) owner, group, etc are functions that take strings.

(Because of Lua call syntax sugar, we can leave out parens when there
is a single argument which is a string literal or a table constructor)

Alternative to 3), set table keys (since presumably order is not
important here?)

directory "/etc/" {
  owner="root";
  group="wheel";
  mode="0755";
  action="create";
 }

If you don't want delimiters, the code can be converted into valid Lua
by a suitable string transformation, e.g a simple-minded replacement
of strings at end-of-line with the string plus semi-colon.

When executing such configuration Lua, run it in your own environment
that will contain the directory, etc functions and have no references
to dangerous global functions

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

Dirk Laurie-2
In reply to this post by Vasiliy Tolstov
You're a few commas away from legal Lua syntax.

directory "/etc/" {
  owner "root",
  group "wheel",
  mode "0755",
  action "create",
}

It can be done (functions owner etc would have to store
their argument somewhere) but a few equal signs makes the
Lua code efficient:

directory "/etc/" {
  owner="root",
  group="wheel",
  mode="0755",
  action="create",
}

The code would be (not tested):

function directory(dirname)
   return function(t)
      os.execute ("mkdir %s; chown %s.%s %s; chmod %s %s"):
         format(dirname,t.owner,t.group,dirname,t.mode,dirname)
   end
end

Or one could replace the `{`..`}` by `[[`..`]]` and insert
a small parser that extracts the fields from the string.

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

steve donovan
In reply to this post by Vasiliy Tolstov
On Thu, Dec 6, 2012 at 7:52 AM, Vasiliy Tolstov <[hidden email]> wrote:
> can be possible via base lua or using lpeg.

The advantage of lpeg of course is that your DSL is defined exactly
and does not suffer from the problems of being a fully-executable Lua
script (much as JavaScript people would never parse JSON by simply
interpreting it).

An entertaining project (or maybe it already exists?) would be a
lpeg-based DSL generation tool

You would give it something like:

MUST directory STRING {
  owner IDEN
  group IDEN
  mode STRING
  action IDEN
}

which would match this syntax (there MUST be a directory clause)

directory "/etc/" {
  owner root
  group wheel
  mode "0755"
  action create
}

and create a parser that brings this in as a table structure. ( It
would issue sensible errors at the right place, which is a tricky
thing with lpeg)

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

Vasiliy Tolstov
In reply to this post by Dirk Laurie-2
Thanks. But = sign i think is ambigious... How can i avoid using = sign?

2012/12/6 Dirk Laurie <[hidden email]>:

> You're a few commas away from legal Lua syntax.
>
> directory "/etc/" {
>   owner "root",
>   group "wheel",
>   mode "0755",
>   action "create",
> }
>
> It can be done (functions owner etc would have to store
> their argument somewhere) but a few equal signs makes the
> Lua code efficient:
>
> directory "/etc/" {
>   owner="root",
>   group="wheel",
>   mode="0755",
>   action="create",
> }
>
> The code would be (not tested):
>
> function directory(dirname)
>    return function(t)
>       os.execute ("mkdir %s; chown %s.%s %s; chmod %s %s"):
>          format(dirname,t.owner,t.group,dirname,t.mode,dirname)
>    end
> end
>
> Or one could replace the `{`..`}` by `[[`..`]]` and insert
> a small parser that extracts the fields from the string.
>



--
Vasiliy Tolstov,
Clodo.ru
e-mail: [hidden email]
jabber: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

Coda Highland
The = is just an efficiency thing, you can write it without it. It's
the commas that are important.

It'd probably end up looking something like

function owner(name) return {key='owner', value=name} end

and then the function returned by directory() would iterate over the
members of the table passed to it and construct a table based on that.

/s/ Adam

On Wed, Dec 5, 2012 at 10:48 PM, Vasiliy Tolstov <[hidden email]> wrote:

> Thanks. But = sign i think is ambigious... How can i avoid using = sign?
>
> 2012/12/6 Dirk Laurie <[hidden email]>:
>> You're a few commas away from legal Lua syntax.
>>
>> directory "/etc/" {
>>   owner "root",
>>   group "wheel",
>>   mode "0755",
>>   action "create",
>> }
>>
>> It can be done (functions owner etc would have to store
>> their argument somewhere) but a few equal signs makes the
>> Lua code efficient:
>>
>> directory "/etc/" {
>>   owner="root",
>>   group="wheel",
>>   mode="0755",
>>   action="create",
>> }
>>
>> The code would be (not tested):
>>
>> function directory(dirname)
>>    return function(t)
>>       os.execute ("mkdir %s; chown %s.%s %s; chmod %s %s"):
>>          format(dirname,t.owner,t.group,dirname,t.mode,dirname)
>>    end
>> end
>>
>> Or one could replace the `{`..`}` by `[[`..`]]` and insert
>> a small parser that extracts the fields from the string.
>>
>
>
>
> --
> Vasiliy Tolstov,
> Clodo.ru
> e-mail: [hidden email]
> jabber: [hidden email]
>

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

Vasiliy Tolstov
In reply to this post by steve donovan
0) ok, ";" sign is not very big problem
1-2) can you provide me simple exmple, please.
3) owner, group, etc are functions that take strings is not preferred,
i thing more usable to set table keys...

2012/12/6 steve donovan <[hidden email]>:

> On Thu, Dec 6, 2012 at 7:52 AM, Vasiliy Tolstov <[hidden email]> wrote:
>> directory "/etc/" {
>>   owner "root";
>>   group "wheel";
>>   mode "0755";
>>   action "create";
>> }
>
> Here is how to make this valid Lua:
>
> 0) use semicolons or commas as delimiters (my edit!)
> 1) directory is a function that takes a path string and returns a function
> 2) which takes a table argument
> 3) owner, group, etc are functions that take strings.
>
> (Because of Lua call syntax sugar, we can leave out parens when there
> is a single argument which is a string literal or a table constructor)
>
> Alternative to 3), set table keys (since presumably order is not
> important here?)
>
> directory "/etc/" {
>   owner="root";
>   group="wheel";
>   mode="0755";
>   action="create";
>  }
>
> If you don't want delimiters, the code can be converted into valid Lua
> by a suitable string transformation, e.g a simple-minded replacement
> of strings at end-of-line with the string plus semi-colon.
>
> When executing such configuration Lua, run it in your own environment
> that will contain the directory, etc functions and have no references
> to dangerous global functions
>
> steve d.
>



--
Vasiliy Tolstov,
Clodo.ru
e-mail: [hidden email]
jabber: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

Vasiliy Tolstov
In reply to this post by steve donovan
Where i can find some exmples for creating such parser?

2012/12/6 steve donovan <[hidden email]>:

> An entertaining project (or maybe it already exists?) would be a
> lpeg-based DSL generation tool
>
> You would give it something like:
>
> MUST directory STRING {
>   owner IDEN
>   group IDEN
>   mode STRING
>   action IDEN
> }
>
> which would match this syntax (there MUST be a directory clause)
>
> directory "/etc/" {
>   owner root
>   group wheel
>   mode "0755"
>   action create
> }
>
> and create a parser that brings this in as a table structure. ( It
> would issue sensible errors at the right place, which is a tricky
> thing with lpeg)



--
Vasiliy Tolstov,
Clodo.ru
e-mail: [hidden email]
jabber: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

steve donovan
In reply to this post by Vasiliy Tolstov
On Thu, Dec 6, 2012 at 8:53 AM, Vasiliy Tolstov <[hidden email]> wrote:
> 1-2) can you provide me simple exmple, please.

function directory(path)
    local t = {path=path}
    return function (spec)
        for key,value in pairs(spec) do
            t[key] = value
        end
        create_directory(t)  ---> actually makes the directory
    end
end

So it's a function that returnsa function - or more accurately creates
a closure that has a reference to the local t (an 'upvalue')

If we had "directory '/tmp/foo' { owner='root' }" then
create_directory will be called with the table
{path='/tmp/foo',owner='root'}

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

Vasiliy Tolstov
Big thanks!

But if that possible to avoid using = and not to create many function
like function owner/mode/group etc?

function dump(o)
  if type(o) == 'table' then
    local s = '{ '
    for k,v in pairs(o) do
      if type(k) ~= 'string' then k = '"'..k..'"' end
        s = s .. ''..k..' = \'' .. dump(v) .. '\', '
      end
    return s .. '} '
  else
    return tostring(o)
  end
end

function directory(name)
    local t = {name=name}
    return function (spec)
        for key,value in pairs(spec) do
            t[key] = value
        end
        print(dump(t))
--        create_directory(t)  ---> actually makes the directory
    end
end

directory "/etc" {
  path = "/etc";
  owner = "root";
  group = "wheel";
  mode = "0755";
}

2012/12/6 steve donovan <[hidden email]>:

> On Thu, Dec 6, 2012 at 8:53 AM, Vasiliy Tolstov <[hidden email]> wrote:
>> 1-2) can you provide me simple exmple, please.
>
> function directory(path)
>     local t = {path=path}
>     return function (spec)
>         for key,value in pairs(spec) do
>             t[key] = value
>         end
>         create_directory(t)  ---> actually makes the directory
>     end
> end
>
> So it's a function that returnsa function - or more accurately creates
> a closure that has a reference to the local t (an 'upvalue')
>
> If we had "directory '/tmp/foo' { owner='root' }" then
> create_directory will be called with the table
> {path='/tmp/foo',owner='root'}
>
> steve d.
>



--
Vasiliy Tolstov,
Clodo.ru
e-mail: [hidden email]
jabber: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

Alfredo Palhares
In reply to this post by Vasiliy Tolstov
Just as a side question: Are you creating some configuration managemente system by some sorts ?
Like chef ?

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

Vasiliy Tolstov
Yes =) Now its for fun, but in generaly i think that it can be some
alternative to chef.

2012/12/6 Alfredo Palhares <[hidden email]>:
> Just as a side question: Are you creating some configuration managemente system by some sorts ?
> Like chef ?
>



--
Vasiliy Tolstov,
Clodo.ru
e-mail: [hidden email]
jabber: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

Alfredo Palhares
Hello,

I want links ! :) Do you have a public repo somewhere ?

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

Rena
In reply to this post by Dirk Laurie-2

On 2012-12-06 1:27 AM, "Dirk Laurie" <[hidden email]> wrote:
>
>       os.execute ("mkdir %s; chown %s.%s %s; chmod %s %s"):
>          format(dirname,t.owner,t.group,dirname,t.mode,dirname)

That needs more parens:
os.execute (("mkdir %s; chown %s.%s %s; chmod %s %s"):
   format(dirname,t.owner,t.group,dirname,t.mode,dirname))

without them, it would be trying to format the result of os.execute. (It's also not secure at all; consider dirname="x;rm -rf /")

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

Elias Barrionovo

On Dec 6, 2012 10:08 AM, "Rena" <[hidden email]> wrote:
> (It's also not secure at all; consider dirname="x;rm -rf /")

Yes, good old shell injection. That's why os.execute is very unsafe; one should use a library that has the API for filesystem stuff (luaposix? lfs?).

BTW, one must also --no-preserve-root these dreaded days... =/

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

Vasiliy Tolstov
In reply to this post by Alfredo Palhares
No now i'm only doing some proto for check...
I want to minimize depends on all libraries and want to use golang for
backend and lua for "frontend"
For example i do not want to use lua file system or lua posix, needed
function has been written on golang and used by lua.

2012/12/6 Alfredo Palhares <[hidden email]>:
> Hello,
>
> I want links ! :) Do you have a public repo somewhere ?
>



--
Vasiliy Tolstov,
Clodo.ru
e-mail: [hidden email]
jabber: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

Craig Barnes
Sounds like an interesting project. I approve of your choice of languages ;)

Do you already have an idea of how you will integrate Go and Lua? This is
something that I've been considering for a while but haven't been entirely
satisfied with the current options.

P.S. I wrote a small snippet a while back (mainly for my memory)
that is similar to your DSL idea:

  https://github.com/craigbarnes/lua-snippets/blob/master/dsl.lua

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

steve donovan
On Thu, Dec 6, 2012 at 2:43 PM, Craig Barnes <[hidden email]> wrote:
> Do you already have an idea of how you will integrate Go and Lua? This is
> something that I've been considering for a while but haven't been entirely
> satisfied with the current options.

Yes, golua (several forks available, one for 5.2) does the basics of
providing the API in a Go-consumable form.

But still, it's a pain to make Go functions available in Lua.  I have
an extension library around which makes it much easier to register Go
functions (uses reflection, yay!) and marshalls maps and slices
appropriately.  I can dig it out if anyone is interested.

steve d.

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

Javier Guerra Giraldez
In reply to this post by steve donovan
On Thu, Dec 6, 2012 at 1:47 AM, steve donovan <[hidden email]> wrote:
> much as JavaScript people would never parse JSON by simply
> interpreting it

... removing wishful thinking...

"much as responsible JavaScript people would never parse JSON by
simply interpreting it"

.... and got an empty set!

(just kidding!)

--
Javier

Reply | Threaded
Open this post in threaded view
|

Re: DSL in lua

spir ☣
In reply to this post by steve donovan
On 06/12/2012 07:47, steve donovan wrote:

> On Thu, Dec 6, 2012 at 7:52 AM, Vasiliy Tolstov <[hidden email]> wrote:
>> can be possible via base lua or using lpeg.
>
> The advantage of lpeg of course is that your DSL is defined exactly
> and does not suffer from the problems of being a fully-executable Lua
> script (much as JavaScript people would never parse JSON by simply
> interpreting it).
>
> An entertaining project (or maybe it already exists?) would be a
> lpeg-based DSL generation tool
>
> You would give it something like:
>
> MUST directory STRING {
>    owner IDEN
>    group IDEN
>    mode STRING
>    action IDEN
> }
>
> which would match this syntax (there MUST be a directory clause)
>
> directory "/etc/" {
>    owner root
>    group wheel
>    mode "0755"
>    action create
> }
>
> and create a parser that brings this in as a table structure. ( It
> would issue sensible errors at the right place, which is a tricky
> thing with lpeg)
>
> steve d.

I did this once (around the WML language of Wesnoth). It is in fact, in my view,
just like a semantic schema, but at the (meta-)level of language/grammar def
instead of language usage. If I did it again, I would use plain s-exps as the
base, fondamental meta-grammar: it is the only case I know where absence of any
distinction actually is an advantage.

Denis

123