Lua的语法是无歧义的吗?

lua 5.3语法分析的BNF 看lua解释器源代码的时候发现和lua官网上给的有点出入,自己记录一下 官网的文档:https://www.lua.org/manual/5.3/manual.html,直接在页面搜索BNF就行了 以下是从源码的注释里扣出来的: block -> statlist statlist -> { stat [';'] } fieldsel -> ['.' | ':'] NAM... 阅读详情

    Lua5.0的语法非常简洁,这从参考手册中的语法定义的规模(转换成标准BNF形式大概有100个左右的产生式)可以看出。不过简洁归简洁,它却不完全是无二义性的。下面将用具体例子揭示什么样的代码会引起歧义(执行环境是www.lua.org发布的Lua5.04)。

    首先定义如下几个函数:

function foo(a)
   print("foo print",a)
   return a
end

function goo(a)
   print("goo print",a)
   return a
end

function hoo(a)
   print("hoo print",a)
   return a
end

试看这一段代码:

foo(goo)
(hoo)(1979)

如果试图编译执行上面这段程序,那么解释器就会报告 "ambiguous syntax (function call x new statement) near '(' " 这样的错误。为什么呢?或许写程序的人原本的意思就是第一行foo(goo)为一个单独的函数调用语句(statement),而第二行(hoo)(1979)又为另一个单独的函数调用语句(Lua中语句之间的分隔符——分号并非必需,而是可选的)。但是不要忘记了foo(goo)(hoo)是一个语法上完全合法的函数调用形式(在编译过程中换行符作为空白符会被忽略掉),foo(goo)(hoo)(1979)也可以成为一个完整的函数调用语句。这样的话,编译器就无法知道程序员的真正意图了。

    我们可以再深入到编译过程里头一点看看。Lua语法的形式定义(转换成BNF标准形式)包含如下几个产生式:

(1) stat -> functioncall  (语句的产生式)
(2) prefixexp -> functioncall (前缀表达式的产生式)
(3) functioncall -> prefixexp args 
                  | prefixexp ':' Name args (函数调用的产生式)


可以发现,functioncall既可以被规约(reduce)为stat,也可以被规约成prefixexp,(1)和(2)两个产生式发生了冲突,编译器不知道用哪一个对foo(goo)进行规约,所以便出现了错误。

    其实要解决这个问题歧义问题也很简单,在第一行后面加一个语句分隔符——分号,编译器就会把代码编译成两个独立的语句。或者把两行合并成一行,那么foo(goo)(hoo)(1979)就被看作是一个完整的函数调用(其实此时仍然是有歧义的,但是Lua5.04通过优先选择prefixexp -> functioncall进行规约解决了二义性)。

    实际上,还有另外3种情况也会引起歧义:

-- prefixexp -> functioncall 与 
-- exp -> functioncall 冲突。
-- 编译器不知道该把foo(goo)解释成表达式(exp)还是前缀表达式

local v = foo(goo)
(hoo)(1979)

-- exp -> var 与 prefixexp -> var 冲突
-- 第二行的变量(var)m不知道该被看成表达式还是前缀表达式

m = foo
local v = m
(goo)(1979)

-- prefixexp -> '(' exp ')' 与 
-- exp -> '(' exp ')' 冲突
-- 不知道该把(t.fn)看成表达式还是前缀表达式

t = {fn = foo}
local v = (t.fn)
(goo)(1979)

第一个例子中解决歧义的两种方法同样也适用于这三种情况。至此我们不难发现,引起歧义的根本原因在于Lua语句之间的分隔符是可选而不是必需的。如果强制要求象C语言那样每条语句后跟一个分号,那么二义性就不复存在(这一点在本文作者构造Lua5.0的SLR解析表时得到了验证)。但是有许多人未必喜欢敲入那么多讨厌的分号,所以Lua的作者把选择的权利留给了程序员自己,付出的代价就是引进了这些模糊的代码(虽然出现的几率不大),这也算是语言设计时的一种折衷吧。

lua:Lua很棒,Lua是巴西人发明的,这些都令我不爽,但是还不至于脸红,最多眼红。让我脸红的是Lua的源代码,百分之一百的ANSI C,一点都不取代。在任何支持ANSI C编译器的平台上都可以轻松编译通过。我试过,真是一点废话都没有。 1W行。下载地址:http 立即下载

相关推荐

牛耕式全覆盖算法-matlab代码

牛耕式路径全覆盖算法,也称为牛耕算法或者蚂蚁算法,是一种用于解决路径规划问题的启发式算法。这个算法的灵感来自于牛在耕田时的行为。在这个算法中,假设有一块田地需要耕作,牛从田地的某个角落开始行走,走过的路径会被标记。牛会优先选择尚未经过的路径,当所有的路径都走过后,算法停止。在路径规划问题中,田地可以看作是一个由节点和边构成的图。每个节点代表一个位置,每条边代表两个节点之间的连接。路径全覆盖问题是找出一组路径,使得每个节点都被至少一条路径经过。牛耕式路径全覆盖算法的基本思想是以启发式的方式逐步构建路径。

m0_69611489的博客 1689

Lua 奇怪的错误 ambiguous syntax (function call x new statement) near '('

原文链接:http://blog.youkuaiyun.com/zhangxaochen/article/details/8094929 很简单的代码: ('hello'):sub(1, 2) ('hello'):sub(1, 2) 整个文件只有这样两行。 看起来挺正常, 猜猜运行会怎样?结果是, 执行会出错!错误信息: ambiguous syntax (function call

zhangxaochen的专栏 5663

手把手教你用周立功USBCANFD-200U和ZCANPRO软件,从驱动安装到UDS诊断一条龙搞定

本文详细介绍了如何使用周立功USBCANFD-200U硬件和ZCANPRO软件,从驱动安装到UDS诊断的全流程操作指南。涵盖硬件连接、软件配置、CAN通信测试及UDS诊断实战,帮助汽车电子爱好者和工程师快速掌握CAN总线通信技术,实现专业的车辆诊断功能。

weixin_30752699的博客 579

理解 Lua 的那些坑爹特性

按:最近看到了依云的文章,一方面,为Lua被人误解而感到十分难过,另一方面,也为我的好友, 依云没有能够体会到Lua的绝妙和优雅之处而感到很遗憾,因此我写了这篇文章,逐条款地说明了 依云理解中出现的一些问题。希望能够帮助到大家! 1. 协程只能在Lua代码中使用 是的,协程在当你需要挂起一个C函数的时候无法使用。但是,在提出这个缺陷的时 候,是不是应该想一想:为什...

weixin_33982670的博客 278

【python3.7】解决报错 error: Microsoft Visual C++ 14.0 or greater is required. Get it with “Microsoft C++

解决pip安装py7zr遇到的报错问题。

水w的博客 3938

用户存续期价值评估(CLV) 一

用户存续期价值评估(CLV) 1 一. 定义 ​     用户存续期价值(Customer Lifetime Value),也可称为CLTV、LCV或者LTV,是企业对未来一个客户与其的关系所带来的净收益的预测。这个预测模型可以有不同水平的复杂度和精确度,从一个直观感觉到使用复杂的预测技术。CLV可以被简单理解为客户关系的价值,也就是未来由于与客户的关系所带...

weixin_43171270的博客 8024

lua BNF

Here is the complete syntax of Lua in extended BNF. (It does not describe operator precedences.) chunk ::= {stat [`;´]} [laststat [`;´]] block ::= chunk stat ::= varlist1 `=´ explist1 |

红流 958

基于COMSOL电弧动态仿真模型优化:高收敛性可修改吹弧方案解析

在多物理场耦合分析中,电弧动态仿真历来是数值稳定性的难点:温度从室温跃升至数万开尔文,电导率随温度呈数量级跳变,流动、传热与电磁场相互牵制,极易引发求解器不收敛或初始值不一致等问题。如何构建高收敛性的数值模型,成为开关设备灭弧性能优化的重要技术基础。通过合理的几何简化、全耦合求解器配置、辅助扫描初始化策略以及参数化建模手段,可以实现对吹弧方案的灵活调整与批量寻优,从而系统性评估气流速度、喷口形状、触头间距等关键因素对熄弧性能的影响。这类仿真方法广泛应用于断路器、接触器等高压电器产品研发,为灭弧室结构设计提供

weixin_29758911的博客 350

lua的Chunks和block

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33744854的博客 267

链路状态路由协议 OSPF (一)

本章将会学习链路状态路由协议OSPF,理解OSPF的基本概念,工作原理,掌握OSPF配置基本命令。本章重点,OSPF的基本概念,OSPF配置。

yj11290301的博客 3475

配置 SAP Web Dispatcher 的实战指南:打通 SAP Fiori、SAP Gateway 与前端系统的关键一跳

SAP Web Dispatcher 在 Fiori 架构中扮演关键角色,作为统一入口处理 HTTPS 请求、实现安全代理和流量分发。它将分散在不同系统的访问路径统一收口,解决浏览器同源策略限制,集中管理 HTTPS 终止和客户端信息传递。典型配置中,Web Dispatcher 监听 443 端口,根据路径将 OData 请求转发至 Gateway 系统,静态资源请求送至前端服务器。SSL 相关配置(如 PSE 文件)确保安全通信,而路由规则(wdisp/system_xx)决定请求转发目标。实施时需注意

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 101

Lua学习笔记-语法

前言 Lua语言是一种嵌入式语言被广泛的用于各个领域,而且与C语言的兼容性比较好.Openresty当中就可以使用Lua进行快速开发.Redis可以借助Lua实现事务.以及各大游戏引擎有很多都支持Lua脚本.以此可见Lua使用范围是很广泛的. 本篇将Lua语言和其它几种语言(PHP,JavaScript,Go,Shell,C)做对比,进行对比的记忆. Lua的语法风格和shell语言有些相似之处,...

Coder Liu的博客 1048

多体动力学分析软件:SIMPACK_(17).SIMPACK高级编程与脚本

自定义力和约束可以用于模拟更复杂和现实的物理场景。SIMPACK 提供了接口,允许用户通过 Python 脚本来实现自定义力和约束。以下是一个示例,展示如何定义一个自定义力函数并应用于模型。# 定义自定义力函数"""自定义力函数:param t: 时间:param position: 位置:param velocity: 速度:return: 力"""# 创建一个新的 SIMPACK 模型# 添加一个刚体# 添加一个关节# 添加一个自定义力# 设置仿真参数# 运行仿真。

kkchenjj的博客 1419

Freeswitch Lua学习笔记

在FreeSWITCH中,Lua模块是默认加载的。在所有嵌入式脚本语言中,它是最值得推荐的语言。首先它非常轻 量级,mod_lua.so经过减肥(Strip)后只有272KB;另外,它的语法相对的简单。有人做过对比,在嵌入式的脚 本语言里,如果Python得2分,Perl得4分,JavaScript得5,则Lua语言可得10分 [2],由此可见一斑。 另外,Lua模块的文档也是最全的。笔者在使用其...

irizhao的专栏 3690

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Lua快速入门教程

以上实例中,我们定义了一个名为 foo 的函数作为协同程序。在函数中,我们使用 coroutine.yield 暂停了协同程序的执行,并返回了一个值 。在主程序中,我们使用 coroutine.create 创建了一个协同程序对象,并使用 coroutine.resume 启动了它的执行。 在第一次调用 coroutine.resume 后,协同程序执行到 coroutine.yield 处暂停,并将值返回给主程序。然后,我们再次调用 coroutine.resume,并传入一个值作为协同程序恢复执行时的参

weixin_45715405的博客 4367

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Lua语法介绍(7)_table

Lua语法介绍(7)_table表

l531798151的博客 585

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

[Lua] Lua Binding基础

Lua → C++Lua 调用函数↓Lua VM 执行 CALL↓发现目标是 CFunction↓把参数放到 lua_State 栈上↓调用 C wrapper↓wrapper 从栈取参数↓调用真实 C + + 函数↓wrapper 把返回值压栈↓ return 返回值数量C++ → LuaC + + 获取 Lua 函数↓压入参数↓lua_pcall↓Lua VM 执行 Lua 函数↓返回值留在栈上↓C + + 从栈读取返回值类对象绑定。

selfsongs 314

Lua - 语言学习笔记

看云风的Skynet的时候, 对Lua生出了很大的兴趣,抽出时间看了下Lua在线手册,特作此记录。 本文仅为Lua语言作为独立的脚本语言的部分知识速记。 虽然Lua被设计来作为宿主语言的嵌入脚本,不过简单的逻辑纯Lua也可以实现。 关键字和操作符 关键字 and break do else elseif end false

郭立东的个人博客 650

lua学习笔记(一)

笔者不知不觉开始用cocos2dx-lua写项目有2个月左右了,闲来无事,且来谈论一番lua的特殊之处。 一:函数调用方式。在java,javaScript,C++(指针除外)中通过“对象”调用方法通常都是用.(点);然而在lua中调用“对象”(此处勿纠结lua的“伪对象--元表”)通常是用:(冒号)。但若是非要用.(点)调用lua“对象”的方法也是可以的,在笔者看来区别有两点,1:用冒...

星晨六慕的博客 342

Lua 学习笔记(一)—— 基本语法

1 简介 由 clean C 实现。需要被宿主程序调用,可以注入 C 函数。 2 语法约定 Lua 的语法基于 BNF 的语法规则。 Lua 对大小写敏感。 2.1 保留关键字 C 语言中没有的关键字有: and elseif functionin nil local not orrepeat then until 规范:...

weixin_33912638的博客 102

Lua的值与类型

Lua 是一门动态类型语言。 这意味着变量没有类型;只有值才有类型。 语言中不设类型定义。 所有的值携带自己的类型。 Lua 中有八种基本类型: nil、 boolean、 number、 string、 function、userdata、 thread 和 table。

u011218378的博客 793

【Lua程序设计】字符串

【Lua程序设计】字符串

qq_44861231的博客 822

Lua-类型与值

Lua是一种动态类型语言,包含8种基础数据类型:nil(空值)、boolean(布尔)、number(数字)、string(字符串)、userdata(自定义类型)、function(函数)、thread(线程)和table(表)。其中nil表示无值,boolean包含true和false,但Lua中除false和nil外其他值都视为真。number表示实数,string是不可变字符序列,table是灵活的数据结构,function支持高阶函数编程。Lua的类型系统灵活,支持动态类型转换和自动内存管理,适用

2401_83191546的博客 953

Lua中的三目运算符

0x00 三目运算 熟悉C/C++的老司机都知道三目运算a?b:c,这种写法替换简单的条件判断语句可以在不增加阅读难度的情况下,使代码尽量保持简洁。 int a, b, ret; //if-else if (a > b) ret = a; else ret = b; //三目运算符 ret = a > b ? a : b;

coffeecato的个人博客 1万+
上一篇: Lua的多任务机制——协程(coroutine)
下一篇: 为什么会出现LNK2005"符号已定义"的链接错误?
ShenRui
博客等级 码龄20年 63粉丝 36原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值