📄 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-functionsstatic 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 128static 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;#endifstatic 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 equelstatic 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 + -