📄 bcgpoutlineparser.cpp
字号:
// BCGPOutlineParser.cpp: implementation of the CBCGPOutlineParser class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "bcgcbpro.h"
#include "BCGPOutlineParser.h"
#include "BCGPEditCtrl.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CBCGPOutlineParser::CBCGPOutlineParser()
{
}
CBCGPOutlineParser::~CBCGPOutlineParser()
{
RemoveAllBlockTypes ();
}
void CBCGPOutlineParser::RemoveAllBlockTypes ()
{
for (int i = 0; i <= m_arrBlockTypes.GetUpperBound (); i++)
{
delete m_arrBlockTypes.GetAt (i);
}
m_arrBlockTypes.RemoveAll ();
}
void CBCGPOutlineParser::Init ()
{
RemoveAllBlockTypes ();
// Default init for C++ outline blocks:
AddEscapeSequence (_T("\\\""));
AddBlockType (_T("\""), _T("\""), _T("\"\""), FALSE, TRUE);
AddBlockType (_T("//"), _T("\n"), _T("/**/"), FALSE, TRUE);
AddBlockType (_T("/*"), _T("*/"), _T("/**/"), FALSE, FALSE);
CStringList lstKeywords;
lstKeywords.AddTail (_T("if"));
lstKeywords.AddTail (_T("else"));
lstKeywords.AddTail (_T("while"));
lstKeywords.AddTail (_T("for"));
lstKeywords.AddTail (_T("do"));
lstKeywords.AddTail (_T("switch"));
lstKeywords.AddTail (_T("class"));
lstKeywords.AddTail (_T("union"));
lstKeywords.AddTail (_T("struct"));
lstKeywords.AddTail (_T("namespace"));
lstKeywords.AddTail (_T("catch"));
lstKeywords.AddTail (_T("try"));
lstKeywords.AddTail (_T("operator"));
AddBlockType (_T("{"), _T("}"), _T("..."), TRUE, FALSE, &lstKeywords);
}
//************************************************************************************
void CBCGPOutlineParser::AddBlockType (LPCTSTR lpszOpen, LPCTSTR lpszClose, LPCTSTR lpszReplace, BOOL bNested, BOOL bIgnore, CStringList* pKeywordsList)
{
ASSERT (lpszOpen != NULL);
ASSERT (lpszClose != NULL);
CString strClose = lpszClose;
if (strClose.IsEmpty ())
{
AddEscapeSequence (lpszOpen);
return;
}
BlockType* pNewBlockType = new BlockType (
lpszOpen, lpszClose, (lpszReplace != NULL) ? lpszReplace : _T("..."), bNested, bIgnore, pKeywordsList);
m_arrBlockTypes.Add (pNewBlockType);
}
//************************************************************************************
void CBCGPOutlineParser::AddEscapeSequence (LPCTSTR lpszStr)
{
ASSERT (lpszStr != NULL);
m_lstEscapeSequences.AddTail (lpszStr);
}
//************************************************************************************
const BlockType* CBCGPOutlineParser::GetBlockType (int nIndex) const
{
if (nIndex >= 0 && nIndex <= m_arrBlockTypes.GetUpperBound ())
{
return m_arrBlockTypes [nIndex];
}
else
{
ASSERT (FALSE);
return NULL;
}
}
/*
XML format:
-----------
<SETTINGS>
<OUTLINE_DATA>
<IgnoreOneLineBlocks></IgnoreOneLineBlocks>
<EscapeSequences>
<EscapeSequence></EscapeSequence>
</EscapeSequences>
<BLOCKS>
<BLOCK>
<Start></Start>
<End></End>
<ReplaceString></ReplaceString>
<AllowNestedBlocks></AllowNestedBlocks>
<Ignore></Ignore>
</BLOCK>
</BLOCKS>
</OUTLINE_DATA>
</SETTINGS>
<IgnoreOneLineBlocks> "False" by default
<Start> => m_strOpen;
<End> => m_strClose;
<ReplaceString> => m_strReplace; "..." by default
<AllowNestedBlocks> => m_bAllowNestedBlocks; "True" by default
<Ignore> => m_bIgnore "False" by default
Default XML settings for C++:
-----------------------------
<SETTINGS>
<OUTLINE_DATA>
<IgnoreOneLineBlocks>True</IgnoreOneLineBlocks>
<IncludeSpaceLines>True</IncludeSpaceLines>
<EscapeSequences>
<EscapeSequence>\\\"</EscapeSequence>
</EscapeSequences>
<BLOCKS>
<BLOCK>
<Start>\"</Start>
<End>\"</End>
<ReplaceString>\"\"</ReplaceString>
<AllowNestedBlocks>False</AllowNestedBlocks>
<Ignore>True</Ignore>
</BLOCK>
<BLOCK>
<Start>{</Start>
<End>}</End>
<ReplaceString>..</ReplaceString>
<KEYWORDS>
<Keyword>else</Keyword>
<Keyword>struct</Keyword>
<Keyword>enum</Keyword>
<Keyword>switch</Keyword>
<Keyword>catch</Keyword>
<Keyword>try</Keyword>
<Keyword>for</Keyword>
<Keyword>operator</Keyword>
<Keyword>class</Keyword>
<Keyword>if</Keyword>
<Keyword>union</Keyword>
<Keyword>do</Keyword>
<Keyword>while</Keyword>
<Keyword>namespace</Keyword>
</KEYWORDS>
</BLOCK>
<BLOCK>
<Start>{</Start>
<End>}</End>
<ReplaceString>...</ReplaceString>
</BLOCK>
*/
// <BLOCK>
// <Start>//</Start>
// <End>\n</End>
// <ReplaceString>/**/</ReplaceString>
// <AllowNestedBlocks>False</AllowNestedBlocks>
// </BLOCK>
// <BLOCK>
// <Start>/*</Start>
// <End>*/</End>
// <ReplaceString>/**/</ReplaceString>
// <AllowNestedBlocks>False</AllowNestedBlocks>
// </BLOCK>
/*
</BLOCKS>
</OUTLINE_DATA>
</SETTINGS>
*/
//************************************************************************************
static BOOL Compare (const CString& strBuffer, const int nBufferOffset, const CString& strCompareWith, int& nEndOffset)
{
// Returns equal chars num:
const int nLength = strCompareWith.GetLength ();
const int nBufLength = strBuffer.GetLength ();
for (int i = 0; i < nLength && nBufferOffset + i < nBufLength; i++)
{
if (strCompareWith [i] != strBuffer [nBufferOffset + i])
{
nEndOffset = nBufferOffset;
return FALSE;
}
}
nEndOffset = nBufferOffset + i - 1;
return i > 0;
}
//************************************************************************************
BOOL CBCGPOutlineParser::IsEscapeSequence (const CString& strBuffer, int& nBufferOffset) const
{
for (POSITION pos = m_lstEscapeSequences.GetHeadPosition (); pos != NULL; )
{
const CString& str = m_lstEscapeSequences.GetNext (pos);
int nEndOffset;
if (str.GetLength () > 0 &&
Compare (strBuffer, nBufferOffset, str, nEndOffset))
{
nBufferOffset += str.GetLength ();
return TRUE;
}
}
return FALSE;
}
//************************************************************************************
Lexeme CBCGPOutlineParser::GetNext (const CString& strIn, int& nOffset, const int nSearchTo)
{
while (nOffset >= 0 && nOffset < strIn.GetLength () && nOffset <= nSearchTo)
{
if (IsEscapeSequence (strIn, nOffset))
{
continue;
}
for (int i = 0; i <= m_arrBlockTypes.GetUpperBound (); i++)
{
BlockType* pBlockType = m_arrBlockTypes [i];
ASSERT (pBlockType != NULL);
// Nested blocks:
if (pBlockType->m_bAllowNestedBlocks)
{
int nEndOffset;
if (Compare (strIn, nOffset, pBlockType->m_strOpen, nEndOffset))
{
Lexeme lexem (i, LT_BlockStart, nOffset, nEndOffset);
nOffset += pBlockType->m_strOpen.GetLength ();
return lexem;
}
else if (Compare (strIn, nOffset, pBlockType->m_strClose, nEndOffset))
{
Lexeme lexem (i, LT_BlockEnd, nOffset, nEndOffset);
nOffset += pBlockType->m_strClose.GetLength ();
return lexem;
}
}
// NonNested blocks:
else
{
int nEndOffset;
if (Compare (strIn, nOffset, pBlockType->m_strOpen, nEndOffset))
{
Lexeme lexem (i, LT_CompleteBlock, nOffset, nEndOffset);
nOffset += pBlockType->m_strOpen.GetLength ();
if (!pBlockType->m_strClose.IsEmpty ())
{
// find close token skipping escape sequences:
while (nOffset >= 0 &&
nOffset < strIn.GetLength () &&
nOffset <= nSearchTo)
{
if (IsEscapeSequence (strIn, nOffset))
{
continue;
}
if (Compare (strIn, nOffset, pBlockType->m_strClose, nEndOffset))
{
nOffset += pBlockType->m_strClose.GetLength ();
if (pBlockType->m_strClose == _T("\n"))
{
nOffset--;
}
lexem.m_nEnd = nOffset - 1;
return lexem;
}
nOffset++;
}
}
lexem.m_nEnd = strIn.GetLength () - 1;
return lexem;
}
}
}
nOffset++;
}
return Lexeme (0, LT_EndOfText, 0, 0);
}
//************************************************************************************
void CBCGPOutlineParser::PushResult (Lexeme lexem, CObList& lstResults)
{
CString str;
const BlockType* pBlockType = GetBlockType (lexem.m_nBlockType);
ASSERT (pBlockType != NULL);
switch (lexem.m_nType)
{
case LT_CompleteBlock:
{
CBCGPOutlineBaseNode block;
block.m_nStart = lexem.m_nStart;
block.m_nEnd = lexem.m_nEnd;
block.m_nNameOffset;
block.m_strReplace = pBlockType->m_strReplace;
block.m_nBlockType = lexem.m_nBlockType;
block.m_dwFlags = g_dwOBFComplete;
CBCGPOutlineNode* pNode = new CBCGPOutlineNode (block);
ASSERT_VALID (pNode);
lstResults.AddTail (pNode);
}
str.Format (_T("%s_%d_%d, "), pBlockType->m_strReplace, lexem.m_nStart, lexem.m_nEnd);
break;
case LT_BlockStart:
{
CBCGPOutlineBaseNode block;
block.m_nStart = lexem.m_nStart;
block.m_nEnd = lexem.m_nEnd;
block.m_nNameOffset;
block.m_strReplace = pBlockType->m_strReplace;
block.m_nBlockType = lexem.m_nBlockType;
block.m_dwFlags = g_dwOBFLeft;
CBCGPOutlineNode* pNode = new CBCGPOutlineNode (block);
ASSERT_VALID (pNode);
lstResults.AddTail (pNode);
}
str.Format (_T("{_%d, "), lexem.m_nStart);
break;
case LT_BlockEnd:
{
CBCGPOutlineBaseNode block;
block.m_nStart = lexem.m_nStart;
block.m_nEnd = lexem.m_nEnd;
block.m_nNameOffset;
block.m_strReplace = pBlockType->m_strReplace;
block.m_nBlockType = lexem.m_nBlockType;
block.m_dwFlags = g_dwOBFRight;
CBCGPOutlineNode* pNode = new CBCGPOutlineNode (block);
ASSERT_VALID (pNode);
lstResults.AddTail (pNode);
}
str.Format (_T("}_%d, "), lexem.m_nEnd);
break;
case LT_Eps:
str = _T("Finished");
break;
default:
str = _T("Error! ");
}
m_strOut += str;
}
//************************************************************************************
void CBCGPOutlineParser::DoParse (const CString& strBuffer,
const int nStartOffset, const int nEndOffset,
CObList& lstResults)
{
ASSERT (nStartOffset >= 0);
ASSERT (nEndOffset < strBuffer.GetLength ());
ASSERT (nStartOffset <= nEndOffset);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -