diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..3595238 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,20 @@ +module.exports = { + 'env': { + 'commonjs': true, + 'es2021': true, + }, + 'extends': 'google', + 'overrides': [ + ], + 'parserOptions': { + 'ecmaVersion': 'latest', + 'sourceType': 'module', + }, + 'rules': { + 'indent': ['error', 2, {'SwitchCase': 1}], + 'max-len': [ + 'error', + {'code': 160, 'ignoreComments': true, 'ignoreUrls': true, 'ignoreStrings': true}, + ], + }, +}; diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..327630a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,30 @@ +name: CI +on: + workflow_dispatch: + pull_request: + push: + +jobs: + test: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: true + matrix: + os: [macos-latest, ubuntu-latest] + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 18 + - run: npm install + - run: npm test + + test_windows: + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 18 + - run: npm install + - run: npm run test-windows diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml new file mode 100644 index 0000000..39e8671 --- /dev/null +++ b/.github/workflows/fuzz.yml @@ -0,0 +1,22 @@ +name: Fuzz Parser + +on: + push: + paths: + - src/scanner.c + pull_request: + paths: + - src/scanner.c + workflow_dispatch: + +jobs: + test: + name: Parser fuzzing + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: vigoux/tree-sitter-fuzz-action@v1 + with: + language: cpp + external-scanner: src/scanner.c + time: 60 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..d94f7f3 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,19 @@ +name: Lint + +on: + push: + branches: + - master + pull_request: + branches: + - "**" + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Install modules + run: npm install + - name: Run ESLint + run: npm run lint diff --git a/grammar.js b/grammar.js index 5f83a3b..e5dade8 100644 --- a/grammar.js +++ b/grammar.js @@ -1,11 +1,23 @@ -const C = require("tree-sitter-c/grammar") +/** + * @file C++ grammar for tree-sitter + * @author Max Brunsfeld + * @license MIT + */ + +/* eslint-disable arrow-parens */ +/* eslint-disable camelcase */ +/* eslint-disable-next-line spaced-comment */ +/// +// @ts-check + +const C = require('tree-sitter-c/grammar'); const PREC = Object.assign(C.PREC, { LAMBDA: 18, NEW: C.PREC.CALL + 1, STRUCTURED_BINDING: -1, THREE_WAY: C.PREC.RELATIONAL + 1, -}) +}); const FOLD_OPERATORS = [ '+', '-', '*', '/', '%', @@ -19,7 +31,7 @@ const FOLD_OPERATORS = [ ',', '.*', '->*', 'or', 'and', 'bitor', 'xor', 'bitand', 'not_eq', -] +]; module.exports = grammar(C, { name: 'cpp', @@ -76,15 +88,15 @@ module.exports = grammar(C, { placeholder_type_specifier: $ => prec(1, seq( field('constraint', optional($._type_specifier)), - choice($.auto, alias($.decltype_auto, $.decltype)) + choice($.auto, alias($.decltype_auto, $.decltype)), )), - auto: $ => 'auto', + auto: _ => 'auto', decltype_auto: $ => seq( 'decltype', '(', $.auto, - ')' + ')', ), decltype: $ => seq( 'decltype', @@ -106,11 +118,11 @@ module.exports = grammar(C, { $.decltype, prec.right(choice( alias($.qualified_type_identifier, $.qualified_identifier), - $._type_identifier - )) + $._type_identifier, + )), ), - type_qualifier: ($, original) => choice( + type_qualifier: (_, original) => choice( original, 'mutable', 'constexpr', @@ -118,7 +130,7 @@ module.exports = grammar(C, { 'consteval', ), - type_descriptor: ($, original) => prec.right(original), + type_descriptor: (_, original) => prec.right(original), // When used in a trailing return type, these specifiers can now occur immediately before // a compound statement. This introduces a shift/reduce conflict that needs to be resolved @@ -132,46 +144,46 @@ module.exports = grammar(C, { optional(field('name', $._class_name)), optional($.virtual_specifier), optional($.base_class_clause), - field('body', $.field_declaration_list) - ) - ) + field('body', $.field_declaration_list), + ), + ), )), class_specifier: $ => seq( 'class', - $._class_declaration + $._class_declaration, ), union_specifier: $ => seq( 'union', - $._class_declaration + $._class_declaration, ), struct_specifier: $ => seq( 'struct', - $._class_declaration + $._class_declaration, ), _class_name: $ => prec.right(choice( $._type_identifier, $.template_type, - alias($.qualified_type_identifier, $.qualified_identifier) + alias($.qualified_type_identifier, $.qualified_identifier), )), function_definition: ($, original) => ({ ...original, members: original.members.map( - e => e.name !== 'body' - ? e - : field('body', choice(e.content, $.try_statement))) + (e) => e.name !== 'body' ? + e : + field('body', choice(e.content, $.try_statement))), }), - virtual_specifier: $ => choice( + virtual_specifier: _ => choice( 'final', // the only legal value here for classes - 'override' // legal for functions in addition to final, plus permutations. + 'override', // legal for functions in addition to final, plus permutations. ), - virtual: $ => choice('virtual'), + virtual: _ => choice('virtual'), _declaration_modifiers: ($, original) => choice( original, @@ -184,8 +196,8 @@ module.exports = grammar(C, { 'explicit', '(', $._expression, - ')' - )) + ')', + )), ), base_class_clause: $ => seq( @@ -195,11 +207,11 @@ module.exports = grammar(C, { optional(choice( $.access_specifier, seq($.access_specifier, $.virtual), - seq($.virtual, $.access_specifier) + seq($.virtual, $.access_specifier), )), $._class_name, - optional('...') - )) + optional('...'), + )), ), enum_specifier: $ => prec.right(seq( @@ -209,10 +221,10 @@ module.exports = grammar(C, { seq( field('name', $._class_name), optional($._enum_base_clause), - optional(field('body', $.enumerator_list)) + optional(field('body', $.enumerator_list)), ), - field('body', $.enumerator_list) - ) + field('body', $.enumerator_list), + ), )), _enum_base_clause: $ => prec.left(seq( @@ -220,19 +232,19 @@ module.exports = grammar(C, { field('base', choice( alias($.qualified_type_identifier, $.qualified_identifier), $._type_identifier, - $.sized_type_specifier - )) + $.sized_type_specifier, + )), )), // The `auto` storage class is removed in C++0x in order to allow for the `auto` type. - storage_class_specifier: ($, original) => choice( - ...original.members.filter(member => member.value !== 'auto'), + storage_class_specifier: (_, original) => choice( + ...original.members.filter((member) => member.value !== 'auto'), 'thread_local', ), dependent_type: $ => prec.dynamic(-1, prec.right(seq( 'typename', - $._type_specifier + $._type_specifier, ))), // Declarations @@ -253,14 +265,14 @@ module.exports = grammar(C, { alias($.constructor_or_destructor_definition, $.function_definition), alias($.operator_cast_declaration, $.declaration), alias($.operator_cast_definition, $.function_definition), - ) + ), ), template_instantiation: $ => seq( 'template', optional($._declaration_specifiers), field('declarator', $._declarator), - ';' + ';', ), template_parameter_list: $ => seq( @@ -272,27 +284,27 @@ module.exports = grammar(C, { $.variadic_parameter_declaration, $.variadic_type_parameter_declaration, $.optional_type_parameter_declaration, - $.template_template_parameter_declaration + $.template_template_parameter_declaration, )), - alias(token(prec(1, '>')), '>') + alias(token(prec(1, '>')), '>'), ), type_parameter_declaration: $ => prec(1, seq( choice('typename', 'class'), - optional($._type_identifier) + optional($._type_identifier), )), variadic_type_parameter_declaration: $ => prec(1, seq( choice('typename', 'class'), '...', - optional($._type_identifier) + optional($._type_identifier), )), optional_type_parameter_declaration: $ => seq( choice('typename', 'class'), optional(field('name', $._type_identifier)), '=', - field('default_type', $._type_specifier) + field('default_type', $._type_specifier), ), template_template_parameter_declaration: $ => seq( @@ -301,8 +313,8 @@ module.exports = grammar(C, { choice( $.type_parameter_declaration, $.variadic_type_parameter_declaration, - $.optional_type_parameter_declaration - ) + $.optional_type_parameter_declaration, + ), ), parameter_list: $ => seq( @@ -311,34 +323,34 @@ module.exports = grammar(C, { $.parameter_declaration, $.optional_parameter_declaration, $.variadic_parameter_declaration, - '...' + '...', )), - ')' + ')', ), optional_parameter_declaration: $ => seq( $._declaration_specifiers, field('declarator', optional($._declarator)), '=', - field('default_value', $._expression) + field('default_value', $._expression), ), variadic_parameter_declaration: $ => seq( $._declaration_specifiers, field('declarator', choice( $.variadic_declarator, - alias($.variadic_reference_declarator, $.reference_declarator) - )) + alias($.variadic_reference_declarator, $.reference_declarator), + )), ), variadic_declarator: $ => seq( '...', - optional($.identifier) + optional($.identifier), ), variadic_reference_declarator: $ => seq( choice('&&', '&'), - $.variadic_declarator + $.variadic_declarator, ), init_declarator: ($, original) => choice( @@ -347,9 +359,9 @@ module.exports = grammar(C, { field('declarator', $._declarator), field('value', choice( $.argument_list, - $.initializer_list - )) - ) + $.initializer_list, + )), + ), ), operator_cast: $ => prec.right(1, seq( @@ -360,11 +372,11 @@ module.exports = grammar(C, { // Avoid ambiguity between compound statement and initializer list in a construct like: // A b {}; - compound_statement: ($, original) => prec(-1, original), + compound_statement: (_, original) => prec(-1, original), field_initializer_list: $ => seq( ':', - commaSep1($.field_initializer) + commaSep1($.field_initializer), ), field_initializer: $ => prec(1, seq( @@ -374,7 +386,7 @@ module.exports = grammar(C, { alias($.qualified_field_identifier, $.qualified_identifier), ), choice($.initializer_list, $.argument_list), - optional('...') + optional('...'), )), _field_declaration_list_item: ($, original) => choice( @@ -390,7 +402,7 @@ module.exports = grammar(C, { $.alias_declaration, $.using_declaration, $.type_definition, - $.static_assert_declaration + $.static_assert_declaration, ), field_declaration: $ => seq( @@ -399,9 +411,9 @@ module.exports = grammar(C, { optional(choice( $.bitfield_clause, field('default_value', $.initializer_list), - seq('=', field('default_value', choice($._expression, $.initializer_list))) + seq('=', field('default_value', choice($._expression, $.initializer_list))), )), - ';' + ';', ), inline_method_definition: $ => seq( @@ -410,39 +422,39 @@ module.exports = grammar(C, { choice( field('body', choice($.compound_statement, $.try_statement)), $.default_method_clause, - $.delete_method_clause - ) + $.delete_method_clause, + ), ), _constructor_specifiers: $ => choice( $._declaration_modifiers, - $.explicit_function_specifier + $.explicit_function_specifier, ), operator_cast_definition: $ => seq( repeat($._constructor_specifiers), field('declarator', choice( $.operator_cast, - alias($.qualified_operator_cast_identifier, $.qualified_identifier) + alias($.qualified_operator_cast_identifier, $.qualified_identifier), )), - field('body', choice($.compound_statement, $.try_statement)) + field('body', choice($.compound_statement, $.try_statement)), ), operator_cast_declaration: $ => prec(1, seq( repeat($._constructor_specifiers), field('declarator', choice( $.operator_cast, - alias($.qualified_operator_cast_identifier, $.qualified_identifier) + alias($.qualified_operator_cast_identifier, $.qualified_identifier), )), optional(seq('=', field('default_value', $._expression))), - ';' + ';', )), constructor_try_statement: $ => seq( 'try', optional($.field_initializer_list), field('body', $.compound_statement), - repeat1($.catch_clause) + repeat1($.catch_clause), ), constructor_or_destructor_definition: $ => seq( @@ -451,22 +463,22 @@ module.exports = grammar(C, { choice( seq( optional($.field_initializer_list), - field('body', $.compound_statement) + field('body', $.compound_statement), ), alias($.constructor_try_statement, $.try_statement), $.default_method_clause, - $.delete_method_clause - ) + $.delete_method_clause, + ), ), constructor_or_destructor_declaration: $ => seq( repeat($._constructor_specifiers), field('declarator', $.function_declarator), - ';' + ';', ), - default_method_clause: $ => seq('=', 'default', ';'), - delete_method_clause: $ => seq('=', 'delete', ';'), + default_method_clause: _ => seq('=', 'default', ';'), + delete_method_clause: _ => seq('=', 'delete', ';'), friend_declaration: $ => seq( 'friend', @@ -477,17 +489,17 @@ module.exports = grammar(C, { optional(choice( 'class', 'struct', - 'union' + 'union', )), - $._class_name, ';' - ) - ) + $._class_name, ';', + ), + ), ), - access_specifier: $ => choice( + access_specifier: _ => choice( 'public', 'private', - 'protected' + 'protected', ), _declarator: ($, original) => choice( @@ -497,19 +509,19 @@ module.exports = grammar(C, { $.template_function, $.operator_name, $.destructor_name, - $.structured_binding_declarator + $.structured_binding_declarator, ), _field_declarator: ($, original) => choice( original, alias($.reference_field_declarator, $.reference_declarator), $.template_method, - $.operator_name + $.operator_name, ), _abstract_declarator: ($, original) => choice( original, - $.abstract_reference_declarator + $.abstract_reference_declarator, ), reference_declarator: $ => prec.dynamic(1, prec.right(seq(choice('&', '&&'), $._declarator))), @@ -517,10 +529,10 @@ module.exports = grammar(C, { abstract_reference_declarator: $ => prec.right(seq(choice('&', '&&'), optional($._abstract_declarator))), structured_binding_declarator: $ => prec.dynamic(PREC.STRUCTURED_BINDING, seq( - '[', commaSep1($.identifier), ']' + '[', commaSep1($.identifier), ']', )), - ref_qualifier: $ => choice('&', '&&'), + ref_qualifier: _ => choice('&', '&&'), _function_declarator_seq: $ => prec.right(seq( field('parameters', $.parameter_list), @@ -535,8 +547,8 @@ module.exports = grammar(C, { optional($.trailing_return_type), optional(choice( repeat($.virtual_specifier), - $.requires_clause - )) + $.requires_clause, + )), )), function_declarator: $ => prec.dynamic(1, seq( @@ -573,22 +585,22 @@ module.exports = grammar(C, { '(', commaSep($.type_descriptor), ')', - ) + ), ), template_type: $ => seq( field('name', $._type_identifier), - field('arguments', $.template_argument_list) + field('arguments', $.template_argument_list), ), template_method: $ => seq( field('name', $._field_identifier), - field('arguments', $.template_argument_list) + field('arguments', $.template_argument_list), ), template_function: $ => seq( field('name', $.identifier), - field('arguments', $.template_argument_list) + field('arguments', $.template_argument_list), ), template_argument_list: $ => seq( @@ -596,9 +608,9 @@ module.exports = grammar(C, { commaSep(choice( prec.dynamic(3, $.type_descriptor), prec.dynamic(2, alias($.type_parameter_pack_expansion, $.parameter_pack_expansion)), - prec.dynamic(1, $._expression) + prec.dynamic(1, $._expression), )), - alias(token(prec(1, '>')), '>') + alias(token(prec(1, '>')), '>'), ), namespace_definition: $ => seq( @@ -609,7 +621,7 @@ module.exports = grammar(C, { $._namespace_identifier, $.nested_namespace_specifier, ))), - field('body', $.declaration_list) + field('body', $.declaration_list), ), namespace_alias_definition: $ => seq( @@ -618,14 +630,14 @@ module.exports = grammar(C, { '=', choice( $._namespace_identifier, - $.nested_namespace_specifier + $.nested_namespace_specifier, ), - ';' + ';', ), _namespace_specifier: $ => seq( optional('inline'), - $._namespace_identifier + $._namespace_identifier, ), nested_namespace_specifier: $ => prec(1, seq( @@ -633,8 +645,8 @@ module.exports = grammar(C, { '::', choice( $.nested_namespace_specifier, - $._namespace_specifier - ) + $._namespace_specifier, + ), )), using_declaration: $ => seq( @@ -642,9 +654,9 @@ module.exports = grammar(C, { optional(choice('namespace', 'enum')), choice( $.identifier, - $.qualified_identifier + $.qualified_identifier, ), - ';' + ';', ), alias_declaration: $ => seq( @@ -653,7 +665,7 @@ module.exports = grammar(C, { repeat($.attribute_declaration), '=', field('type', $.type_descriptor), - ';' + ';', ), static_assert_declaration: $ => seq( @@ -666,10 +678,10 @@ module.exports = grammar(C, { $.string_literal, $.raw_string_literal, $.concatenated_string, - )) + )), )), ')', - ';' + ';', ), concept_definition: $ => seq( @@ -677,7 +689,7 @@ module.exports = grammar(C, { field('name', $.identifier), '=', $._expression, - ';' + ';', ), // Statements @@ -694,13 +706,13 @@ module.exports = grammar(C, { switch_statement: $ => seq( 'switch', field('condition', $.condition_clause), - field('body', $.compound_statement) + field('body', $.compound_statement), ), while_statement: $ => seq( 'while', field('condition', $.condition_clause), - field('body', $._statement) + field('body', $._statement), ), if_statement: $ => prec.right(seq( @@ -710,8 +722,8 @@ module.exports = grammar(C, { field('consequence', $._statement), optional(seq( 'else', - field('alternative', $._statement) - )) + field('alternative', $._statement), + )), )), for_range_loop: $ => seq( @@ -726,7 +738,7 @@ module.exports = grammar(C, { $.initializer_list, )), ')', - field('body', $._statement) + field('body', $._statement), ), init_statement: $ => choice( @@ -756,44 +768,44 @@ module.exports = grammar(C, { field('value', $._expression), ), field('value', $.initializer_list), - ) + ), ), return_statement: ($, original) => seq( choice( original, - seq('return', $.initializer_list, ';') - ) + seq('return', $.initializer_list, ';'), + ), ), co_return_statement: $ => seq( 'co_return', optional($._expression), - ';' + ';', ), co_yield_statement: $ => seq( 'co_yield', $._expression, - ';' + ';', ), throw_statement: $ => seq( 'throw', optional($._expression), - ';' + ';', ), try_statement: $ => seq( 'try', field('body', $.compound_statement), - repeat1($.catch_clause) + repeat1($.catch_clause), ), catch_clause: $ => seq( 'catch', field('parameters', $.parameter_list), - field('body', $.compound_statement) + field('body', $.compound_statement), ), // Expressions @@ -813,7 +825,7 @@ module.exports = grammar(C, { $.this, $.raw_string_literal, $.user_defined_literal, - $.fold_expression + $.fold_expression, ), raw_string_literal: $ => seq( @@ -838,18 +850,18 @@ module.exports = grammar(C, { field('argument', $._expression), '[', field('index', choice($._expression, $.initializer_list)), - ']' + ']', )), call_expression: ($, original) => choice(original, seq( field('function', $.primitive_type), - field('arguments', $.argument_list) + field('arguments', $.argument_list), )), co_await_expression: $ => prec.left(PREC.UNARY, seq( field('operator', 'co_await'), - field('argument', $._expression) + field('argument', $._expression), )), new_expression: $ => prec.right(PREC.NEW, seq( @@ -860,22 +872,22 @@ module.exports = grammar(C, { field('declarator', optional($.new_declarator)), field('arguments', optional(choice( $.argument_list, - $.initializer_list - ))) + $.initializer_list, + ))), )), new_declarator: $ => prec.right(seq( '[', field('length', $._expression), ']', - optional($.new_declarator) + optional($.new_declarator), )), delete_expression: $ => seq( optional('::'), 'delete', optional(seq('[', ']')), - $._expression + $._expression, ), field_expression: ($, original) => choice( @@ -883,14 +895,14 @@ module.exports = grammar(C, { seq( prec(PREC.FIELD, seq( field('argument', $._expression), - choice('.', '->') + choice('.', '->'), )), field('field', choice( $.destructor_name, $.template_method, - alias($.dependent_field_identifier, $.dependent_name) - )) - ) + alias($.dependent_field_identifier, $.dependent_name), + )), + ), ), type_requirement: $ => seq('typename', $._class_name), @@ -899,13 +911,13 @@ module.exports = grammar(C, { '{', $._expression, '}', optional('noexcept'), optional($.trailing_return_type), - ';' + ';', ), _requirement: $ => choice( alias($.expression_statement, $.simple_requirement), $.type_requirement, - $.compound_requirement + $.compound_requirement, ), requirement_seq: $ => seq('{', repeat($._requirement), '}'), @@ -913,13 +925,13 @@ module.exports = grammar(C, { constraint_conjunction: $ => prec.left(PREC.LOGICAL_AND, seq( field('left', $._requirement_clause_constraint), field('operator', choice('&&', 'and')), - field('right', $._requirement_clause_constraint)) + field('right', $._requirement_clause_constraint)), ), constraint_disjunction: $ => prec.left(PREC.LOGICAL_OR, seq( field('left', $._requirement_clause_constraint), field('operator', choice('||', 'or')), - field('right', $._requirement_clause_constraint)) + field('right', $._requirement_clause_constraint)), ), _requirement_clause_constraint: $ => choice( @@ -941,7 +953,7 @@ module.exports = grammar(C, { requires_clause: $ => seq( 'requires', - field('constraint', $._requirement_clause_constraint) + field('constraint', $._requirement_clause_constraint), ), requires_parameter_list: $ => seq( @@ -951,13 +963,13 @@ module.exports = grammar(C, { $.optional_parameter_declaration, $.variadic_parameter_declaration, )), - ')' + ')', ), requires_expression: $ => seq( 'requires', field('parameters', optional(alias($.requires_parameter_list, $.parameter_list))), - field('requirements', $.requirement_seq) + field('requirements', $.requirement_seq), ), lambda_expression: $ => seq( @@ -967,7 +979,7 @@ module.exports = grammar(C, { optional(field('constraint', $.requires_clause)), )), optional(field('declarator', $.abstract_function_declarator)), - field('body', $.compound_statement) + field('body', $.compound_statement), ), lambda_capture_specifier: $ => prec(PREC.LAMBDA, seq( @@ -977,31 +989,31 @@ module.exports = grammar(C, { commaSep($._expression), seq( $.lambda_default_capture, - ',', commaSep1($._expression) - ) + ',', commaSep1($._expression), + ), ), - ']' + ']', )), - lambda_default_capture: $ => choice('=', '&'), + lambda_default_capture: _ => choice('=', '&'), - _fold_operator: $ => choice(...FOLD_OPERATORS), - _binary_fold_operator: $ => choice(...FOLD_OPERATORS.map(operator => seq(field('operator', operator), '...', operator))), + _fold_operator: _ => choice(...FOLD_OPERATORS), + _binary_fold_operator: _ => choice(...FOLD_OPERATORS.map((operator) => seq(field('operator', operator), '...', operator))), _unary_left_fold: $ => seq( field('left', '...'), field('operator', $._fold_operator), - field('right', $._expression) + field('right', $._expression), ), _unary_right_fold: $ => seq( field('left', $._expression), field('operator', $._fold_operator), - field('right', '...') + field('right', '...'), ), _binary_fold: $ => seq( field('left', $._expression), $._binary_fold_operator, - field('right', $._expression) + field('right', $._expression), ), fold_expression: $ => seq( @@ -1009,19 +1021,19 @@ module.exports = grammar(C, { choice( $._unary_right_fold, $._unary_left_fold, - $._binary_fold + $._binary_fold, ), - ')' + ')', ), parameter_pack_expansion: $ => prec(-1, seq( field('pattern', $._expression), - '...' + '...', )), type_parameter_pack_expansion: $ => seq( field('pattern', $.type_descriptor), - '...' + '...', ), sizeof_expression: ($, original) => prec.right(PREC.SIZEOF, choice( @@ -1030,7 +1042,7 @@ module.exports = grammar(C, { 'sizeof', '...', '(', field('value', $.identifier), - ')' + ')', ), )), @@ -1038,8 +1050,8 @@ module.exports = grammar(C, { original, prec.left(PREC.UNARY, seq( field('operator', choice('not', 'compl')), - field('argument', $._expression) - )) + field('argument', $._expression), + )), ), binary_expression: ($, original) => { @@ -1058,16 +1070,17 @@ module.exports = grammar(C, { ...table.map(([operator, precedence]) => { return prec.left(precedence, seq( field('left', $._expression), + // @ts-ignore field('operator', operator), - field('right', $._expression) - )) + field('right', $._expression), + )); })); }, argument_list: $ => seq( '(', commaSep(choice($._expression, $.initializer_list)), - ')' + ')', ), destructor_name: $ => prec(1, seq('~', $.identifier)), @@ -1076,8 +1089,8 @@ module.exports = grammar(C, { original, seq( field('type', $._class_name), - field('value', $.initializer_list) - ) + field('value', $.initializer_list), + ), ), dependent_identifier: $ => seq('template', $.template_function), @@ -1089,7 +1102,7 @@ module.exports = grammar(C, { $._namespace_identifier, $.template_type, $.decltype, - alias($.dependent_type_identifier, $.dependent_name) + alias($.dependent_type_identifier, $.dependent_name), ))), '::', )), @@ -1100,8 +1113,8 @@ module.exports = grammar(C, { alias($.dependent_field_identifier, $.dependent_name), alias($.qualified_field_identifier, $.qualified_identifier), $.template_method, - $._field_identifier - )) + $._field_identifier, + )), ), qualified_identifier: $ => seq( @@ -1112,7 +1125,7 @@ module.exports = grammar(C, { $.template_function, $.identifier, $.operator_name, - $.destructor_name + $.destructor_name, )), ), @@ -1122,7 +1135,7 @@ module.exports = grammar(C, { alias($.dependent_type_identifier, $.dependent_name), alias($.qualified_type_identifier, $.qualified_identifier), $.template_type, - $._type_identifier + $._type_identifier, )), ), @@ -1130,8 +1143,8 @@ module.exports = grammar(C, { $._scope_resolution, field('name', choice( alias($.qualified_operator_cast_identifier, $.qualified_identifier), - $.operator_cast - )) + $.operator_cast, + )), ), _assignment_left_expression: ($, original) => choice( @@ -1146,10 +1159,10 @@ module.exports = grammar(C, { field('operator', choice( 'and_eq', 'or_eq', - 'xor_eq' + 'xor_eq', )), - field('right', $._expression) - )) + field('right', $._expression), + )), ), operator_name: $ => prec(1, seq( @@ -1173,19 +1186,19 @@ module.exports = grammar(C, { 'not', 'xor_eq', 'and_eq', 'or_eq', 'not_eq', 'and', 'or', seq(choice('new', 'delete'), optional('[]')), - seq('""', $.identifier) - ) + seq('""', $.identifier), + ), )), - this: $ => 'this', - nullptr: $ => 'nullptr', + this: _ => 'this', + nullptr: _ => 'nullptr', concatenated_string: $ => seq( choice($.raw_string_literal, $.string_literal), - repeat1(choice($.raw_string_literal, $.string_literal)) + repeat1(choice($.raw_string_literal, $.string_literal)), ), - literal_suffix: $ => token.immediate(/[a-zA-Z_]\w*/), + literal_suffix: _ => token.immediate(/[a-zA-Z_]\w*/), user_defined_literal: $ => seq( choice( @@ -1193,19 +1206,35 @@ module.exports = grammar(C, { $.char_literal, $.string_literal, $.raw_string_literal, - $.concatenated_string + $.concatenated_string, ), - $.literal_suffix + $.literal_suffix, ), - _namespace_identifier: $ => alias($.identifier, $.namespace_identifier) - } + _namespace_identifier: $ => alias($.identifier, $.namespace_identifier), + }, }); +/** + * Creates a rule to optionally match one or more of the rules separated by a comma + * + * @param {Rule} rule + * + * @return {ChoiceRule} + * + */ function commaSep(rule) { return optional(commaSep1(rule)); } +/** + * Creates a rule to match one or more of the rules separated by a comma + * + * @param {Rule} rule + * + * @return {SeqRule} + * + */ function commaSep1(rule) { return seq(rule, repeat(seq(',', rule))); } diff --git a/package.json b/package.json index 10913a2..85f1579 100644 --- a/package.json +++ b/package.json @@ -17,10 +17,14 @@ "nan": "^2.14.0" }, "devDependencies": { + "eslint": "^8.43.0", + "eslint-config-google": "^0.14.0", "tree-sitter-c": "^0.20.2", "tree-sitter-cli": "^0.20.0" }, "scripts": { + "build": "tree-sitter generate && node-gyp build", + "lint": "eslint grammar.js", "test": "tree-sitter test && tree-sitter parse examples/* --quiet --time", "test-windows": "tree-sitter test" },