Here is a Lua 5.2.2 transcript, showing the declaration and indexing of a table:
> mylist = {'foo', 'bar'}
> print(mylist[1])
foo
Why isn't the following statement legal?
> print({'foo', 'bar'}[1])
stdin:1: ')' expected near '['
I can't think of any other language where a literal can't be substituted for a reference (except, of course, when an lvalue is needed).
FWIW, parenthesizing the table literal makes the statement legal:
> print(({'foo', 'bar'})[1])
foo
It is also related to the fact that in Lua this syntax is valid:
myfunc { 1, 2, 3 }
and it is equivalent to:
myfunc( { 1, 2, 3 } )
Therefore an expression such as:
myfunc { 1, 2, 3 } [2]
is parsed as:
myfunc( { 1, 2, 3 } )[2]
so first the function call is evaluated, then the indexing takes place.
If {1,2,3}[2]
could be parsed as a valid indexing operation it could lead to ambiguities in the previous expression that would require more lookahead. The Lua team chose to make the Lua bytecode compiler fast by making it a single pass compiler, so it scans source code only once with a minimum of lookahead. This message to lua mailing list from Roberto Ierusalimschy (lead Lua developer) points in that direction.
The same problem exists for string literals and method calls. This is invalid:
"my literal":sub(1)
but this is valid:
("my literal"):sub(1)
Again, Lua allows this:
func "my literal"
as equivalent to this:
func( "my literal" )
Going of the grammar defined here, the reason that the non parenthesized version is invalid yet the parenthesized is, is because the syntax tree takes a different path and expects a closing bracket )
because there should be no other symbol in that context.
In the first case:
functioncall ::= prefixexp args | prefixexp `:´ Name args
prefixexp =>
prefixexp ::= var | functioncall | `(´ exp `)´
var -> print
THEREFORE prefixexp -> print
args =>
args ::= `(´ [explist] `)´ | tableconstructor | String
match '('
explist =>
explist ::= {exp `,´} exp
exp =>
exp ::= nil | false | true | Number | String | `...´ | function | prefixexp | tableconstructor | exp binop exp | unop exp
tableconstructor =>
explist-> {'foo','bar'}
THEREFORE explist = {'foo','bar'}
match ')' ERROR!!! found '[' expected ')'
On the other hand with parenthesis:
functioncall ::= prefixexp args | prefixexp `:´ Name args
prefixexp =>
prefixexp ::= var | functioncall | `(´ exp `)´
var -> print
THEREFORE prefixexp -> print
args =>
args ::= `(´ [explist] `)´ | tableconstructor | String
match '('
explist =>
explist ::= {exp `,´} exp
exp =>
exp ::= nil | false | true | Number | String | `...´ | function | prefixexp | tableconstructor | exp binop exp | unop exp
prefixexp =>
prefixexp ::= var | functioncall | `(´ exp `)´
var =>
var ::= Name | prefixexp `[´ exp `]´ | prefixexp `.´ Name
prefixexp =>
prefixexp ::= var | functioncall | `(´ exp `)´
match '('
exp =>
exp ::= nil | false | true | Number | String | `...´ | function | prefixexp | tableconstructor | exp binop exp | unop exp
tableconstructor =>
THEREFORE exp = {'foo','bar'}
match ')'
THEREFORE prefixexp = ({'foo','bar'})
match '['
exp => Number = 1
match ']'
THEREFORE VAR = ({'foo','bar'})[1]
THEREFORE prefixexp = VAR
THEREFOER exp = VAR
THEREFORE explist = VAR
match ')'
THEREFORE args = (VAR)
=> print(VAR)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With