Problem with infix operator with "flat" association

18 views
Skip to first unread message

Jaco

unread,
Oct 18, 2011, 9:01:26 AM10/18/11
to metalua
I'm implementing a Matlab-like range operator using "::" as the
operator. This operator has two forms:

1::10 -- returns the list {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
1::2::10 -- returns the list {1, 3, 5, 7, 9}

My metalua implementation is the following:

-{ block:
mlp.lexer:add "::"
mlp.expr.infix:add {"::", prec = 40, assoc = "flat", builder =
|a| +{range(-{a})} }
}

table.print( +{1::10} )
table.print( +{1::2::10} )

When I run this program it prints the correct ASTs:

`Call{ `Id "range", { `Number 1, `Number 10 } }
`Call{ `Id "range", { `Number 1, `Number 2, `Number 10 } }

However, when I try to use this with the following code:

function range(a)
return a
end

table.print(1::10)
table.print(1::2::10)

metalua fails with the following error:

lua: compile.lua:1054: No tag in expression { `Number 1, `Number
10 }

Am I doing something wrong?

Fabien

unread,
Oct 18, 2011, 9:14:41 AM10/18/11
to met...@googlegroups.com
On Tue, Oct 18, 2011 at 3:01 PM, Jaco <jvdm...@emss.co.za> wrote:
When I run this program it prints the correct ASTs:

   `Call{ `Id "range", { `Number 1, `Number 10 } }
   `Call{ `Id "range", { `Number 1, `Number 2, `Number 10 } }

That's not the correct AST, call arguments are not nested in a list. The correct AST would be:

   `Call{ `Id "range", `Number 1, `Number 10 } 
   `Call{ `Id "range", `Number 1, `Number 2, `Number 10 } 

This will be fixed with the following builder: "builder = |a| `Call{ +{range}, unpack(a) }"

Jaco

unread,
Oct 18, 2011, 9:50:09 AM10/18/11
to met...@googlegroups.com
Thanks, that solves my problem, and improved my understanding of metalua ASTs!

Now that this approach is working, I'm contemplating whether it might be possible to rather use the colon operator ":" instead of the double colon operator "::". This will bring it much closer to Matlab syntax. The main problem I see is that the colon operator is part of the standard Lua syntax where it is used for method definitions and method invocations. The difference between the following examples are fairly obvious (for a human reader), but I'm not sure whether metalua has a way of making a distinction and handling them separately:

Ranges

1:10
1:2:10
1:n
0:pi/4:pi
a:b

Method definitions

function o:f() ... end
 
function a.b.c:g() ... end

Method invocations

o:f()

a.b.c:f()

I would appreciate it if you can comment on the possibility of such an approach.

Fabien Fleutot

unread,
Oct 18, 2011, 10:10:25 AM10/18/11
to met...@googlegroups.com
On Tue, Oct 18, 2011 at 3:50 PM, Jaco <jvdm...@emss.co.za> wrote:
Thanks, that solves my problem, and improved my understanding of metalua ASTs!

Now that this approach is working, I'm contemplating whether it might be possible to rather use the colon operator ":" instead of the double colon operator "::". This will bring it much closer to Matlab syntax.
I would appreciate it if you can comment on the possibility of such an approach.


It would be ambiguous, think for instance "a:f(x)" or "a:f(x):g(y)", which are valid Lua invocations, and would also make sense as ranges according to your syntax.

Generally speaking, most Lua constructs are introduced by a dedicated keyword. Respecting this principle ensures that independent extensions can cohabitate together. "[" is free as an initial keyword in an expression context, so "[a:b:c]" could have been readable and unambiguous. Unfortunately, you'd get into trouble in table contexts: "{ [a:f(x)]"  could be either the beginning of the list "{ [a:f(x)] }" starting with a range element, or "{ [a:f(x)] = b }" a plain Lua table with one key which is an invocation.

I'd suggest that you use an available keyword, such as "#" or "::" indeed, for range denotations. Another  possibility would be to disable method invocation, but I wouldn't advocate this either, it doesn't seem worth further breaking compatibility for such a cosmetic purpose. 

Note that MLP isn't optimized to let you write arbitrary grammars: it tries to encourage you choosing syntaxes which respect "the Lua way", i.e. which are easy to disambiguate, according to simple rules. The support for rules which require big lookaheads is intentionally limited (I event wonder whether it's documented... :))


Jaco

unread,
Oct 18, 2011, 10:39:19 AM10/18/11
to met...@googlegroups.com
Thank you for the feedback - it is always good to know more about the philosophy of metalua and the type of things one has to consider when extending the syntax. In my case I will then rather use the "::" operator for ranges. It is close enough to the Matlab equivalent. As a result I believe that Matlab users will feel comfortable with the slight syntactic change.
Reply all
Reply to author
Forward
0 new messages