Skip to content

Conversation

@CppCXY
Copy link

@CppCXY CppCXY commented Dec 25, 2025

No description provided.

@MunifTanjim
Copy link
Collaborator

Thanks! I'm gonna take a look at it soon.

@MunifTanjim
Copy link
Collaborator

Can you please apply this patch? I can't push to this branch as it seems...

diff --git a/grammar.js b/grammar.js
index 4604fcf..33681f5 100644
--- a/grammar.js
+++ b/grammar.js
@@ -84,7 +84,10 @@ module.exports = grammar({
                 for namelist in explist do block end |
                 function funcname funcbody |
                 local function Name funcbody |
-                local namelist ['=' explist]
+                global function Name funcbody | 
+                local attnamelist ['=' explist] |
+                global attnamelist ['=' explist] |
+                global [attrib] ‘*’
     */
     statement: ($) =>
       choice(
@@ -100,14 +103,6 @@ module.exports = grammar({
         $.if_statement,
         $.for_statement,
         $.declaration,
-        $.global_mode_statement
-      ),
-    // global * | global <attrib> * [Lua 5.5]
-    global_mode_statement: ($) =>
-      seq(
-        'global',
-        optional(field('attribute', alias($._attrib, $.attribute))),
-        '*'
       ),
 
     // retstat ::= return [explist] [';']
@@ -215,12 +210,15 @@ module.exports = grammar({
         field('end', $.expression),
         optional(seq(',', field('step', $.expression)))
       ),
+    // namelist ::= Name {',' Name}
+    _name_list: ($) => name_list($),
 
     // function funcname funcbody
     // local function Name funcbody
-    // local namelist ['=' explist]
-    // global function Name funcbody [Lua 5.5]
-    // global namelist ['=' explist] [Lua 5.5]
+    // global function Name funcbody
+    // local attnamelist [‘=’ explist]
+    // global attnamelist [‘=’ explist]
+    // global [attrib] ‘*’
     declaration: ($) =>
       choice(
         $.function_declaration,
@@ -233,7 +231,14 @@ module.exports = grammar({
           'global_declaration',
           alias($._global_function_declaration, $.function_declaration)
         ),
-        field('global_declaration', $.global_variable_declaration)
+        field(
+          'global_declaration',
+          alias($._global_variable_declaration, $.variable_declaration)
+        ),
+        field(
+          'global_declaration',
+          alias($._global_implicit_variable_declaration, $.implicit_variable_declaration)
+        )
       ),
     // function funcname funcbody
     function_declaration: ($) =>
@@ -241,7 +246,7 @@ module.exports = grammar({
     // local function Name funcbody
     _local_function_declaration: ($) =>
       seq('local', 'function', field('name', $.identifier), $._function_body),
-    // global function Name funcbody [Lua 5.5]
+    // global function Name funcbody
     _global_function_declaration: ($) =>
       seq('global', 'function', field('name', $.identifier), $._function_body),
     // funcname ::= Name {'.' Name} [':' Name]
@@ -271,65 +276,52 @@ module.exports = grammar({
         field('method', $.identifier)
       ),
 
-    // local namelist ['=' explist]
+    // local attnamelist [‘=’ explist]
     variable_declaration: ($) =>
       seq(
         'local',
         choice(
           alias($._att_name_list, $.variable_list),
-          alias($._local_variable_assignment, $.assignment_statement)
+          alias($._variable_assignment, $.assignment_statement)
         )
       ),
-    // global namelist ['=' explist] [Lua 5.5]
-    // global <attrib> namelist ['=' explist] [Lua 5.5]
-    global_variable_declaration: ($) =>
+    // global attnamelist [‘=’ explist]
+    _global_variable_declaration: ($) =>
       seq(
         'global',
         choice(
-          // global <attrib> namelist ['=' explist]
-          seq(
-            field('attribute', alias($._attrib, $.attribute)),
-            choice(
-              alias($._name_list, $.variable_list),
-              alias($._global_prefixed_variable_assignment, $.assignment_statement)
-            )
-          ),
-          // global namelist ['=' explist]
           alias($._att_name_list, $.variable_list),
-          alias($._global_variable_assignment, $.assignment_statement)
+          alias($._variable_assignment, $.assignment_statement),
         )
       ),
-    _local_variable_assignment: ($) =>
+    // attnamelist ‘=’ explist
+    _variable_assignment: ($) =>
       seq(
         alias($._att_name_list, $.variable_list),
         '=',
         alias($._variable_assignment_explist, $.expression_list)
       ),
-    _global_variable_assignment: ($) =>
-      seq(
-        alias($._att_name_list, $.variable_list),
-        '=',
-        alias($._variable_assignment_explist, $.expression_list)
-      ),
-    _global_prefixed_variable_assignment: ($) =>
-      seq(
-        alias($._name_list, $.variable_list),
-        '=',
-        alias($._variable_assignment_explist, $.expression_list)
-      ),
-    // namelist ::= Name {',' Name}
-    _name_list: ($) => name_list($),
 
-    // attnamelist ::=  Name attrib {‘,’ Name attrib}
+    // attnamelist ::= [attrib] Name [attrib] {‘,’ Name [attrib]}
     _att_name_list: ($) =>
-      list_seq(
-        seq(
-          field('name', $.identifier),
-          optional(field('attribute', alias($._attrib, $.attribute)))
+      seq(
+        optional(field('attribute', alias($._attrib, $.attribute))),
+        list_seq(
+          seq(
+            field('name', $.identifier),
+            optional(field('attribute', alias($._attrib, $.attribute)))
+          ),
+          ','
         ),
-        ','
       ),
-    // attrib ::= [‘<’ Name ‘>’]
+    // global [attrib] ‘*’
+    _global_implicit_variable_declaration: ($) =>
+      seq(
+        'global',
+        optional(field('attribute', alias($._attrib, $.attribute))),
+        '*'
+      ),
+    // attrib ::= ‘<’ Name ‘>’
     _attrib: ($) => seq('<', $.identifier, '>'),
 
     // explist ::= exp {',' exp}
@@ -478,15 +470,15 @@ module.exports = grammar({
       ),
     // '(' [parlist] ')'
     parameters: ($) => seq('(', optional($._parameter_list), ')'),
-    // parlist ::= namelist [',' '...'] | '...' | namelist [',' '...' Name] | '...' Name [Lua 5.5]
+    // parlist ::= namelist [‘,’ varargparam] | varargparam
     _parameter_list: ($) =>
       choice(
-        seq(name_list($), optional(seq(',', choice($.vararg_expression, $.named_vararg)))),
-        $.vararg_expression,
-        $.named_vararg
+        seq(name_list($), optional(seq(',', $._vararg_parameter))),
+        $._vararg_parameter
       ),
-    // '...' Name [Lua 5.5]
-    named_vararg: ($) => seq('...', field('name', $.identifier)),
+    // varargparam ::= ‘...’ [Name]
+    _vararg_parameter: ($) =>
+      seq($.vararg_expression, optional(field('name', $.identifier))),
 
     // prefixexp ::= var | functioncall | '(' exp ')'
     _prefix_expression: ($) =>

@MunifTanjim
Copy link
Collaborator

@clason @ObserverOfTime

For the new named vararg, the non-breaking change looks like this:

function a(x, y, ...x) end

function a(x, y, ...) end
image

But the more proper way would be to make a breaking change (imo).

image

Do you think the breaking change would be too much?

@clason
Copy link
Collaborator

clason commented Dec 26, 2025

(You can't push because the PR was not opened from a feature branch but the main branch.)

Since the parser is a critical component of Neovim, I would prefer to avoid breaking changes as much as possible -- certainly if the motivation is a (so far) niche feature like Lua 5.5. I also worry about the complexity this change adds (although it seems minor).

Let me push a bit of additional CI so we can see the actual fallout of this change.

@clason
Copy link
Collaborator

clason commented Dec 26, 2025

Alternative would be to add a choice between (vararg) and (named_vararg)? That could complicate things further, though.

@MunifTanjim
Copy link
Collaborator

image

This one is good enough that doesn't have any breaking changes. We can merge after the patch I added is applied.

@clason
Copy link
Collaborator

clason commented Dec 26, 2025

First my PR, then a rebase ;)

@clason
Copy link
Collaborator

clason commented Dec 26, 2025

@CppCXY could you please open a new PR from a branch created from the tip(!) of main? Otherwise we can't fix merge issues.

@clason clason closed this Dec 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants