⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asbeautifier.cpp

📁 非常好用的可移植的多平台C/C++源代码编辑器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// $Id: ASBeautifier.cpp,v 1.4 2005/07/01 18:58:17 mandrav Exp $
// --------------------------------------------------------------------------
//
// Copyright (C) 1998,1999,2000,2001,2002 Tal Davidson.
// Copyright (C) 2004 Martin Baute.
// All rights reserved.
//
// This file is a part of "Artistic Style" - an indentation and reformatting
// tool for C, C++, C# and Java source files - http://astyle.sourceforge.net
//
// --------------------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// --------------------------------------------------------------------------
//
// Patches:
// 18 March 1999 - Brian Rampel -
//       Fixed inverse insertion of spaces vs. tabs when in -t mode.

#include "astyle.h"

#include <vector>
#include <string>
#include <cctype>
#include <algorithm>
#include <iostream>

using namespace std;

namespace astyle
{

static const string * headers_[] = { &AS_IF, &AS_ELSE, &AS_FOR, &AS_WHILE,
    &AS_DO, &AS_TRY, &AS_CATCH, &AS_FINALLY, &AS_SYNCHRONIZED, &AS_SWITCH,
    &AS_CASE, &AS_DEFAULT, &AS_FOREACH, &AS_LOCK, &AS_UNSAFE, &AS_FIXED,
    &AS_GET, &AS_SET, &AS_ADD, &AS_REMOVE, &AS_TEMPLATE, &AS_CONST, &AS_STATIC,
    &AS_EXTERN
    //, &AS_PUBLIC, &AS_PRIVATE, &AS_PROTECTED, &AS_OPERATOR
};
static vector < const string * > headers( headers_, headers_ + ( sizeof(headers_) / sizeof(headers_[0]) ) );

static const string * nonParenHeaders_[] = { &AS_ELSE, &AS_DO, &AS_TRY, &AS_FINALLY,
    &AS_STATIC, &AS_CONST, &AS_EXTERN, &AS_CASE, &AS_DEFAULT, &AS_UNSAFE,
    &AS_GET, &AS_SET, &AS_ADD, &AS_REMOVE, &AS_PUBLIC, &AS_PRIVATE,
    &AS_PROTECTED, &AS_TEMPLATE, &AS_CONST
    //, &AS_ASM
};
static vector < const string * > nonParenHeaders( nonParenHeaders_, nonParenHeaders_ + ( sizeof(nonParenHeaders_) / sizeof(nonParenHeaders_[0]) ) );

static const string * preBlockStatements_[] = { &AS_CLASS, &AS_STRUCT, &AS_UNION,
    &AS_INTERFACE, &AS_NAMESPACE, &AS_THROWS, &AS_EXTERN
};
static vector < const string * > preBlockStatements( preBlockStatements_, preBlockStatements_ + ( sizeof(preBlockStatements_) / sizeof(preBlockStatements_[0]) ) );

static const string * assignmentOperators_[] = { &AS_ASSIGN, &AS_PLUS_ASSIGN,
    &AS_MINUS_ASSIGN, &AS_MULT_ASSIGN, &AS_DIV_ASSIGN, &AS_MOD_ASSIGN,
    &AS_OR_ASSIGN, &AS_AND_ASSIGN, &AS_XOR_ASSIGN, &AS_GR_GR_GR_ASSIGN,
    &AS_GR_GR_ASSIGN, &AS_LS_LS_LS_ASSIGN, &AS_LS_LS_ASSIGN, &AS_RETURN
};
static vector < const string * > assignmentOperators( assignmentOperators_, assignmentOperators_ + ( sizeof(assignmentOperators_) / sizeof( assignmentOperators_[0]) ) );

static const string * nonAssignmentOperators_[] = { &AS_EQUAL, &AS_PLUS_PLUS,
    &AS_MINUS_MINUS, &AS_NOT_EQUAL, &AS_GR_EQUAL, &AS_GR_GR_GR, &AS_GR_GR,
    &AS_LS_EQUAL, &AS_LS_LS_LS, &AS_LS_LS, &AS_ARROW, &AS_AND, &AS_OR
};
static vector < const string * > nonAssignmentOperators( nonAssignmentOperators_, nonAssignmentOperators_ + ( sizeof(nonAssignmentOperators_) / sizeof(nonAssignmentOperators_[0]) ) );

ASBeautifier::ASBeautifier(const ASBeautifier &other)
{
    waitingBeautifierStack = NULL;
    activeBeautifierStack = NULL;
    waitingBeautifierStackLengthStack = NULL;
    activeBeautifierStackLengthStack = NULL;
    headerStack  = new vector<const string*>;
    *headerStack = *other.headerStack;
    tempStacks = new vector< vector<const string*>* >;
    vector< vector<const string*>* >::iterator iter;
    for (iter = other.tempStacks->begin();
         iter != other.tempStacks->end();
         ++iter)
    {
        vector<const string*> *newVec = new vector<const string*>;
        *newVec = **iter;
        tempStacks->push_back(newVec);
    }
    blockParenDepthStack = new vector<int>;
    *blockParenDepthStack = *other.blockParenDepthStack;

    blockStatementStack = new vector<bool>;
    *blockStatementStack = *other.blockStatementStack;

    parenStatementStack =  new vector<bool>;
    *parenStatementStack = *other.parenStatementStack;

    bracketBlockStateStack = new vector<bool>;
    *bracketBlockStateStack = *other.bracketBlockStateStack;

    inStatementIndentStack = new vector<int>;
    *inStatementIndentStack = *other.inStatementIndentStack;

    inStatementIndentStackSizeStack = new vector<unsigned>;
    *inStatementIndentStackSizeStack = *other.inStatementIndentStackSizeStack;

    parenIndentStack = new vector<int>;
    *parenIndentStack = *other.parenIndentStack;

    sourceIterator = other.sourceIterator;

    indentString = other.indentString;
    currentHeader = other.currentHeader;
    previousLastLineHeader = other.previousLastLineHeader;
    immediatelyPreviousAssignmentOp = other.immediatelyPreviousAssignmentOp;
    isInQuote = other.isInQuote;
    isInComment = other.isInComment;
    isInCase = other.isInCase;
    isInQuestion = other.isInQuestion;
    isInStatement =other. isInStatement;
    isInHeader = other.isInHeader;
    sourceStyle = other.sourceStyle;
    isInOperator = other.isInOperator;
    isInTemplate = other.isInTemplate;
    isInConst = other.isInConst;
    classIndent = other.classIndent;
    isInClassHeader = other.isInClassHeader;
    isInClassHeaderTab = other.isInClassHeaderTab;
    switchIndent = other.switchIndent;
    caseIndent = other.caseIndent;
    namespaceIndent = other.namespaceIndent;
    bracketIndent = other.bracketIndent;
    blockIndent = other.blockIndent;
    labelIndent = other.labelIndent;
    preprocessorIndent = other.preprocessorIndent;
    parenDepth = other.parenDepth;
    indentLength = other.indentLength;
    blockTabCount = other.blockTabCount;
    leadingWhiteSpaces = other.leadingWhiteSpaces;
    maxInStatementIndent = other.maxInStatementIndent;
    templateDepth = other.templateDepth;
    quoteChar = other.quoteChar;
    prevNonSpaceCh = other.prevNonSpaceCh;
    currentNonSpaceCh = other.currentNonSpaceCh;
    currentNonLegalCh = other.currentNonLegalCh;
    prevNonLegalCh = other.prevNonLegalCh;
    isInConditional = other.isInConditional;
    minConditionalIndent = other.minConditionalIndent;
    prevFinalLineSpaceTabCount = other.prevFinalLineSpaceTabCount;
    prevFinalLineTabCount = other.prevFinalLineTabCount;
    emptyLineIndent = other.emptyLineIndent;
    probationHeader = other.probationHeader;
    isInDefine = other.isInDefine;
    isInDefineDefinition = other.isInDefineDefinition;
    backslashEndsPrevLine = other.backslashEndsPrevLine;
    defineTabCount = other.defineTabCount;
    eolString = other.eolString;
}

/**
 * ASBeautifier's destructor
 */
ASBeautifier::~ASBeautifier()
{
    delete( headerStack );
    delete( tempStacks );
    delete( blockParenDepthStack );
    delete( blockStatementStack );
    delete( parenStatementStack );
    delete( bracketBlockStateStack );
    delete( inStatementIndentStack );
    delete( inStatementIndentStackSizeStack );
    delete( parenIndentStack );
}

/**
 * initialize the ASBeautifier.
 *
 * init() should be called every time a ASBeautifier object is to start
 * formatting a NEW source file.
 * init() recieves an istream reference
 * that will be used to iterate through the source code.
 */
void ASBeautifier::init(istream & iter)
{
    sourceIterator = &iter;
    delete( waitingBeautifierStack );
    waitingBeautifierStack = new vector<ASBeautifier*>;

    delete( activeBeautifierStack );
    activeBeautifierStack = new vector<ASBeautifier*>;

    delete( waitingBeautifierStackLengthStack );
    waitingBeautifierStackLengthStack = new vector<int>;

    delete( activeBeautifierStackLengthStack );
    activeBeautifierStackLengthStack = new vector<int>;

    delete( headerStack );
    headerStack = new vector<const string*>;

    delete( tempStacks );
    tempStacks = new vector< vector<const string*>* >;
    tempStacks->push_back(new vector<const string*>);

    delete( blockParenDepthStack );
    blockParenDepthStack = new vector<int>;

    delete( blockStatementStack );
    blockStatementStack = new vector<bool>;

    delete( parenStatementStack );
    parenStatementStack = new vector<bool>;

    delete( bracketBlockStateStack );
    bracketBlockStateStack = new vector<bool>;
    bracketBlockStateStack->push_back(true);

    delete( inStatementIndentStack );
    inStatementIndentStack = new vector<int>;

    delete( inStatementIndentStackSizeStack );
    inStatementIndentStackSizeStack = new vector<unsigned>;
    inStatementIndentStackSizeStack->push_back(0);

    delete( parenIndentStack );
    parenIndentStack = new vector<int>;

    immediatelyPreviousAssignmentOp = NULL;
    previousLastLineHeader = NULL;

    isInQuote = false;
    isInComment = false;
    isInStatement = false;
    isInCase = false;
    isInQuestion = false;
    isInClassHeader = false;
    isInClassHeaderTab = false;
    isInHeader = false;
    isInOperator = false;
    isInTemplate = false;
    isInConst = false;
    isInConditional = false;
    templateDepth = 0;
    parenDepth=0;
    blockTabCount = 0;
    leadingWhiteSpaces = 0;
    prevNonSpaceCh = '{';
    currentNonSpaceCh = '{';
    prevNonLegalCh = '{';
    currentNonLegalCh = '{';
    prevFinalLineSpaceTabCount = 0;
    prevFinalLineTabCount = 0;
    probationHeader = NULL;
    backslashEndsPrevLine = false;
    isInDefine = false;
    isInDefineDefinition = false;
    defineTabCount = 0;
}

/**
 * check if there are any indented lines ready to be read by nextLine()
 *
 * @return    are there any indented lines ready?
 */
bool ASBeautifier::hasMoreLines() const
{
    return sourceIterator->good();
}

/**
 * get the next indented line.
 *
 * @return    indented line.
 */
string ASBeautifier::nextLine()
{
    string buffer;
    getline(*sourceIterator, buffer);
    if ( !buffer.empty() && buffer[buffer.size() - 1] == '\r' )
    {
        buffer = buffer.substr(0, buffer.size() - 1);
    }
    return beautify(buffer);
}

/**
 * beautify a line of source code.
 * every line of source code in a source code file should be sent
 * one after the other to the beautify method.
 *
 * @return      the indented line.
 * @param originalLine       the original unindented line.
 */
string ASBeautifier::beautify( const string & originalLine )
{
    TRACE_LIFE( FUNCTION, "beautifying new line" );
    TRACE( INFO, "processing '" << originalLine << "'." );
    string line;
    bool isInLineComment = false;
    bool lineStartsInComment = false;
    bool isInClass = false;
    bool isInSwitch = false;
    bool isImmediatelyAfterConst = false;
    bool isSpecialChar = false;
    char ch = ' ';
    char prevCh;
    string outBuffer; // the newly idented line is bufferd here
    int tabCount = 0;
    const string *lastLineHeader = NULL;
    bool closingBracketReached = false;
    int spaceTabCount = 0;
    char tempCh;
    unsigned headerStackSize = headerStack->size();
    //bool isLineInStatement = isInStatement;
    bool shouldIndentBrackettedLine = true;
    int lineOpeningBlocksNum = 0;
    int lineClosingBlocksNum = 0;
    bool previousLineProbation = (probationHeader != NULL);
    string::size_type i;

    static bool suppressIndent = false; // "remembering" to suppress next-line indent
    bool suppressCurrentIndent = suppressIndent; // whether the *current* line shall be indent-suppressed

    currentHeader = NULL;

    lineStartsInComment = isInComment;

    // handle and remove white spaces around the line:
    // If not in comment, first find out size of white space before line,
    // so that possible comments starting in the line continue in
    // relation to the preliminary white-space.
    // FIXME: When suppressCurrentIndent is set, LEADING whitespace must not be trimmed.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -