📄 asbeautifier.cpp
字号:
// $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 + -