aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/3rdparty/cplusplus/TranslationUnit.cpp
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@nokia.com>2011-05-16 10:53:42 +0200
committerOswald Buddenhagen <oswald.buddenhagen@nokia.com>2011-05-16 11:05:30 +0200
commit67704b8b41b053eddbd4119a04115fb0fb2c9237 (patch)
tree094fb9bc849f2467d6389267d5613574a48f478f /src/libs/3rdparty/cplusplus/TranslationUnit.cpp
parent5a39fba5805d34fbef16a50d20312b8a9de5bdfc (diff)
move src/shared/cplusplus/ -> src/libs/3rdparty/cplusplus/
Approved-by: legal
Diffstat (limited to 'src/libs/3rdparty/cplusplus/TranslationUnit.cpp')
-rw-r--r--src/libs/3rdparty/cplusplus/TranslationUnit.cpp511
1 files changed, 511 insertions, 0 deletions
diff --git a/src/libs/3rdparty/cplusplus/TranslationUnit.cpp b/src/libs/3rdparty/cplusplus/TranslationUnit.cpp
new file mode 100644
index 0000000000..ba6572e7a2
--- /dev/null
+++ b/src/libs/3rdparty/cplusplus/TranslationUnit.cpp
@@ -0,0 +1,511 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at info@qt.nokia.com.
+**
+**************************************************************************/
+// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "TranslationUnit.h"
+#include "Control.h"
+#include "Parser.h"
+#include "Lexer.h"
+#include "MemoryPool.h"
+#include "AST.h"
+#include "Literals.h"
+#include "DiagnosticClient.h"
+#include <stack>
+#include <cstdarg>
+#include <algorithm>
+
+#ifdef _MSC_VER
+# define va_copy(dst, src) ((dst) = (src))
+#elif defined(__INTEL_COMPILER) && !defined(va_copy)
+# define va_copy __va_copy
+#endif
+
+using namespace CPlusPlus;
+
+TranslationUnit::TranslationUnit(Control *control, const StringLiteral *fileId)
+ : _control(control),
+ _fileId(fileId),
+ _firstSourceChar(0),
+ _lastSourceChar(0),
+ _pool(0),
+ _ast(0),
+ _flags(0)
+{
+ _tokens = new std::vector<Token>();
+ _previousTranslationUnit = control->switchTranslationUnit(this);
+ _pool = new MemoryPool();
+}
+
+TranslationUnit::~TranslationUnit()
+{
+ (void) _control->switchTranslationUnit(_previousTranslationUnit);
+ delete _tokens;
+ delete _pool;
+}
+
+bool TranslationUnit::qtMocRunEnabled() const
+{ return f._qtMocRunEnabled; }
+
+void TranslationUnit::setQtMocRunEnabled(bool onoff)
+{ f._qtMocRunEnabled = onoff; }
+
+bool TranslationUnit::cxx0xEnabled() const
+{ return f._cxx0xEnabled; }
+
+void TranslationUnit::setCxxOxEnabled(bool onoff)
+{ f._cxx0xEnabled = onoff; }
+
+bool TranslationUnit::objCEnabled() const
+{ return f._objCEnabled; }
+
+void TranslationUnit::setObjCEnabled(bool onoff)
+{ f._objCEnabled = onoff; }
+
+Control *TranslationUnit::control() const
+{ return _control; }
+
+const StringLiteral *TranslationUnit::fileId() const
+{ return _fileId; }
+
+const char *TranslationUnit::fileName() const
+{ return _fileId->chars(); }
+
+unsigned TranslationUnit::fileNameLength() const
+{ return _fileId->size(); }
+
+const char *TranslationUnit::firstSourceChar() const
+{ return _firstSourceChar; }
+
+const char *TranslationUnit::lastSourceChar() const
+{ return _lastSourceChar; }
+
+unsigned TranslationUnit::sourceLength() const
+{ return _lastSourceChar - _firstSourceChar; }
+
+void TranslationUnit::setSource(const char *source, unsigned size)
+{
+ _firstSourceChar = source;
+ _lastSourceChar = source + size;
+}
+
+unsigned TranslationUnit::tokenCount() const
+{ return _tokens->size(); }
+
+const Token &TranslationUnit::tokenAt(unsigned index) const
+{ return _tokens->at(index); }
+
+int TranslationUnit::tokenKind(unsigned index) const
+{ return _tokens->at(index).f.kind; }
+
+const char *TranslationUnit::spell(unsigned index) const
+{
+ if (! index)
+ return 0;
+
+ return _tokens->at(index).spell();
+}
+
+const Identifier *TranslationUnit::identifier(unsigned index) const
+{ return _tokens->at(index).identifier; }
+
+const Literal *TranslationUnit::literal(unsigned index) const
+{ return _tokens->at(index).literal; }
+
+const StringLiteral *TranslationUnit::stringLiteral(unsigned index) const
+{ return _tokens->at(index).string; }
+
+const NumericLiteral *TranslationUnit::numericLiteral(unsigned index) const
+{ return _tokens->at(index).number; }
+
+unsigned TranslationUnit::matchingBrace(unsigned index) const
+{ return _tokens->at(index).close_brace; }
+
+MemoryPool *TranslationUnit::memoryPool() const
+{ return _pool; }
+
+AST *TranslationUnit::ast() const
+{ return _ast; }
+
+bool TranslationUnit::isTokenized() const
+{ return f._tokenized; }
+
+bool TranslationUnit::isParsed() const
+{ return f._parsed; }
+
+void TranslationUnit::tokenize()
+{
+ if (isTokenized())
+ return;
+
+ f._tokenized = true;
+
+ Lexer lex(this);
+ lex.setQtMocRunEnabled(f._qtMocRunEnabled);
+ lex.setCxxOxEnabled(f._cxx0xEnabled);
+ lex.setObjCEnabled(f._objCEnabled);
+
+ std::stack<unsigned> braces;
+ _tokens->push_back(Token()); // the first token needs to be invalid!
+
+ pushLineOffset(0);
+ pushPreprocessorLine(0, 1, fileId());
+
+ const Identifier *lineId = control()->identifier("line");
+ const Identifier *genId = control()->identifier("gen");
+
+ bool generated = false;
+ Token tk;
+ do {
+ lex(&tk);
+
+ _Lrecognize:
+ if (tk.is(T_POUND) && tk.newline()) {
+ unsigned offset = tk.offset;
+ lex(&tk);
+
+ if (! tk.f.newline && tk.is(T_IDENTIFIER) && tk.identifier == genId) {
+ // it's a gen directive.
+ lex(&tk);
+
+ if (! tk.f.newline && tk.is(T_TRUE)) {
+ lex(&tk);
+ generated = true;
+ } else {
+ generated = false;
+ }
+ } else {
+ if (! tk.f.newline && tk.is(T_IDENTIFIER) && tk.identifier == lineId)
+ lex(&tk);
+ if (! tk.f.newline && tk.is(T_NUMERIC_LITERAL)) {
+ unsigned line = (unsigned) strtoul(tk.spell(), 0, 0);
+ lex(&tk);
+ if (! tk.f.newline && tk.is(T_STRING_LITERAL)) {
+ const StringLiteral *fileName = control()->stringLiteral(tk.string->chars(),
+ tk.string->size());
+ pushPreprocessorLine(offset, line, fileName);
+ lex(&tk);
+ }
+ }
+ }
+ while (tk.isNot(T_EOF_SYMBOL) && ! tk.f.newline)
+ lex(&tk);
+ goto _Lrecognize;
+ } else if (tk.f.kind == T_LBRACE) {
+ braces.push(_tokens->size());
+ } else if (tk.f.kind == T_RBRACE && ! braces.empty()) {
+ const unsigned open_brace_index = braces.top();
+ braces.pop();
+ (*_tokens)[open_brace_index].close_brace = _tokens->size();
+ }
+ tk.f.generated = generated;
+ _tokens->push_back(tk);
+ } while (tk.f.kind);
+
+ for (; ! braces.empty(); braces.pop()) {
+ unsigned open_brace_index = braces.top();
+ (*_tokens)[open_brace_index].close_brace = _tokens->size();
+ }
+}
+
+bool TranslationUnit::skipFunctionBody() const
+{ return f._skipFunctionBody; }
+
+void TranslationUnit::setSkipFunctionBody(bool skipFunctionBody)
+{ f._skipFunctionBody = skipFunctionBody; }
+
+bool TranslationUnit::parse(ParseMode mode)
+{
+ if (isParsed())
+ return false;
+
+ if (! isTokenized())
+ tokenize();
+
+ f._parsed = true;
+
+ Parser parser(this);
+ parser.setQtMocRunEnabled(f._qtMocRunEnabled);
+ parser.setCxxOxEnabled(f._cxx0xEnabled);
+ parser.setObjCEnabled(f._objCEnabled);
+
+ 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 ParseDeclarator: {
+ DeclaratorAST *node = 0;
+ parsed = parser.parseDeclarator(node, /*decl_specifier_list =*/ 0);
+ _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)
+{ _lineOffsets.push_back(offset); }
+
+void TranslationUnit::pushPreprocessorLine(unsigned offset,
+ unsigned line,
+ const StringLiteral *fileName)
+{ _ppLines.push_back(PPLine(offset, line, fileName)); }
+
+unsigned TranslationUnit::findLineNumber(unsigned offset) const
+{
+ std::vector<unsigned>::const_iterator it =
+ std::lower_bound(_lineOffsets.begin(), _lineOffsets.end(), offset);
+
+ if (it != _lineOffsets.begin())
+ --it;
+
+ return it - _lineOffsets.begin();
+}
+
+TranslationUnit::PPLine TranslationUnit::findPreprocessorLine(unsigned offset) const
+{
+ std::vector<PPLine>::const_iterator it =
+ std::lower_bound(_ppLines.begin(), _ppLines.end(), PPLine(offset));
+
+ if (it != _ppLines.begin())
+ --it;
+
+ return *it;
+}
+
+unsigned TranslationUnit::findColumnNumber(unsigned offset, unsigned lineNumber) const
+{
+ if (! offset)
+ return 0;
+
+ return offset - _lineOffsets[lineNumber];
+}
+
+void TranslationUnit::getTokenPosition(unsigned index,
+ unsigned *line,
+ unsigned *column,
+ const StringLiteral **fileName) const
+{ return getPosition(tokenAt(index).offset, line, column, fileName); }
+
+void TranslationUnit::getTokenStartPosition(unsigned index, unsigned *line,
+ unsigned *column,
+ const StringLiteral **fileName) const
+{ return getPosition(tokenAt(index).begin(), line, column, fileName); }
+
+void TranslationUnit::getTokenEndPosition(unsigned index, unsigned *line,
+ unsigned *column,
+ const StringLiteral **fileName) const
+{ return getPosition(tokenAt(index).end(), line, column, fileName); }
+
+void TranslationUnit::getPosition(unsigned tokenOffset,
+ unsigned *line,
+ unsigned *column,
+ const StringLiteral **fileName) const
+{
+ unsigned lineNumber = findLineNumber(tokenOffset);
+ unsigned columnNumber = findColumnNumber(tokenOffset, lineNumber);
+ const PPLine ppLine = findPreprocessorLine(tokenOffset);
+
+ lineNumber -= findLineNumber(ppLine.offset) + 1;
+ lineNumber += ppLine.line;
+
+ if (line)
+ *line = lineNumber;
+
+ if (column)
+ *column = columnNumber;
+
+ if (fileName)
+ *fileName = ppLine.fileName;
+}
+
+bool TranslationUnit::blockErrors(bool block)
+{
+ bool previous = f._blockErrors;
+ f._blockErrors = block;
+ return previous;
+}
+
+void TranslationUnit::message(DiagnosticClient::Level level, unsigned index, const char *format, va_list args)
+{
+ if (f._blockErrors)
+ return;
+
+ index = std::min(index, tokenCount() - 1);
+
+ unsigned line = 0, column = 0;
+ const StringLiteral *fileName = 0;
+ getTokenPosition(index, &line, &column, &fileName);
+
+ if (DiagnosticClient *client = control()->diagnosticClient()) {
+ client->report(level, fileName, line, column, format, args);
+ } else {
+ fprintf(stderr, "%s:%d: ", fileName->chars(), line);
+ const char *l = "error";
+ if (level == DiagnosticClient::Warning)
+ l = "warning";
+ else if (level == DiagnosticClient::Fatal)
+ l = "fatal";
+ fprintf(stderr, "%s: ", l);
+
+ vfprintf(stderr, format, args);
+ fputc('\n', stderr);
+
+ showErrorLine(index, column, stderr);
+ }
+
+ if (level == DiagnosticClient::Fatal)
+ exit(EXIT_FAILURE);
+}
+
+void TranslationUnit::warning(unsigned index, const char *format, ...)
+{
+ if (f._blockErrors)
+ return;
+
+ va_list args, ap;
+ va_start(args, format);
+ va_copy(ap, args);
+ message(DiagnosticClient::Warning, index, format, args);
+ va_end(ap);
+ va_end(args);
+}
+
+void TranslationUnit::error(unsigned index, const char *format, ...)
+{
+ if (f._blockErrors)
+ return;
+
+ va_list args, ap;
+ va_start(args, format);
+ va_copy(ap, args);
+ message(DiagnosticClient::Error, index, format, args);
+ va_end(ap);
+ va_end(args);
+}
+
+void TranslationUnit::fatal(unsigned index, const char *format, ...)
+{
+ if (f._blockErrors)
+ return;
+
+ va_list args, ap;
+ va_start(args, format);
+ va_copy(ap, args);
+ message(DiagnosticClient::Fatal, index, format, args);
+ va_end(ap);
+ va_end(args);
+}
+
+unsigned TranslationUnit::findPreviousLineOffset(unsigned tokenIndex) const
+{
+ unsigned lineOffset = _lineOffsets[findLineNumber(_tokens->at(tokenIndex).offset)];
+ return lineOffset;
+}
+
+void TranslationUnit::showErrorLine(unsigned index, unsigned column, FILE *out)
+{
+ unsigned lineOffset = _lineOffsets[findLineNumber(_tokens->at(index).offset)];
+ for (const char *cp = _firstSourceChar + lineOffset + 1; *cp && *cp != '\n'; ++cp) {
+ fputc(*cp, out);
+ }
+ fputc('\n', out);
+
+ const char *end = _firstSourceChar + lineOffset + 1 + column - 1;
+ for (const char *cp = _firstSourceChar + lineOffset + 1; cp != end; ++cp) {
+ if (*cp != '\t')
+ fputc(' ', out);
+ else
+ fputc('\t', out);
+ }
+ fputc('^', out);
+ fputc('\n', out);
+}
+
+void TranslationUnit::resetAST()
+{
+ delete _pool;
+ _pool = 0;
+ _ast = 0;
+}
+
+void TranslationUnit::release()
+{
+ resetAST();
+ delete _tokens;
+ _tokens = 0;
+}
+
+