From 0fc8c8cc42191c75611f99d4fb711ee40edb718a Mon Sep 17 00:00:00 2001 From: John Drouhard Date: Fri, 20 Sep 2024 09:58:49 -0500 Subject: [PATCH] lambda expressions: support capture syntax through cpp20 --- grammar.js | 37 ++++++++++++- test/corpus/expressions.txt | 100 +++++++++++++++++++++++++++++++++--- 2 files changed, 129 insertions(+), 8 deletions(-) diff --git a/grammar.js b/grammar.js index d55da2c..b9f4e5f 100644 --- a/grammar.js +++ b/grammar.js @@ -78,6 +78,11 @@ module.exports = grammar(C, { [$.expression, $._declarator], [$.expression, $.structured_binding_declarator], [$.expression, $._declarator, $.type_specifier], + [$.expression, $.identifier_parameter_pack_expansion], + [$.expression, $._lambda_capture_identifier], + [$.expression, $._lambda_capture], + [$.expression, $.structured_binding_declarator, $._lambda_capture_identifier], + [$.structured_binding_declarator, $._lambda_capture_identifier], [$.parameter_list, $.argument_list], [$.type_specifier, $.call_expression], [$._declaration_specifiers, $._constructor_specifiers], @@ -1094,10 +1099,10 @@ module.exports = grammar(C, { '[', choice( $.lambda_default_capture, - commaSep($.expression), + commaSep($._lambda_capture), seq( $.lambda_default_capture, - ',', commaSep1($.expression), + ',', commaSep1($._lambda_capture), ), ), ']', @@ -1105,6 +1110,29 @@ module.exports = grammar(C, { lambda_default_capture: _ => choice('=', '&'), + _lambda_capture_identifier: $ => seq( + optional('&'), + choice( + $.identifier, + $.qualified_identifier, + alias($.identifier_parameter_pack_expansion, $.parameter_pack_expansion), + ), + ), + + lambda_capture_initializer: $ => seq( + optional('&'), + optional('...'), + field('left', $.identifier), + '=', + field('right', $.expression), + ), + + _lambda_capture: $ => choice( + seq(optional('*'), $.this), + $._lambda_capture_identifier, + $.lambda_capture_initializer, + ), + _fold_operator: _ => choice(...FOLD_OPERATORS), _binary_fold_operator: _ => choice(...FOLD_OPERATORS.map((operator) => seq(field('operator', operator), '...', operator))), @@ -1144,6 +1172,11 @@ module.exports = grammar(C, { '...', ), + identifier_parameter_pack_expansion: $ => seq( + field('pattern', $.identifier), + '...', + ), + sizeof_expression: ($, original) => prec.right(PREC.SIZEOF, choice( original, seq( diff --git a/test/corpus/expressions.txt b/test/corpus/expressions.txt index d6ab9ca..aa394c7 100644 --- a/test/corpus/expressions.txt +++ b/test/corpus/expressions.txt @@ -278,22 +278,30 @@ auto f = [&](int x) -> bool { return true; }; -auto g = [x, y](int z) { +auto f = [x, y](int z) { return false; }; -auto h = [] { +auto f = [] { return false; }; -auto i = [] () { +auto f = [] () { return T(); }; -auto i = [] requires Hashable { +auto f = [] requires Hashable { return T(); }; +auto f = [... args = std::forward(args)](auto &&func) mutable { + return std::invoke(std::forward(func), std::forward(args)...); +}; + +auto f = [&arg, &...etc = etc] {}; + +auto f = [=, *this, &args...] {}; + -------------------------------------------------------------------------------- (translation_unit @@ -380,7 +388,87 @@ auto i = [] requires Hashable { (return_statement (call_expression (identifier) - (argument_list)))))))) + (argument_list))))))) + (declaration + (placeholder_type_specifier + (auto)) + (init_declarator + (identifier) + (lambda_expression + (lambda_capture_specifier + (lambda_capture_initializer + (identifier) + (call_expression + (qualified_identifier + (namespace_identifier) + (template_function + (identifier) + (template_argument_list + (type_descriptor + (type_identifier))))) + (argument_list + (identifier))))) + (abstract_function_declarator + (parameter_list + (parameter_declaration + (placeholder_type_specifier + (auto)) + (reference_declarator + (identifier)))) + (type_qualifier)) + (compound_statement + (return_statement + (call_expression + (qualified_identifier + (namespace_identifier) + (identifier)) + (argument_list + (call_expression + (qualified_identifier + (namespace_identifier) + (template_function + (identifier) + (template_argument_list + (type_descriptor + (decltype + (identifier)))))) + (argument_list + (identifier))) + (parameter_pack_expansion + (call_expression + (qualified_identifier + (namespace_identifier) + (template_function + (identifier) + (template_argument_list + (type_descriptor + (type_identifier))))) + (argument_list + (identifier))))))))))) + (declaration + (placeholder_type_specifier + (auto)) + (init_declarator + (identifier) + (lambda_expression + (lambda_capture_specifier + (identifier) + (lambda_capture_initializer + (identifier) + (identifier))) + (compound_statement)))) + (declaration + (placeholder_type_specifier + (auto)) + (init_declarator + (identifier) + (lambda_expression + (lambda_capture_specifier + (lambda_default_capture) + (this) + (parameter_pack_expansion + (identifier))) + (compound_statement))))) ================================================================================ Nested template calls @@ -1555,4 +1643,4 @@ template void negateValues(Args... args) { (unary_expression (identifier))) (string_literal - (string_content)))))))))) \ No newline at end of file + (string_content))))))))))