📄 cjparser.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
// Name: No names yet.
// Purpose: Contrib. demo
// Author: Aleksandras Gluchovas
// Modified by:
// Created: 22/09/98
// RCS-ID: $Id: cjparser.cpp,v 1.21 2005/09/23 12:56:18 MR Exp $
// Copyright: (c) Aleskandars Gluchovas
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "cjparser.h"
#if defined( wxUSE_TEMPLATE_STL )
#include <map>
#else
#include "wxstlac.h"
#endif
/***** Implementation for class SJParser *****/
// statics used by inline'ed C helper-functions
static char* _gSrcStart = 0;
static char* _gSrcEnd = 0;
static wxChar* _gLastSuppresedComment = 0;
static int _gLineNo = 0;
// FOR NOW:: comments queue is static
#define MAX_CQ_ENTRIES 128
static char* _gCommentsQueue[MAX_CQ_ENTRIES];
static int _gCQSize = 0;
/***** keyword map related structures *****/
struct less_c_str
{
inline bool operator()( char* x, char* y) const
{ return ( strcmp( x,y ) < 0 );
}
};
//WXSTL_MAP(CharPtrT,CharPtrT, LESS_THEN_FUNCTOR(CharPtrT));
#if defined( wxUSE_TEMPLATE_STL )
typedef map< char*, char*, less_c_str > KeywordMapT;
#else
typedef char* CharPtrT;
typedef WXSTL_MAP( CharPtrT, CharPtrT ,less_c_str) KeywordMapT;
#endif
static KeywordMapT __gMultiLangMap;
static int __gMapReady = 0;
static char* __gKeyWords[] =
{
"public",
"protected",
"private",
"class",
"struct",
"union",
"enum",
"interface",
"package",
"import",
"typedef",
"template",
"friend",
"const",
"volatile",
"mutable",
"virtual",
"inline",
"static",
"register",
"final",
"abstract",
"native",
"__stdcall",
"extern",
0
};
static void check_keyword_map()
{
if ( !__gMapReady )
{
__gMapReady = 1;
// "make sure" the address of the first member of non-polimorphic class
// coinsides with the address of the instance
char** keyword = __gKeyWords;
while ( (*keyword) != 0 )
{
__gMultiLangMap.insert(
KeywordMapT::value_type( *keyword, *keyword )
);
++keyword;
}
}
}
/***** helper functions *****/
static inline void skip_to_eol( char*& cur )
{
while( *(cur) != 10 && *cur != 13 && cur < _gSrcEnd) ++cur;
}
static inline void skip_eol( char*& cur )
{
if ( *cur == 13 )
cur += 2;
else
cur += 1;
++_gLineNo;
}
static inline bool skip_to_next_comment_in_the_line( char*& cur )
{
do
{
while( cur < _gSrcEnd &&
*cur != 10 &&
*cur != 13 &&
*cur != '/'
) ++cur;
if ( cur == _gSrcEnd ) return false;
if ( *cur == '/' )
{
if ( (*(cur+1) == '*') ||
(*(cur+1) == '/') ) return true;
else
{
++cur;
continue;
}
}
return false;
} while(1);
}
inline static void store_line_no( int& toVar )
{
toVar = _gLineNo;
}
inline static void restore_line_no( int storedLineNo )
{
_gLineNo = storedLineNo;
}
inline static int get_line_no()
{
return _gLineNo;
}
static void skip_to_prev_line( char*& cur )
{
while( cur >= _gSrcStart &&
*cur != 10 &&
*cur != 13
) --cur;
// NOTE:: '\n' is 13,10 for DOS
// '\n' is 10 for UNIX
// NOTE1: '\n' symbol is not used here,
// to provide possibility of loading
// file as binary
--cur;
if ( *cur == 10 )
{
++cur;
return;
}
if ( *cur == 13 ) --cur;
while( cur >= _gSrcStart &&
*cur != 10 &&
*cur != 13
) --cur;
++cur; // move to the first character in the line
}
static inline void skip_comments( char*& cur )
{
++cur; // skip '/' token
if ( *cur != '/' && *cur != '*' ) return;
// first, store position of the comment into the queue
// (which further will be attached to the next context
// found)
if ( cur-1 != _gLastSuppresedComment )
{
if ( _gCQSize == MAX_CQ_ENTRIES )
{
size_t i = MAX_CQ_ENTRIES-1;
while( i != 0 )
{
_gCommentsQueue[i-1] = _gCommentsQueue[i];
--i;
}
--_gCQSize ;
}
_gCommentsQueue[_gCQSize++] = cur-1;
}
// if signle-line comment, skip it now
if ( *cur == '/' )
{
skip_to_eol( cur );
skip_eol( cur );
return;
}
size_t level = 1;
// check for multiline comment (handle nested multiline comments!)
int line_len = 0;
++cur;
++cur;
do
{
// TBD:: check eof cond.
// detect and remove vertical columns of '*''s
while ( *cur != '/' && cur < _gSrcEnd )
{
switch (*cur)
{
case '*' :
{
if ( *(cur+1) != '/' )
{
if ( line_len == 1 )
*cur = ' ';
}
break;
}
case 13 : line_len = 0; break;
case 10 : { line_len = 0; ++_gLineNo; } break;
default : ++line_len;
}
++cur;
}
if ( cur >= _gSrcEnd ) return;
++cur;
if ( *(cur-2) == '*' )
{
--level;
if ( level == 0 )
break;
}
else
if ( *cur == '*' )
{
++cur;
++cur;
++level;
}
} while(1);
}
static inline void clear_commets_queue()
{
_gCQSize = 0;
}
static inline void skip_quoted_string( char*& cur )
{
++cur; // skip first quote '"'
// check if quote wasn't prefixed
if ( *(cur-2) == '\\' )
return;
do
{
while ( *cur != '"' && cur < _gSrcEnd )
{
if ( *cur == 10 ) ++_gLineNo;
++cur;
}
if ( cur >= _gSrcEnd ) return;
++cur; // skip the last quote
// check if it wasn't prefixed
if ( *(cur-2) != '\\' )
break;
} while (1);
}
// skips subsequent white space and comments
// (return false if the end of source code reached)
static inline bool get_next_token( char*& cur )
{
for( ; cur < _gSrcEnd; ++cur )
{
switch( *(cur) )
{
case ' ' : continue;
case '\t': continue;
case 13 : continue;
case 10 : { ++_gLineNo;continue; }
case '/' : skip_comments( cur );
--cur;
continue;
default : break;
};
break;
}
if ( cur >= _gSrcEnd )
return false;
else
return true;
}
static inline void skip_preprocessor_dir( wxChar*& cur )
{
do
{
skip_to_eol(cur);
if ( *(cur-1) != _T('\\') )
break;
if ( cur < _gSrcEnd )
skip_eol( cur );
else
break;
} while(1);
}
static void skip_token( char*& cur )
{
if ( *cur == '"' )
{
skip_quoted_string( cur );
return;
}
if ( *cur == ',' ||
*cur == ';' ||
*cur == ')' ||
*cur == '('
)
{
++cur;
return;
}
// special case of "!=", "<=", ... 2 character composite tokens
if ( *cur == '<' ||
*cur == '>' ||
*cur == '=' ||
*cur == '!'
)
{
cur++;
if ( *cur == '=' )
cur++;
return;
}
++cur; // leading character is always skipped
for( ; cur < _gSrcEnd ; ++cur )
{
switch ( *cur )
{
case ' ' : break;
case '\t': break;
case 13 : break;
case 10 : break;
case ',' : break;
case ';' : break;
case '<' : break;
case '>' : break;
// FIXME:: QUICK-HACK:: to treat scope resolution
// tokens are a part of the string - e.g. SomeSpace::SubName would
// become one token
case ':' : if ( *(cur+1) == ':' )
{
++cur;
continue;
}
break;
case '=' : break;
case '(' : break;
case ')' : break;
case '{' : break;
case '}' : break;
default : continue;
};
break;
}
}
static inline size_t get_token_len( char* tok )
{
char* start = tok;
skip_token( tok );
return size_t( tok - start );
}
// returns true, if given tokens are equel
static inline bool cmp_tokens( char* tok1, char* tok2 )
{
// NOTE:: the case one token includes
// other in it's entirely is not handled
size_t len = get_token_len( tok1 );
// assuming that tokens are non-zero length
do
{
if ( *(tok1++) != *(tok2++) )
return false;
--len;
} while ( --len );
return true;
}
static inline bool cmp_tokens_fast( char* tok1, char* tok2, size_t len )
{
do
{
if ( *(tok1++) != *(tok2++) )
return false;
} while ( --len );
return true;
}
static inline void skip_tempalate_statement( char*& cur )
{
size_t level = 0;
// go one level deeper
while( *cur != '<' && cur < _gSrcEnd )
{
if (*cur == 10 ) ++_gLineNo;
++cur;
}
// FIXME:: template should be checked statement for
// comments inside of it
do
{
if ( *cur == '<' )
++level;
else
--level;
++cur; // skip '<' or '>' token
if ( level == 0 )
return;
while( *cur != '<' && *cur != '>' && cur < _gSrcEnd )
{
if (*cur == 10 ) ++_gLineNo;
++cur;
}
} while (1);
}
static inline void skip_statement( char*& cur )
{
for( ; cur < _gSrcEnd; ++cur )
switch (*cur)
{
case ';' : ++cur; // skip statement-terminator token
return;
case '"' : skip_quoted_string(cur);
--cur;
continue;
case 10 : ++_gLineNo;
continue;
case '/' : skip_comments( cur );
--cur;
continue;
default : continue;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -