From e2e4fcd95b39fb00d132d4018eac15fcfcf9c228 Mon Sep 17 00:00:00 2001
From: Roberto Raggi <qtc-committer@nokia.com>
Date: Wed, 3 Dec 2008 14:01:19 +0100
Subject: [PATCH] Added different parsing mode to TranslationUnit/CppDocument.

---
 shared/cplusplus/TranslationUnit.cpp    | 40 ++++++++++++++++++++++---
 shared/cplusplus/TranslationUnit.h      | 14 +++++++--
 src/libs/cplusplus/CppDocument.cpp      | 31 +++++++++++++++++--
 src/libs/cplusplus/CppDocument.h        |  9 +++++-
 src/libs/cplusplus/TypeOfExpression.cpp | 27 ++++-------------
 tests/manual/cplusplus/main.cpp         |  4 ++-
 6 files changed, 91 insertions(+), 34 deletions(-)

diff --git a/shared/cplusplus/TranslationUnit.cpp b/shared/cplusplus/TranslationUnit.cpp
index 896ab7d1a55..bc4d219e0f3 100644
--- a/shared/cplusplus/TranslationUnit.cpp
+++ b/shared/cplusplus/TranslationUnit.cpp
@@ -146,7 +146,7 @@ unsigned TranslationUnit::matchingBrace(unsigned index) const
 MemoryPool *TranslationUnit::memoryPool() const
 { return _pool; }
 
-TranslationUnitAST *TranslationUnit::ast() const
+AST *TranslationUnit::ast() const
 { return _ast; }
 
 bool TranslationUnit::isTokenized() const
@@ -218,17 +218,49 @@ bool TranslationUnit::skipFunctionBody() const
 void TranslationUnit::setSkipFunctionBody(bool skipFunctionBody)
 { _skipFunctionBody = skipFunctionBody; }
 
-void TranslationUnit::parse()
+bool TranslationUnit::parse(ParseMode mode)
 {
     if (isParsed())
-        return;
+        return false;
 
     if (! isTokenized())
         tokenize();
 
     Parser parser(this);
     parser.setQtMocRunEnabled(_qtMocRunEnabled);
-    parser.parseTranslationUnit(_ast);
+
+    bool parsed = false;
+
+    switch (mode) {
+    case ParseTranlationUnit: {
+        TranslationUnitAST *node = 0;
+        parsed = parser.parseTranslationUnit(node);
+        _ast = node;
+    } break;
+
+    case ParseDeclaration: {
+        DeclarationAST *node = 0;
+        parsed = parser.parseDeclaration(node);
+        _ast = node;
+    } break;
+
+    case ParseExpression: {
+        ExpressionAST *node = 0;
+        parsed = parser.parseExpression(node);
+        _ast = node;
+    } break;
+
+    case ParseStatement: {
+        StatementAST *node = 0;
+        parsed = parser.parseStatement(node);
+        _ast = node;
+    } break;
+
+    default:
+        break;
+    } // switch
+
+    return parsed;
 }
 
 void TranslationUnit::pushLineOffset(unsigned offset)
diff --git a/shared/cplusplus/TranslationUnit.h b/shared/cplusplus/TranslationUnit.h
index 41f5a1d6e86..ae6b911aeee 100644
--- a/shared/cplusplus/TranslationUnit.h
+++ b/shared/cplusplus/TranslationUnit.h
@@ -95,7 +95,7 @@ public:
     NumericLiteral *numericLiteral(unsigned index) const;
 
     MemoryPool *memoryPool() const;
-    TranslationUnitAST *ast() const;
+    AST *ast() const;
 
     bool blockErrors(bool block);
 
@@ -113,7 +113,15 @@ public:
     void setSkipFunctionBody(bool skipFunctionBody);
 
     bool isParsed() const;
-    void parse();
+
+    enum ParseMode {
+        ParseTranlationUnit,
+        ParseDeclaration,
+        ParseExpression,
+        ParseStatement
+    };
+
+    bool parse(ParseMode mode = ParseTranlationUnit);
 
     void resetAST();
     void release();
@@ -169,7 +177,7 @@ private:
     std::vector<unsigned> _lineOffsets;
     std::vector<PPLine> _ppLines;
     MemoryPool *_pool;
-    TranslationUnitAST *_ast;
+    AST *_ast;
     TranslationUnit *_previousTranslationUnit;
     union {
         unsigned _flags;
diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp
index 3fe4ea86b63..782c14ff6d5 100644
--- a/src/libs/cplusplus/CppDocument.cpp
+++ b/src/libs/cplusplus/CppDocument.cpp
@@ -251,9 +251,31 @@ QSet<QByteArray> Document::macroNames() const
     return _macroNames;
 }
 
