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

📄 asformatter.cpp

📁 非常好用的可移植的多平台C/C++源代码编辑器
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// $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 + -