Support multidimensional subscripts

This change allows commas inside subscripts.

```cpp
auto x = a[1, 2, 3];
```

From C++23, array subscripts work like arguments to `operator[]` as an n-ary
function.

Before C++23, `operator[]` must be a unary function, but before C++20, it's
possible to use the comma operator inside subscript expressions - and this is
done in libraries that use expression templates to achieve multidimensional
array syntax.

Use of the comma operator in subscript expressions was deprecated in C++20 to
make way for the C++23 change to n-ary `operator[]`.
pull/708/head
Ben Deane 2023-08-05 23:29:08 +07:00
parent f88bf81238
commit 472002f3bf
5 changed files with 318112 additions and 316202 deletions

@ -880,11 +880,14 @@ module.exports = grammar(C, {
subscript_expression: $ => prec(PREC.SUBSCRIPT, seq(
field('argument', $._expression),
'[',
field('index', choice($._expression, $.initializer_list)),
']',
field('indices', $.subscript_argument_list),
)),
subscript_argument_list: $ => seq(
'[',
commaSep(choice($._expression, $.initializer_list)),
']',
),
call_expression: ($, original) => choice(original, seq(
field('function', $.primitive_type),

87
src/grammar.json vendored

@ -6860,30 +6860,13 @@
"name": "_expression"
}
},
{
"type": "STRING",
"value": "["
},
{
"type": "FIELD",
"name": "index",
"name": "indices",
"content": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "_expression"
},
{
"type": "SYMBOL",
"name": "initializer_list"
}
]
"type": "SYMBOL",
"name": "subscript_argument_list"
}
},
{
"type": "STRING",
"value": "]"
}
]
}
@ -11439,6 +11422,70 @@
}
]
},
"subscript_argument_list": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "["
},
{
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "_expression"
},
{
"type": "SYMBOL",
"name": "initializer_list"
}
]
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "_expression"
},
{
"type": "SYMBOL",
"name": "initializer_list"
}
]
}
]
}
}
]
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": "]"
}
]
},
"co_await_expression": {
"type": "PREC_LEFT",
"value": 14,

@ -5794,6 +5794,25 @@
]
}
},
{
"type": "subscript_argument_list",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": false,
"types": [
{
"type": "_expression",
"named": true
},
{
"type": "initializer_list",
"named": true
}
]
}
},
{
"type": "subscript_designator",
"named": true,
@ -5823,16 +5842,12 @@
}
]
},
"index": {
"indices": {
"multiple": false,
"required": true,
"types": [
{
"type": "_expression",
"named": true
},
{
"type": "initializer_list",
"type": "subscript_argument_list",
"named": true
}
]

634150
src/parser.c vendored

File diff suppressed because it is too large Load Diff

@ -1168,22 +1168,26 @@ array_[{i}] = s[{1,2,3}];
(assignment_expression
(subscript_expression
(identifier)
(identifier))
(subscript_argument_list
(identifier)))
(subscript_expression
(identifier)
(identifier))))
(subscript_argument_list
(identifier)))))
(expression_statement
(assignment_expression
(subscript_expression
(identifier)
(initializer_list
(identifier)))
(subscript_argument_list
(initializer_list
(identifier))))
(subscript_expression
(identifier)
(initializer_list
(number_literal)
(number_literal)
(number_literal))))))
(subscript_argument_list
(initializer_list
(number_literal)
(number_literal)
(number_literal)))))))
================================================================================
Coroutines
@ -1330,3 +1334,24 @@ foo and_eq bar();
(call_expression
(identifier)
(argument_list)))))
================================================================================
Subscript expression
================================================================================
auto x = a[1, 2, 3];
--------------------------------------------------------------------------------
(translation_unit
(declaration
(placeholder_type_specifier
(auto))
(init_declarator
(identifier)
(subscript_expression
(identifier)
(subscript_argument_list
(number_literal)
(number_literal)
(number_literal))))))