hokein updated this revision to Diff 446388.
hokein marked 2 inline comments as done.
hokein added a comment.

address comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130160/new/

https://reviews.llvm.org/D130160

Files:
  clang-tools-extra/pseudo/include/clang-pseudo/Language.h
  clang-tools-extra/pseudo/lib/GLR.cpp
  clang-tools-extra/pseudo/lib/cxx/CXX.cpp
  clang-tools-extra/pseudo/lib/cxx/cxx.bnf
  clang-tools-extra/pseudo/test/cxx/dangling-else.cpp
  clang-tools-extra/pseudo/unittests/GLRTest.cpp

Index: clang-tools-extra/pseudo/unittests/GLRTest.cpp
===================================================================
--- clang-tools-extra/pseudo/unittests/GLRTest.cpp
+++ clang-tools-extra/pseudo/unittests/GLRTest.cpp
@@ -634,11 +634,12 @@
     start := IDENTIFIER [guard=TestOnly]
   )bnf");
   TestLang.Guards.try_emplace(
-      extensionID("TestOnly"),
-      [&](llvm::ArrayRef<const ForestNode *> RHS, const TokenStream &Tokens) {
-        assert(RHS.size() == 1 &&
-               RHS.front()->symbol() == tokenSymbol(clang::tok::identifier));
-        return Tokens.tokens()[RHS.front()->startTokenIndex()].text() == "test";
+      extensionID("TestOnly"), [&](const GuardParams &P) {
+        assert(P.RHS.size() == 1 &&
+               P.RHS.front()->symbol() ==
+                   tokenSymbol(clang::tok::identifier));
+        return P.Tokens.tokens()[P.RHS.front()->startTokenIndex()]
+                   .text() == "test";
       });
   clang::LangOptions LOptions;
   TestLang.Table = LRTable::buildSLR(TestLang.G);
Index: clang-tools-extra/pseudo/test/cxx/dangling-else.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/pseudo/test/cxx/dangling-else.cpp
@@ -0,0 +1,22 @@
+// RUN: clang-pseudo -grammar=cxx -source=%s --start-symbol=statement-seq --print-forest | FileCheck %s
+
+// Verify the else should belong to the nested if statement
+if (true) if (true) {} else {}
+
+// CHECK:      statement-seq~selection-statement := IF ( condition ) statement
+// CHECK-NEXT: ├─IF
+// CHECK-NEXT: ├─(
+// CHECK-NEXT: ├─condition~TRUE
+// CHECK-NEXT: ├─)
+// CHECK-NEXT: └─statement~selection-statement
+// CHECK-NEXT:   ├─IF
+// CHECK-NEXT:   ├─(
+// CHECK-NEXT:   ├─condition~TRUE
+// CHECK-NEXT:   ├─)
+// CHECK-NEXT:   ├─statement~compound-statement := { }
+// CHECK-NEXT:   │ ├─{
+// CHECK-NEXT:   │ └─}
+// CHECK-NEXT:   ├─ELSE 
+// CHECK-NEXT:   └─statement~compound-statement := { }
+// CHECK-NEXT:     ├─{ 
+// CHECK-NEXT:     └─}
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
@@ -290,7 +290,7 @@
 compound-statement := { statement-seq_opt [recover=Brackets] }
 statement-seq := statement
 statement-seq := statement-seq statement
-selection-statement := IF CONSTEXPR_opt ( init-statement_opt condition ) statement
+selection-statement := IF CONSTEXPR_opt ( init-statement_opt condition ) statement [guard=NextTokenNotElse]
 selection-statement := IF CONSTEXPR_opt ( init-statement_opt condition ) statement ELSE statement
 selection-statement := SWITCH ( init-statement_opt condition ) statement
 iteration-statement := WHILE ( condition ) statement
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
@@ -11,6 +11,7 @@
 #include "clang-pseudo/Language.h"
 #include "clang-pseudo/grammar/Grammar.h"
 #include "clang-pseudo/grammar/LRTable.h"
+#include "clang/Basic/TokenKinds.h"
 #include <utility>
 
 namespace clang {
@@ -21,29 +22,25 @@
 #include "CXXBNF.inc"
     ;
 
-bool guardOverride(llvm::ArrayRef<const ForestNode *> RHS,
-                   const TokenStream &Tokens) {
-  assert(RHS.size() == 1 &&
-         RHS.front()->symbol() == tokenSymbol(clang::tok::identifier));
-  return Tokens.tokens()[RHS.front()->startTokenIndex()].text() == "override";
+bool guardOverride(const GuardParams &P) {
+  assert(P.RHS.size() == 1 &&
+         P.RHS.front()->symbol() == tokenSymbol(clang::tok::identifier));
+  return P.Tokens.tokens()[P.RHS.front()->startTokenIndex()].text() ==
+         "override";
 }
-bool guardFinal(llvm::ArrayRef<const ForestNode *> RHS,
-                const TokenStream &Tokens) {
-  assert(RHS.size() == 1 &&
-         RHS.front()->symbol() == tokenSymbol(clang::tok::identifier));
-  return Tokens.tokens()[RHS.front()->startTokenIndex()].text() == "final";
+bool guardFinal(const GuardParams &P) {
+  assert(P.RHS.size() == 1 &&
+         P.RHS.front()->symbol() == tokenSymbol(clang::tok::identifier));
+  return P.Tokens.tokens()[P.RHS.front()->startTokenIndex()].text() == "final";
 }
-bool guardModule(llvm::ArrayRef<const ForestNode *> RHS,
-                 const TokenStream &Tokens) {
-  return Tokens.tokens()[RHS.front()->startTokenIndex()].text() == "module";
+bool guardModule(const GuardParams &P) {
+  return P.Tokens.tokens()[P.RHS.front()->startTokenIndex()].text() == "module";
 }
-bool guardImport(llvm::ArrayRef<const ForestNode *> RHS,
-                 const TokenStream &Tokens) {
-  return Tokens.tokens()[RHS.front()->startTokenIndex()].text() == "import";
+bool guardImport(const GuardParams &P) {
+  return P.Tokens.tokens()[P.RHS.front()->startTokenIndex()].text() == "import";
 }
-bool guardExport(llvm::ArrayRef<const ForestNode *> RHS,
-                 const TokenStream &Tokens) {
-  return Tokens.tokens()[RHS.front()->startTokenIndex()].text() == "export";
+bool guardExport(const GuardParams &P) {
+  return P.Tokens.tokens()[P.RHS.front()->startTokenIndex()].text() == "export";
 }
 
 bool isFunctionDeclarator(const ForestNode *Declarator) {
@@ -93,17 +90,19 @@
   }
   llvm_unreachable("unreachable");
 }
-bool guardFunction(llvm::ArrayRef<const ForestNode *> RHS,
-                   const TokenStream &Tokens) {
-  assert(RHS.size() == 1 &&
-         RHS.front()->symbol() == (SymbolID)(cxx::Symbol::declarator));
-  return isFunctionDeclarator(RHS.front());
+bool guardFunction(const GuardParams &P) {
+  assert(P.RHS.size() == 1 &&
+         P.RHS.front()->symbol() == (SymbolID)(cxx::Symbol::declarator));
+  return isFunctionDeclarator(P.RHS.front());
 }
-bool guardNonFunction(llvm::ArrayRef<const ForestNode *> RHS,
-                      const TokenStream &Tokens) {
-  assert(RHS.size() == 1 &&
-         RHS.front()->symbol() == (SymbolID)(cxx::Symbol::declarator));
-  return !isFunctionDeclarator(RHS.front());
+bool guardNonFunction(const GuardParams &P) {
+  assert(P.RHS.size() == 1 &&
+         P.RHS.front()->symbol() == (SymbolID)(cxx::Symbol::declarator));
+  return !isFunctionDeclarator(P.RHS.front());
+}
+
+bool guardNextTokenNotElse(const GuardParams &P) {
+  return symbolToToken(P.Lookahead) != tok::kw_else;
 }
 
 llvm::DenseMap<ExtensionID, RuleGuard> buildGuards() {
@@ -115,6 +114,7 @@
       {(ExtensionID)Extension::Module, guardModule},
       {(ExtensionID)Extension::FunctionDeclarator, guardFunction},
       {(ExtensionID)Extension::NonFunctionDeclarator, guardNonFunction},
+      {(ExtensionID)Extension::NextTokenNotElse, guardNextTokenNotElse},
   };
 }
 
Index: clang-tools-extra/pseudo/lib/GLR.cpp
===================================================================
--- clang-tools-extra/pseudo/lib/GLR.cpp
+++ clang-tools-extra/pseudo/lib/GLR.cpp
@@ -421,7 +421,7 @@
     if (!GuardID)
       return true;
     if (auto Guard = Lang.Guards.lookup(GuardID))
-      return Guard(RHS, Params.Code);
+      return Guard({RHS, Params.Code, Lookahead});
     LLVM_DEBUG(llvm::dbgs()
                << llvm::formatv("missing guard implementation for rule {0}\n",
                                 Lang.G.dumpRule(RID)));
Index: clang-tools-extra/pseudo/include/clang-pseudo/Language.h
===================================================================
--- clang-tools-extra/pseudo/include/clang-pseudo/Language.h
+++ clang-tools-extra/pseudo/include/clang-pseudo/Language.h
@@ -19,6 +19,12 @@
 class TokenStream;
 class LRTable;
 
+struct GuardParams {
+  llvm::ArrayRef<const ForestNode *> RHS;
+  const TokenStream &Tokens;
+  // FIXME: use the index of Tokens.
+  SymbolID Lookahead;
+};
 // A guard restricts when a grammar rule can be used.
 //
 // The GLR parser will use the guard to determine whether a rule reduction will
@@ -26,8 +32,7 @@
 // `virt-specifier := IDENTIFIER` only if the identifier's text is 'override`.
 //
 // Return true if the guard is satisfied.
-using RuleGuard = llvm::function_ref<bool(
-    llvm::ArrayRef<const ForestNode *> RHS, const TokenStream &)>;
+using RuleGuard = llvm::function_ref<bool(const GuardParams &)>;
 
 // A recovery strategy determines a region of code to skip when parsing fails.
 //
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to