📄 asformatter.cpp
字号:
// $Id: ASFormatter.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:
// 26 November 1998 - Richard Bullington -
// A correction of line-breaking in headers following '}',
// was created using a variation of a patch by Richard Bullington.
#include "astyle.h"
#include <string>
#include <cctype>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
namespace astyle
{
int Tracer::mIndent = 0;
std::string const AS_IF = "if";
std::string const AS_ELSE = "else";
std::string const AS_FOR = "for";
std::string const AS_DO = "do";
std::string const AS_WHILE = "while";
std::string const AS_SWITCH = "switch";
std::string const AS_CASE = "case";
std::string const AS_DEFAULT = "default";
std::string const AS_CLASS = "class";
std::string const AS_STRUCT = "struct";
std::string const AS_UNION = "union";
std::string const AS_INTERFACE = "interface";
std::string const AS_NAMESPACE = "namespace";
std::string const AS_EXTERN = "extern";
std::string const AS_PUBLIC = "public";
std::string const AS_PROTECTED = "protected";
std::string const AS_PRIVATE = "private";
std::string const AS_STATIC = "static";
std::string const AS_SYNCHRONIZED = "synchronized";
std::string const AS_OPERATOR = "operator";
std::string const AS_TEMPLATE = "template";
std::string const AS_TRY = "try";
std::string const AS_CATCH = "catch";
std::string const AS_FINALLY = "finally";
std::string const AS_THROWS = "throws";
std::string const AS_CONST = "const";
std::string const AS_ASM = "asm";
std::string const AS_BAR_DEFINE = "#define";
std::string const AS_BAR_INCLUDE = "#include";
std::string const AS_BAR_IF = "#if";
std::string const AS_BAR_EL = "#el";
std::string const AS_BAR_ENDIF = "#endif";
std::string const AS_OPEN_BRACKET = "{";
std::string const AS_CLOSE_BRACKET = "}";
std::string const AS_OPEN_LINE_COMMENT = "//";
std::string const AS_OPEN_COMMENT = "/*";
std::string const AS_CLOSE_COMMENT = "*/";
std::string const AS_ASSIGN = "=";
std::string const AS_PLUS_ASSIGN = "+=";
std::string const AS_MINUS_ASSIGN = "-=";
std::string const AS_MULT_ASSIGN = "*=";
std::string const AS_DIV_ASSIGN = "/=";
std::string const AS_MOD_ASSIGN = "%=";
std::string const AS_OR_ASSIGN = "|=";
std::string const AS_AND_ASSIGN = "&=";
std::string const AS_XOR_ASSIGN = "^=";
std::string const AS_GR_GR_ASSIGN = ">>=";
std::string const AS_LS_LS_ASSIGN = "<<=";
std::string const AS_GR_GR_GR_ASSIGN = ">>>=";
std::string const AS_LS_LS_LS_ASSIGN = "<<<=";
std::string const AS_RETURN = "return";
std::string const AS_EQUAL = "==";
std::string const AS_PLUS_PLUS = "++";
std::string const AS_MINUS_MINUS = "--";
std::string const AS_NOT_EQUAL = "!=";
std::string const AS_GR_EQUAL = ">=";
std::string const AS_GR_GR = ">>";
std::string const AS_GR_GR_GR = ">>>";
std::string const AS_LS_EQUAL = "<=";
std::string const AS_LS_LS = "<<";
std::string const AS_LS_LS_LS = "<<<";
std::string const AS_ARROW = "->";
std::string const AS_AND = "&&";
std::string const AS_OR = "||";
std::string const AS_COLON_COLON = "::";
std::string const AS_PAREN_PAREN = "()";
std::string const AS_BLPAREN_BLPAREN = "[]";
std::string const AS_PLUS = "+";
std::string const AS_MINUS = "-";
std::string const AS_MULT = "*";
std::string const AS_DIV = "/";
std::string const AS_MOD = "%";
std::string const AS_GR = ">";
std::string const AS_LS = "<";
std::string const AS_NOT = "!";
std::string const AS_BIT_OR = "|";
std::string const AS_BIT_AND = "&";
std::string const AS_BIT_NOT = "~";
std::string const AS_BIT_XOR = "^";
std::string const AS_QUESTION = "?";
std::string const AS_COLON = ":";
std::string const AS_COMMA = ",";
std::string const AS_SEMICOLON = ";";
std::string const AS_FOREACH = "foreach";
std::string const AS_LOCK = "lock";
std::string const AS_UNSAFE = "unsafe";
std::string const AS_FIXED = "fixed";
std::string const AS_GET = "get";
std::string const AS_SET = "set";
std::string const AS_ADD = "add";
std::string const AS_REMOVE = "remove";
static const string * headers_[] = { &AS_IF, &AS_ELSE, &AS_DO, &AS_WHILE, &AS_FOR,
&AS_SYNCHRONIZED, &AS_TRY, &AS_CATCH, &AS_FINALLY, &AS_SWITCH, &AS_TEMPLATE,
&AS_FOREACH, &AS_LOCK, &AS_UNSAFE, &AS_FIXED, &AS_GET, &AS_SET, &AS_ADD,
&AS_REMOVE
};
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_UNSAFE, &AS_GET, &AS_SET, &AS_ADD, &AS_REMOVE
//, &AS_TEMPLATE
};
static vector< const string * > nonParenHeaders( nonParenHeaders_, nonParenHeaders_ + ( sizeof(nonParenHeaders_) / sizeof(nonParenHeaders_[0] ) ) );
static const string * preDefinitionHeaders_[] = { &AS_CLASS, &AS_INTERFACE,
&AS_NAMESPACE, &AS_STRUCT
};
static vector< const string * > preDefinitionHeaders( preDefinitionHeaders_, preDefinitionHeaders_ + ( sizeof(preDefinitionHeaders_) / sizeof(preDefinitionHeaders_[0] ) ) );
static const string * preCommandHeaders_[] = { &AS_EXTERN, &AS_THROWS, &AS_CONST
};
static vector< const string * > preCommandHeaders( preCommandHeaders_, preCommandHeaders_ + ( sizeof(preCommandHeaders_) / sizeof(preCommandHeaders_[0] ) ) );
static const string * preprocessorHeaders_[] = { &AS_BAR_DEFINE
//, &AS_BAR_INCLUDE, &AS_BAR_IF, &AS_BAR_EL, &AS_BAR_ENDIF
};
static vector< const string * > preprocessorHeaders( preprocessorHeaders_, preprocessorHeaders_+ ( sizeof(preprocessorHeaders_) / sizeof(preprocessorHeaders_[0] ) ) );
static const string * operators_[] = { &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_EQUAL, &AS_PLUS_PLUS,
&AS_MINUS_MINUS, &AS_NOT_EQUAL, &AS_GR_EQUAL, &AS_GR_GR_GR_ASSIGN,
&AS_GR_GR_ASSIGN, &AS_GR_GR_GR, &AS_GR_GR, &AS_LS_EQUAL,
&AS_LS_LS_LS_ASSIGN, &AS_LS_LS_ASSIGN, &AS_LS_LS_LS, &AS_LS_LS,
&AS_ARROW, &AS_AND, &AS_OR, &AS_COLON_COLON, &AS_PLUS, &AS_MINUS,
&AS_MULT, &AS_DIV, &AS_MOD, &AS_QUESTION, &AS_COLON, &AS_ASSIGN,
&AS_LS, &AS_GR, &AS_NOT, &AS_BIT_OR, &AS_BIT_AND, &AS_BIT_NOT,
&AS_BIT_XOR, &AS_OPERATOR, &AS_COMMA, &AS_RETURN
//, &AS_PAREN_PAREN, &AS_BLPAREN_BLPAREN, &AS_SEMICOLON
};
static vector< const string * > operators( operators_, operators_ + ( sizeof(operators_) / sizeof(operators_[0]) ) );
static const string * assignmentOperators_[] = { &AS_PLUS_ASSIGN, &AS_MINUS_ASSIGN,
&AS_MULT_ASSIGN, &AS_DIV_ASSIGN, &AS_MOD_ASSIGN, &AS_XOR_ASSIGN,
&AS_OR_ASSIGN, &AS_AND_ASSIGN, &AS_GR_GR_GR_ASSIGN, &AS_LS_LS_LS_ASSIGN,
&AS_ASSIGN
};
static vector< const string * > assignmentOperators( assignmentOperators_, assignmentOperators_ + ( sizeof(assignmentOperators_) / sizeof(assignmentOperators_[0]) ) );
/**
* initialize the ASFormatter.
*
* init() should be called every time a ASFormatter 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 ASFormatter::init(istream & si)
{
ASBeautifier::init(si);
sourceIterator = &si;
delete( preBracketHeaderStack );
preBracketHeaderStack = new vector<const string*>;
delete( bracketTypeStack );
bracketTypeStack = new vector<BracketType>;
bracketTypeStack->push_back(DEFINITION_TYPE);
delete( parenStack );
parenStack = new vector<int>;
parenStack->push_back(0);
currentHeader = NULL;
currentLine = string("");
formattedLine = "";
currentChar = ' ';
previousCommandChar = ' ';
previousNonWSChar = ' ';
quoteChar = '"';
charNum = 0;
previousOperator = NULL;
isVirgin = true;
isInLineComment = false;
isInComment = false;
isInPreprocessor = false;
doesLineStartComment = false;
isInQuote = false;
isSpecialChar = false;
isNonParenHeader = true;
foundPreDefinitionHeader = false;
foundPreCommandHeader = false;
foundQuestionMark = false;
isInLineBreak = false;
endOfCodeReached = false;
isLineReady = false;
isPreviousBracketBlockRelated = true;
isInPotentialCalculation = false;
//foundOneLineBlock = false;
shouldReparseCurrentChar = false;
passedSemicolon = false;
passedColon = false;
isInTemplate = false;
shouldBreakLineAfterComments = false;
isImmediatelyPostComment = false;
isImmediatelyPostLineComment = false;
isImmediatelyPostEmptyBlock = false;
isPrependPostBlockEmptyLineRequested = false;
isAppendPostBlockEmptyLineRequested = false;
prependEmptyLine = false;
foundClosingHeader = false;
previousReadyFormattedLineLength = 0;
isImmediatelyPostHeader = false;
isInHeader = false;
}
/**
* get the next formatted line.
*
* @return formatted line.
*/
string ASFormatter::nextLine()
{
TRACE_LIFE( FUNCTION, "formatting new line." );
const string *newHeader;
bool isCharImmediatelyPostComment = false;
bool isPreviousCharPostComment = false;
bool isCharImmediatelyPostLineComment = false;
bool isInVirginLine = isVirgin;
bool isCharImmediatelyPostOpenBlock = false;
bool isCharImmediatelyPostCloseBlock = false;
bool isCharImmediatelyPostTemplate = false;
bool isCharImmediatelyPostHeader = false;
if ( ! isFormattingEnabled() )
{
TRACE( INFO, "formatting not enabled - delegating to ASBeautifier." );
return ASBeautifier::nextLine();
}
while ( ! isLineReady )
{
if ( shouldReparseCurrentChar )
{
TRACE( INFO, "reparsing character..." );
shouldReparseCurrentChar = false;
}
else if ( ! getNextChar() )
{
TRACE( INFO, "no more characters - breaking line and delegating to ASBeautifier." );
breakLine();
return beautify(readyFormattedLine);
}
else // stuff to do when reading a new character...
{
// make sure that a virgin '{' at the begining of the file will be treated as a block...
if ( isInVirginLine && currentChar == '{' )
{
TRACE( INFO, "virgin '{'" );
previousCommandChar = '{';
}
isPreviousCharPostComment = isCharImmediatelyPostComment;
isCharImmediatelyPostComment = false;
isCharImmediatelyPostTemplate = false;
isCharImmediatelyPostHeader = false;
}
// handle comments
if ( isInLineComment )
{
appendCurrentChar();
// explicitely break a line when a line comment's end is found.
if ( /* bracketFormatMode == ATTACH_MODE && */ charNum + 1 == currentLine.size())
{
isInLineBreak = true;
isInLineComment = false;
isImmediatelyPostLineComment = true;
currentChar = 0; //make sure it is a neutral char.
}
continue;
}
else if ( isInComment )
{
if ( isSequenceReached( AS_CLOSE_COMMENT ) )
{
isInComment = false;
isImmediatelyPostComment = true;
appendSequence( AS_CLOSE_COMMENT );
goForward( 1 );
}
else
{
appendCurrentChar();
}
continue;
}
// handle quotes
if ( isInQuote )
{
if ( isSpecialChar )
{
isSpecialChar = false;
appendCurrentChar();
}
else if ( currentChar == '\\' )
{
TRACE( INFO, "special (escaped) char entcountered" );
isSpecialChar = true;
appendCurrentChar();
}
else if ( quoteChar == currentChar )
{
TRACE( INFO, "end of quote encountered" );
isInQuote = false;
appendCurrentChar();
}
else
{
appendCurrentChar();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -