Skip to content

Commit 2061df5

Browse files
authored
Merge branch 'master' into max-fields-count
2 parents 1a627ad + 76295c2 commit 2061df5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+118914
-16
lines changed

GLOBAL_KEYWORD_CHANGES.md

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Lua 5.5 `global` 关键字语法支持 - 变更摘要
2+
3+
## 概述
4+
为 Lua Language Server 添加了对 Lua 5.5 新增的 `global` 关键字的完整语法解析支持。
5+
6+
## 修改的文件
7+
- `script/parser/compile.lua`
8+
9+
## 主要变更
10+
11+
### 1. 关键字识别 (第 1391-1420 行)
12+
`isKeyWord` 函数中添加了对 `global` 关键字的处理:
13+
- 仅在 Lua 5.5 中将 `global` 视为关键字
14+
- 其他版本中可作为普通标识符使用
15+
-`goto` 关键字的处理方式一致
16+
17+
### 2. 解析函数 (第 3130-3274 行)
18+
新增 `parseGlobal` 函数,支持三种语法形式:
19+
20+
**a) 全局函数声明**
21+
```lua
22+
global function funcName() end
23+
```
24+
25+
**b) 全局变量声明(带属性)**
26+
```lua
27+
global x -- 单个变量
28+
global <const> y -- 带属性
29+
global a, b, c -- 多个变量
30+
global <const> x, <close> y, z -- 混合属性
31+
```
32+
33+
**c) 全局所有变量**
34+
```lua
35+
global * -- 所有后续变量为全局
36+
global <const> * -- 带属性的全局所有
37+
```
38+
39+
### 3. 语法分发 (第 4117-4119 行)
40+
`parseAction` 函数中添加了 global 关键字的检查和分发:
41+
```lua
42+
if token == 'global' and isKeyWord('global', Tokens[Index + 3]) then
43+
return parseGlobal()
44+
end
45+
```
46+
47+
## 生成的 AST 节点
48+
49+
### setglobal 节点
50+
用于全局变量和函数声明:
51+
```lua
52+
{
53+
type = 'setglobal',
54+
start = <position>,
55+
finish = <position>,
56+
[1] = <variable_name>,
57+
attrs = <optional_attributes>, -- 可选的属性列表
58+
value = <optional_value> -- 对于函数声明
59+
}
60+
```
61+
62+
### globalall 节点
63+
用于 `global *` 声明:
64+
```lua
65+
{
66+
type = 'globalall',
67+
start = <position>,
68+
finish = <position>,
69+
attrs = <optional_attributes>
70+
}
71+
```
72+
73+
## 兼容性
74+
75+
- **Lua 5.5**: `global` 是保留关键字
76+
- **Lua 5.4 及以下**: `global` 可用作标识符
77+
78+
## 测试
79+
80+
要测试此功能:
81+
1. 设置 Lua 版本为 5.5
82+
2. 使用包含 global 声明的代码
83+
3. 验证语法高亮和解析正确性
84+
85+
## 下一步
86+
87+
此实现仅完成了语法解析。完整的功能还需要:
88+
- 语义分析(作用域、引用)
89+
- 类型推断
90+
- 代码补全
91+
- 诊断检查
92+
- 文档生成
93+
94+
详见 `GLOBAL_KEYWORD_IMPLEMENTATION.md`

GLOBAL_KEYWORD_IMPLEMENTATION.md

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
# Lua 5.5 `global` 关键字实现
2+
3+
## 概述
4+
5+
本次修改为 Lua Language Server 添加了对 Lua 5.5 新增的 `global` 关键字的语法解析支持。
6+
7+
## 语法规则
8+
9+
根据 Lua 5.5 的语法规范,`global` 关键字支持以下三种形式:
10+
11+
### 1. 全局函数声明
12+
```lua
13+
global function funcName()
14+
-- function body
15+
end
16+
```
17+
18+
### 2. 全局变量声明(带属性)
19+
```lua
20+
-- 单个变量
21+
global x
22+
23+
-- 带属性的变量
24+
global <const> y
25+
26+
-- 多个变量
27+
global a, b, c
28+
29+
-- 带属性的多个变量
30+
global <const> x, <close> y, z
31+
```
32+
33+
### 3. 全局所有变量声明
34+
```lua
35+
-- 声明所有后续变量为全局
36+
global *
37+
38+
-- 带属性的全局所有变量
39+
global <const> *
40+
```
41+
42+
## 实现细节
43+
44+
### 1. 关键字识别 (`isKeyWord` 函数)
45+
46+
`compile.lua``isKeyWord` 函数中添加了对 `global` 关键字的处理:
47+
48+
```lua
49+
if word == 'global' then
50+
if State.version == 'Lua 5.5' then
51+
return true
52+
end
53+
return false
54+
end
55+
```
56+
57+
类似于 `goto` 关键字的处理方式,`global` 仅在 Lua 5.5 版本中被视为关键字。在其他版本中,它可以作为普通标识符使用。
58+
59+
### 2. 解析函数 (`parseGlobal` 函数)
60+
61+
创建了新的 `parseGlobal` 函数来处理三种不同的 global 语法形式:
62+
63+
- **全局函数**: 调用 `parseFunction` 并将返回的名称类型设置为 `'setglobal'`
64+
- **全局变量**: 解析 attnamelist,支持前置和后置属性
65+
- **全局所有**: 创建特殊的 `'globalall'` 节点
66+
67+
### 3. 语法分发 (`parseAction` 函数)
68+
69+
`parseAction` 函数中添加了对 `global` 关键字的检查:
70+
71+
```lua
72+
if token == 'global' and isKeyWord('global', Tokens[Index + 3]) then
73+
return parseGlobal()
74+
end
75+
```
76+
77+
## 生成的 AST 节点类型
78+
79+
### setglobal 节点
80+
用于全局变量和全局函数声明:
81+
```lua
82+
{
83+
type = 'setglobal',
84+
start = <position>,
85+
finish = <position>,
86+
[1] = <variable_name>,
87+
attrs = <optional_attributes>,
88+
value = <optional_function_or_value>
89+
}
90+
```
91+
92+
### globalall 节点
93+
用于 `global *` 声明:
94+
```lua
95+
{
96+
type = 'globalall',
97+
start = <position>,
98+
finish = <position>,
99+
attrs = <optional_attributes>
100+
}
101+
```
102+
103+
## 版本兼容性
104+
105+
- **Lua 5.5**: `global` 作为关键字,启用完整的语法解析
106+
- **Lua 5.4 及更早版本**: `global` 作为普通标识符,可以用作变量名
107+
108+
## 测试建议
109+
110+
要测试此实现,需要:
111+
112+
1. 设置项目的 Lua 版本为 5.5
113+
2. 创建包含 global 声明的测试文件
114+
3. 验证语法高亮和错误检查是否正常工作
115+
116+
示例测试代码:
117+
```lua
118+
-- 这些在 Lua 5.5 中应该正常解析
119+
global function test()
120+
print("hello")
121+
end
122+
123+
global x
124+
global <const> y
125+
global a, b, c
126+
global *
127+
128+
-- 这在非 Lua 5.5 版本中应该可以正常使用
129+
local global = 10 -- 'global' 作为变量名
130+
```
131+
132+
## 修改的文件
133+
134+
本次实现仅修改了一个文件:
135+
136+
- `script/parser/compile.lua`
137+
138+
### 修改内容总结
139+
140+
1. **isKeyWord 函数** (约第 1391 行)
141+
- 添加了对 `global` 关键字的版本检查
142+
- 仅在 Lua 5.5 中将其识别为关键字
143+
144+
2. **parseGlobal 函数** (约第 3123 行,新增)
145+
- 完整实现了三种 global 语法的解析
146+
- 支持初始化赋值:`global x = 10`
147+
- 处理属性(attrib)的解析和关联
148+
- 支持多变量声明的解析:`global a, b, c = 1, 2, 3`
149+
- 检查 global 不能有 close 属性
150+
- 使用 parseMultiVars 处理初始化赋值
151+
152+
3. **parseAction 函数** (约第 4117 行)
153+
- 添加了 global 关键字的分发逻辑
154+
- 使用 `isKeyWord` 检查确保版本正确性
155+
156+
## 使用示例
157+
158+
在支持 Lua 5.5 的环境中,以下代码将被正确解析:
159+
160+
```lua
161+
-- 示例 1: 声明全局函数
162+
global function myGlobalFunction()
163+
return 42
164+
end
165+
166+
-- 示例 2: 声明全局变量(无初始化)
167+
global x
168+
169+
-- 示例 3: 声明并初始化全局变量
170+
global y = 100
171+
172+
-- 示例 4: 声明带常量属性的全局变量
173+
global <const> PI = 3.14159
174+
175+
-- 示例 5: 声明多个全局变量
176+
global width, height, depth
177+
178+
-- 示例 6: 声明并初始化多个全局变量
179+
global a, b, c = 1, 2, 3
180+
181+
-- 示例 7: 声明带不同属性的多个全局变量
182+
global <const> MAX_SIZE = 100, counter = 0
183+
184+
-- 示例 8: 属性可以在变量名前后
185+
global x <const>, <const> y
186+
187+
-- 示例 9: 声明所有后续变量为全局(可读写)
188+
global *
189+
x = 1 -- x 自动成为全局变量
190+
y = 2 -- y 自动成为全局变量
191+
192+
-- 示例 10: 声明所有后续变量为只读全局
193+
global <const> *
194+
print(math.pi) -- OK,print 和 math 自动为只读
195+
z = 1 -- 错误!z 被声明为只读
196+
```
197+
198+
### 错误示例
199+
200+
```lua
201+
-- 错误 1: global 不能有 close 属性
202+
global x <close> -- 解析错误!
203+
204+
-- 错误 2: 在隐式 global * 失效的作用域内使用未声明变量
205+
global x
206+
y = 1 -- 错误:y 未声明(需要语义分析支持)
207+
208+
-- 错误 3: 赋值给 const 变量
209+
global <const> PI = 3.14
210+
PI = 3.15 -- 错误:不能赋值给常量(需要语义分析支持)
211+
212+
-- 错误 4: 初始化已存在的全局变量
213+
X = 10
214+
global X = 20 -- 运行时错误:X 已定义(需要语义分析支持)
215+
```
216+
217+
## 后续工作
218+
219+
当前实现仅包括语法解析层面的支持。完整的功能还需要:
220+
221+
1. **语义分析支持**
222+
- 变量作用域处理
223+
- 引用关系跟踪
224+
- `globalall` 声明的作用域影响
225+
226+
2. **类型推断支持**
227+
- 全局变量的类型推断
228+
- 属性(const/close)的类型约束
229+
230+
3. **代码补全支持**
231+
- global 关键字的补全
232+
- 全局变量的智能提示
233+
234+
4. **诊断和错误检查**
235+
- 重复声明检查
236+
- 常量修改检查
237+
- close 属性的正确性验证
238+
239+
5. **文档生成支持**
240+
- 全局变量的文档注释
241+
- API 文档生成
242+
243+
这些功能需要在以下模块中进行相应的修改:
244+
- `script/vm/*` - 虚拟机和语义分析
245+
- `script/core/completion.lua` - 代码补全
246+
- `script/core/diagnostics.lua` - 诊断
247+
- `script/core/hover.lua` - 悬停提示
248+
- 等等
249+
250+
## 兼容性说明
251+
252+
此实现完全向后兼容:
253+
254+
- **Lua 5.5**: `global` 是保留关键字,按新语法解析
255+
- **Lua 5.4 及以下**: `global` 是普通标识符,可以用作变量名或函数名
256+
257+
示例:
258+
```lua
259+
-- 在 Lua 5.4 中,这是有效的:
260+
local global = "这是一个变量"
261+
function global()
262+
return "这是一个函数"
263+
end
264+
265+
-- 在 Lua 5.5 中,上述代码会报错,因为 global 是关键字
266+
```
267+
268+
## 技术细节
269+
270+
### attnamelist 的解析
271+
272+
attnamelist 的语法定义为:
273+
```
274+
attnamelist ::= [attrib] Name [attrib] {',' Name [attrib]}
275+
```
276+
277+
这意味着属性可以出现在变量名之前或之后。我们的实现支持这两种情况:
278+
279+
```lua
280+
-- 属性在前
281+
global <const> x
282+
283+
-- 属性在后
284+
global x <const>
285+
286+
-- 混合使用
287+
global <const> x <close>, y, <const> z
288+
```
289+
290+
### AST 节点设计
291+
292+
所有 global 声明都会生成适当的 AST 节点,与现有的 `local` 声明保持一致的结构,便于后续的语义分析和其他处理。

0 commit comments

Comments
 (0)