From 07c2451abd28dd2598f0570622b4324288cbaccc Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Fri, 23 Oct 2009 11:21:36 +0200
Subject: [PATCH] Use memoization to reduce the backtracking when parsing
 template arguments.

---
 src/shared/cplusplus/Parser.cpp | 25 +++++++++++++++++++++++--
 src/shared/cplusplus/Parser.h   | 14 +++++++++++++-
 2 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp
index 24851c991da..67e260230c0 100644
--- a/src/shared/cplusplus/Parser.cpp
+++ b/src/shared/cplusplus/Parser.cpp
@@ -328,8 +328,6 @@ bool Parser::parseTemplateId(NameAST *&node)
     DEBUG_THIS_RULE();
 
     const unsigned start = cursor();
-    Rewind rewind(this);
-    rewind.mark();
 
     if (LA() == T_IDENTIFIER && LA(2) == T_LESS) {
         TemplateIdAST *ast = new (_pool) TemplateIdAST;
@@ -692,8 +690,26 @@ bool Parser::parseOperatorFunctionId(NameAST *&node)
     return true;
 }
 
+Parser::TemplateArgumentListEntry *Parser::templateArgumentListEntry(unsigned tokenIndex)
+{
+    for (unsigned i = 0; i < _templateArgumentList.size(); ++i) {
+        TemplateArgumentListEntry *entry = &_templateArgumentList[i];
+        if (entry->index == tokenIndex)
+            return entry;
+    }
+
+    return 0;
+}
+
 bool Parser::parseTemplateArgumentList(TemplateArgumentListAST *&node)
 {
+    if (TemplateArgumentListEntry *entry = templateArgumentListEntry(cursor())) {
+        rewind(entry->cursor);
+        return entry->ast;
+    }
+
+    unsigned start = cursor();
+
     DEBUG_THIS_RULE();
     TemplateArgumentListAST **template_argument_ptr = &node;
     ExpressionAST *template_argument = 0;
@@ -711,8 +727,13 @@ bool Parser::parseTemplateArgumentList(TemplateArgumentListAST *&node)
                 template_argument_ptr = &(*template_argument_ptr)->next;
             }
         }
+
+        _templateArgumentList.push_back(TemplateArgumentListEntry(start, cursor(), node));
         return true;
     }
+
+    _templateArgumentList.push_back(TemplateArgumentListEntry(start, cursor(), 0));
+
     return false;
 }
 
diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h
index 2a7c15dfa3e..d9ccf6ab490 100644
--- a/src/shared/cplusplus/Parser.h
+++ b/src/shared/cplusplus/Parser.h
@@ -54,7 +54,6 @@
 #include "Token.h"
 #include "TranslationUnit.h"
 
-
 namespace CPlusPlus {
 
 class CPLUSPLUS_EXPORT Parser
@@ -287,6 +286,17 @@ private:
     inline void rewind(unsigned cursor)
     { _tokenIndex = cursor; }
 
+    struct TemplateArgumentListEntry {
+        unsigned index;
+        unsigned cursor;
+        TemplateArgumentListAST *ast;
+
+        TemplateArgumentListEntry(unsigned index = 0, unsigned cursor = 0, TemplateArgumentListAST *ast = 0)
+            : index(index), cursor(cursor), ast(ast) {}
+    };
+
+    TemplateArgumentListEntry *templateArgumentListEntry(unsigned tokenIndex);
+
 private:
     TranslationUnit *_translationUnit;
     Control *_control;
@@ -298,6 +308,8 @@ private:
     bool _inFunctionBody: 1;
     bool _inObjCImplementationContext: 1;
 
+    Array<TemplateArgumentListEntry> _templateArgumentList;
+
     class Rewind;
     friend class Rewind;
 
-- 
GitLab