hokein created this revision.
hokein added a reviewer: sammccall.
Herald added a project: All.
hokein requested review of this revision.
Herald added a subscriber: alextsao1999.
Herald added a project: clang-tools-extra.

The solution is to favor the longest possible nest-name-specifier, and
drop other alternatives by using the guard.

This is my attempt, this might not be a right approach, looking for initial
thoughts.

Motivated cases:

  Foo::Foo() {};
  // the constructor can be parsed as:
  //  - Foo ::Foo(); // where the first Foo is return-type, and ::Foo is the 
function declarator
  //  + Foo::Foo(); // where Foo::Foo is the function declarator



  void test() {
  
  // a very slow parsing case when there are many qualifers!
  X::Y::Z;
  // The statement can be parsed as:
  //  - X ::Y::Z; // ::Y::Z is the declarator
  //  - X::Y ::Z; // ::Z is the declarator
  //  + X::Y::Z;  // a declaration without declarator (X::Y::Z is 
decl-specifier-seq)
  //  + X::Y::Z;  // a qualifed-id expression
  }


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D130511

Files:
  clang-tools-extra/pseudo/lib/cxx/CXX.cpp
  clang-tools-extra/pseudo/lib/cxx/cxx.bnf


Index: clang-tools-extra/pseudo/lib/cxx/cxx.bnf
===================================================================
--- clang-tools-extra/pseudo/lib/cxx/cxx.bnf
+++ clang-tools-extra/pseudo/lib/cxx/cxx.bnf
@@ -370,11 +370,11 @@
 defining-type-specifier := enum-specifier
 defining-type-specifier-seq := defining-type-specifier
 defining-type-specifier-seq := defining-type-specifier 
defining-type-specifier-seq [guard]
-simple-type-specifier := nested-name-specifier_opt type-name
+simple-type-specifier := nested-name-specifier_opt type-name [guard]
 simple-type-specifier := nested-name-specifier TEMPLATE simple-template-id
 simple-type-specifier := decltype-specifier
 simple-type-specifier := placeholder-type-specifier
-simple-type-specifier := nested-name-specifier_opt template-name
+simple-type-specifier := nested-name-specifier_opt template-name [guard]
 simple-type-specifier := builtin-type
 builtin-type := CHAR
 builtin-type := CHAR8_T
Index: clang-tools-extra/pseudo/lib/cxx/CXX.cpp
===================================================================
--- clang-tools-extra/pseudo/lib/cxx/CXX.cpp
+++ clang-tools-extra/pseudo/lib/cxx/CXX.cpp
@@ -162,6 +162,10 @@
   return symbolToToken(P.Lookahead) != tok::kw_else;
 }
 
+bool guardNextTokenNotColCol(const GuardParams &P) {
+  return symbolToToken(P.Lookahead) != tok::coloncolon;
+}
+
 // Whether this e.g. decl-specifier contains an "exclusive" type such as a 
class
 // name, and thus can't combine with a second exclusive type.
 //
@@ -308,6 +312,16 @@
            
selection_statement_0if_1constexpr_2l_paren_3condition_4r_paren_5statement,
        guardNextTokenNotElse},
 
+      {(RuleID)Rule::simple_type_specifier_0nested_name_specifier_1type_name,
+       guardNextTokenNotColCol},
+      
{(RuleID)Rule::simple_type_specifier_0nested_name_specifier_1template_name,
+       guardNextTokenNotColCol},
+      {(RuleID)Rule::simple_type_specifier_0type_name,
+       guardNextTokenNotColCol},
+      {(RuleID)Rule::simple_type_specifier_0template_name,
+       guardNextTokenNotColCol
+      },
+
       // The grammar distinguishes (only) user-defined vs plain string 
literals,
       // where the clang lexer distinguishes (only) encoding types.
       {(RuleID)Rule::user_defined_string_literal_chunk_0string_literal,


Index: clang-tools-extra/pseudo/lib/cxx/cxx.bnf
===================================================================
--- clang-tools-extra/pseudo/lib/cxx/cxx.bnf
+++ clang-tools-extra/pseudo/lib/cxx/cxx.bnf
@@ -370,11 +370,11 @@
 defining-type-specifier := enum-specifier
 defining-type-specifier-seq := defining-type-specifier
 defining-type-specifier-seq := defining-type-specifier defining-type-specifier-seq [guard]
-simple-type-specifier := nested-name-specifier_opt type-name
+simple-type-specifier := nested-name-specifier_opt type-name [guard]
 simple-type-specifier := nested-name-specifier TEMPLATE simple-template-id
 simple-type-specifier := decltype-specifier
 simple-type-specifier := placeholder-type-specifier
-simple-type-specifier := nested-name-specifier_opt template-name
+simple-type-specifier := nested-name-specifier_opt template-name [guard]
 simple-type-specifier := builtin-type
 builtin-type := CHAR
 builtin-type := CHAR8_T
Index: clang-tools-extra/pseudo/lib/cxx/CXX.cpp
===================================================================
--- clang-tools-extra/pseudo/lib/cxx/CXX.cpp
+++ clang-tools-extra/pseudo/lib/cxx/CXX.cpp
@@ -162,6 +162,10 @@
   return symbolToToken(P.Lookahead) != tok::kw_else;
 }
 
+bool guardNextTokenNotColCol(const GuardParams &P) {
+  return symbolToToken(P.Lookahead) != tok::coloncolon;
+}
+
 // Whether this e.g. decl-specifier contains an "exclusive" type such as a class
 // name, and thus can't combine with a second exclusive type.
 //
@@ -308,6 +312,16 @@
            selection_statement_0if_1constexpr_2l_paren_3condition_4r_paren_5statement,
        guardNextTokenNotElse},
 
+      {(RuleID)Rule::simple_type_specifier_0nested_name_specifier_1type_name,
+       guardNextTokenNotColCol},
+      {(RuleID)Rule::simple_type_specifier_0nested_name_specifier_1template_name,
+       guardNextTokenNotColCol},
+      {(RuleID)Rule::simple_type_specifier_0type_name,
+       guardNextTokenNotColCol},
+      {(RuleID)Rule::simple_type_specifier_0template_name,
+       guardNextTokenNotColCol
+      },
+
       // The grammar distinguishes (only) user-defined vs plain string literals,
       // where the clang lexer distinguishes (only) encoding types.
       {(RuleID)Rule::user_defined_string_literal_chunk_0string_literal,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to