-void Document::parse()
+bool Document::parse(ParseMode mode)
 {
-    _translationUnit->parse();
+    TranslationUnit::ParseMode m = TranslationUnit::ParseTranlationUnit;
+    switch (mode) {
+    case ParseTranlationUnit:
+        m = TranslationUnit::ParseTranlationUnit;
+        break;
+
+    case ParseDeclaration:
+        m = TranslationUnit::ParseDeclaration;
+        break;
+
+    case ParseExpression:
+        m = TranslationUnit::ParseExpression;
+        break;
+
+    case ParseStatement:
+        m = TranslationUnit::ParseStatement;
+        break;
+
+    default:
+        break;
+    }
+
+    return _translationUnit->parse(m);
 }
 
 void Document::check()
@@ -264,7 +286,10 @@ void Document::check()
 
     _globalNamespace = _control->newNamespace(0);
     Scope *globals = _globalNamespace->members();
-    if (TranslationUnitAST *ast = _translationUnit->ast()) {
+    if (! _translationUnit->ast())
+        return; // nothing to do.
+
+    if (TranslationUnitAST *ast = _translationUnit->ast()->asTranslationUnit()) {
         for (DeclarationAST *decl = ast->declarations; decl; decl = decl->next) {
             semantic.check(decl, globals);
         }
diff --git a/src/libs/cplusplus/CppDocument.h b/src/libs/cplusplus/CppDocument.h
index d4de240d3a4..17762200fa0 100644
--- a/src/libs/cplusplus/CppDocument.h
+++ b/src/libs/cplusplus/CppDocument.h
@@ -85,7 +85,14 @@ public:
     void startSkippingBlocks(unsigned offset);
     void stopSkippingBlocks(unsigned offset);
 
-    void parse(); // ### remove
+    enum ParseMode { // ### keep in sync with CPlusPlus::TranslationUnit
+        ParseTranlationUnit,
+        ParseDeclaration,
+        ParseExpression,
+        ParseStatement
+    };
+
+    bool parse(ParseMode mode = ParseTranlationUnit);
     void check();
     void releaseTranslationUnit();
 
diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp
index 7e3ed35af8b..2672bfb105f 100644
--- a/src/libs/cplusplus/TypeOfExpression.cpp
+++ b/src/libs/cplusplus/TypeOfExpression.cpp
@@ -81,34 +81,17 @@ ExpressionAST *TypeOfExpression::expressionAST() const
 
 ExpressionAST *TypeOfExpression::extractExpressionAST(Document::Ptr doc) const
 {
-    TranslationUnitAST *translationUnitAST = doc->translationUnit()->ast();
+    if (! doc->translationUnit()->ast())
+        return 0;
 
-    // ### evaluate the expression
-    ExpressionAST *expressionAST = 0;
-    if (translationUnitAST) {
-        DeclarationAST *declaration = translationUnitAST->declarations;
-        SimpleDeclarationAST *simpleDecl = 0;
-        if (declaration)
-            simpleDecl = declaration->asSimpleDeclaration();
-        if (simpleDecl && simpleDecl->decl_specifier_seq) {
-            if (TypeofSpecifierAST *typeOfSpec = simpleDecl->decl_specifier_seq->asTypeofSpecifier())
-                expressionAST = typeOfSpec->expression;
-        }
-    }
-    return expressionAST;
+    return doc->translationUnit()->ast()->asExpression();
 }
 
 Document::Ptr TypeOfExpression::documentForExpression(const QString &expression) const
 {
-    // create a __typeof__ specifier
-    QByteArray declaration;
-    declaration += "__typeof__ ";
-    declaration += expression.toLatin1(); // C++ code needs to be in latin1
-    declaration += ";";
-
     // create the expression's AST.
     Document::Ptr doc = Document::create(QLatin1String("<completion>"));
-    doc->setSource(declaration);
-    doc->parse();
+    doc->setSource(expression.toUtf8());
+    doc->parse(Document::ParseExpression);
     return doc;
 }
diff --git a/tests/manual/cplusplus/main.cpp b/tests/manual/cplusplus/main.cpp
index 946bd5c735a..234c9684a39 100644
--- a/tests/manual/cplusplus/main.cpp
+++ b/tests/manual/cplusplus/main.cpp
@@ -56,8 +56,10 @@ int main(int, char *[])
     TranslationUnit unit(&control, fileId);
     unit.setSource(source.constData(), source.size());
     unit.parse();
+    if (unit.ast()) {
+        TranslationUnitAST *ast = unit.ast()->asTranslationUnit();
+        Q_ASSERT(ast != 0);
 
-    if (TranslationUnitAST *ast = unit.ast()) {
         Scope globalScope;
         Semantic sem(&control);
         for (DeclarationAST *decl = ast->declarations; decl; decl = decl->next) {
-- 
GitLab