From 1d2853ef08e95d54863fd04e99fc4e67ccda0bd5 Mon Sep 17 00:00:00 2001 From: mx42 <49202620+Maan2003@users.noreply.github.com> Date: Fri, 21 Jul 2023 00:00:33 +0000 Subject: [PATCH] Treesitter: fix where clause (#2998) follow up to #2902 --- utils/treesitter/grammar.js | 92 +++++++++++++++++--------------- utils/treesitter/test_runner.cpp | 14 ----- 2 files changed, 50 insertions(+), 56 deletions(-) diff --git a/utils/treesitter/grammar.js b/utils/treesitter/grammar.js index 56b6e667b3b4..0a64ed400b14 100644 --- a/utils/treesitter/grammar.js +++ b/utils/treesitter/grammar.js @@ -18,24 +18,24 @@ function comma_sep(thing) { // This is based on toolchain/parser/precedence.cpp const PREC = { - TermPrefix: 11, - TermPostfix: 11, - NumericPrefix: 10, - NumericPostfix: 10, - Multiplicative: 9, - Additive: 8, - BitwisePrefix: 7, - BitwiseAnd: 6, - BitwiseOr: 6, - BitwiseXor: 6, - BitShift: 6, - TypePostfix: 5, - LogicalPrefix: 4, - Relational: 3, - LogicalAnd: 2, - LogicalOr: 2, + TermPrefix: 12, + TermPostfix: 12, + NumericPrefix: 11, + NumericPostfix: 11, + Multiplicative: 10, + Additive: 9, + BitwisePrefix: 8, + BitwiseAnd: 7, + BitwiseOr: 7, + BitwiseXor: 7, + BitShift: 7, + TypePostfix: 6, + LogicalPrefix: 5, + Relational: 4, + LogicalAnd: 3, + LogicalOr: 3, + IfExpression: 2, WhereClause: 1, - IfExpression: 1, }; module.exports = grammar({ @@ -198,10 +198,11 @@ module.exports = grammar({ $.paren_pattern, // alternative patterns // example: Optional(i32).Some(x: i32) - seq($._expression, $.paren_pattern) + seq($._simple_expression, $.paren_pattern) ), - _pattern: ($) => choice($._pattern_without_expression, $._expression), + _pattern: ($) => + choice($._pattern_without_expression, $._simple_expression), unary_prefix_expression: ($) => { const table = [ @@ -252,13 +253,14 @@ module.exports = grammar({ // This should be non-associative but conflicts are not allowed in tree-sitter as_expression: ($) => prec.left(seq($._expression, 'as', $._expression)), - ref_expression: ($) => prec.right(PREC.TermPrefix, seq('&', $._expression)), + ref_expression: ($) => + prec.right(PREC.TermPrefix, seq('&', $._simple_expression)), deref_expression: ($) => - prec.right(PREC.TermPrefix, seq('*', $._expression)), + prec.right(PREC.TermPrefix, seq('*', $._simple_expression)), fn_type_expression: ($) => - prec.left(seq('__Fn', $.paren_expression, '->', $._expression)), + prec.left(seq('__Fn', $.paren_expression, '->', $._simple_expression)), if_expression: ($) => prec( @@ -269,7 +271,10 @@ module.exports = grammar({ paren_expression: ($) => seq('(', comma_sep($._expression), ')'), index_expression: ($) => - prec(PREC.TermPostfix, seq($._expression, '[', $._expression, ']')), + prec( + PREC.TermPostfix, + seq($._simple_expression, '[', $._expression, ']') + ), designator: ($) => seq('.', choice('base', $.ident)), @@ -277,7 +282,7 @@ module.exports = grammar({ prec( PREC.TermPostfix, seq( - $._expression, + $._simple_expression, choice( '++', '--', @@ -289,51 +294,54 @@ module.exports = grammar({ ), where_clause: ($) => - prec( - PREC.WhereClause, - choice( - seq($._expression, '==', $._expression), - seq($._expression, 'impls', $._expression), - seq($._expression, '=', $._expression), - // TODO: Fix conflict with logical and - prec.left(seq($.where_clause, 'and', $.where_clause)) + choice( + seq($._simple_expression, '==', $._simple_expression), + seq($._simple_expression, 'impls', $._simple_expression), + seq($._simple_expression, '=', $._simple_expression), + prec.left( + PREC.WhereClause + 1, + seq($.where_clause, 'and', $.where_clause) ) ), where_expression: ($) => - prec.left(PREC.TermPostfix, seq($._expression, 'where', $.where_clause)), + prec.left(PREC.WhereClause, seq($._expression, 'where', $.where_clause)), call_expression: ($) => - prec(PREC.TermPostfix, seq($._expression, $.paren_expression)), + prec(PREC.TermPostfix, seq($._simple_expression, $.paren_expression)), pointer_expression: ($) => - prec(PREC.TypePostfix, seq($._expression, $.postfix_star)), + prec(PREC.TypePostfix, seq($._simple_expression, $.postfix_star)), - _expression: ($) => + _simple_expression: ($) => choice( $.array_literal, - $.as_expression, - $.binary_expression, $.builtin_type, $.call_expression, $.deref_expression, $.fn_type_expression, $.ident, - $.if_expression, $.index_expression, $.literal, $.paren_expression, $.pointer_expression, $.postfix_expression, $.ref_expression, - $.unary_prefix_expression, - $.where_expression, 'self', - // TODO: Remove these two once `where` clauses don't use the expression rule '.Self', $.designator ), + _expression: ($) => + choice( + $.as_expression, + $.binary_expression, + $.if_expression, + $.unary_prefix_expression, + $.where_expression, + $._simple_expression + ), + var_declaration: ($) => seq( 'var', diff --git a/utils/treesitter/test_runner.cpp b/utils/treesitter/test_runner.cpp index 76d6860972e1..e70b5b151443 100644 --- a/utils/treesitter/test_runner.cpp +++ b/utils/treesitter/test_runner.cpp @@ -36,18 +36,10 @@ auto main(int argc, char** argv) -> int { ts_parser_set_language(parser, tree_sitter_carbon()); std::vector failed; - std::vector skipped; for (int i = 1; i < argc; i++) { std::string file_path = argv[i]; std::string source = ReadFile(file_path); - // `and` in where clauses is not parsed correctly. - // TODO: remove once where clause is implemented correctly. - if (source.find("where") != std::string::npos && - source.find("and") != std::string::npos) { - skipped.push_back(file_path); - continue; - } auto* tree = ts_parser_parse_string(parser, nullptr, source.data(), source.size()); @@ -64,15 +56,9 @@ auto main(int argc, char** argv) -> int { ts_tree_delete(tree); } ts_parser_delete(parser); - for (const auto& file : skipped) { - std::cout << "SKIPPED " << file << "\n"; - } for (const auto& file : failed) { std::cout << "FAILED " << file << "\n"; } - if (!skipped.empty()) { - std::cout << skipped.size() << " tests skipped.\n"; - } if (!failed.empty()) { std::cout << failed.size() << " tests failing.\n"; return 1;