Lua中赋值语句如何以左括号开头?语法歧义解析
Lua赋值语句以左括号开头的语法及歧义解析
首先明确:Lua的赋值语句允许左侧的左值被括号包裹,因此确实存在以左括号开头的赋值语句,比如:
-- 基础示例:括号包裹单个变量 (a) = 10 print(a) -- 输出 10 -- 多变量赋值的情况,部分左值带括号 (b, (c)) = 20, 30 print(b, c) -- 输出 20 30
这种写法的本质是,Lua语法中赋值语句的左值列表支持括号表达式(只要表达式最终指向可赋值的对象,比如变量、表字段),括号在这里仅作为分组,不改变语义,但让赋值语句可以左括号开头。
回到你提到的歧义示例:
a = b + c (print or io.write)('done')
Lua允许语句之间省略分号,换行不一定代表语句结束,因此语法分析器会面临两种解读:
- 将两行视为同一语句的延续:把第二行的
(print or io.write)当作c的函数调用参数,然后把c(...)的返回值当作可调用对象,再传入'done'调用,最终整句是:a = b + c(print or io.write)('done') - 将两行视为独立语句:第一行是赋值语句,第二行是独立的函数调用语句(等价于加了分号):
a = b + c; (print or io.write)('done')
为什么会有这种歧义?核心原因是:Lua语法中左括号开头的语句可能是函数调用,也可能是赋值语句,语法分析器无法仅通过左括号开头这一点,判断它是新语句还是上一行的延续。比如如果第二行是一个以左括号开头的赋值语句:
a = b + c (d) = 5
同样会产生歧义——是尝试解析为a = b + c(d) =5(语义非法,但语法分析阶段会先做这种尝试),还是两行独立语句。
Lua解决这个歧义的规则是:如果一个语句以左括号开头,且上一行是一个可以作为函数调用前缀的表达式(比如变量c),则优先将其解析为上一行的函数调用延续;否则才当作新语句。手册特意指出这个语法设计带来的歧义,就是为了提醒开发者在这类场景下可以手动加分号消除歧义。
内容的提问来源于stack exchange,提问作者Ashutosh Biswas
相关产品推荐
相关产品推荐

