/***************************************************************************/
// "Меркурий"-"Правда" - open source переводчик
// распространяется в соответсвии с лицензией GNU v 2.0
//
// Класс, разбивающий текстовый файл на слова
// Анисимов Д.В. сегодня
/***************************************************************************/
# include <string.h>
# include "mylib.h"
# include "lexer.h"
# define Ifstr( a,b ) if( 0==strcmp(a,b)
)
/***************************************************************************/
t_Lexer :: t_Lexer( void )
{
Mass = NULL ;
Mass1 = NULL ;
Word = NULL ;
Str = NULL ;
l_Mass = 0 ;
n_Word = 0 ;
clr_breaker( );
}
/***************************************************************************/
t_Lexer :: ~t_Lexer( void )
{
Free( Mass );
Free( Mass1 );
Free( Word );
Free( Str );
}
/***************************************************************************/
// установить какие символы являются разделителями слов
/***************************************************************************/
// set_breaker( ".,;:#$%^=+-*/(){}<>[]\"\\" );
void t_Lexer :: set_breaker( unsigned char *Breaker )
{
for( short i=0 ; i<256 && Breaker[i]!=0 ; i++ )
Type[Breaker[i]]=1 ;
}
/***************************************************************************/
// установить дефолтные символы, разделители слов
/***************************************************************************/
void t_Lexer :: clr_breaker( void )
{
for( short i=0 ; i<256 ; i++ )
Type[i]=0 ;
Type[' '] =2 ;Type['\t']=2;
Type['\n']=3 ;Type['\r']=3 ;
}
/***************************************************************************/
// задать массив, который будет разбираться на слова
/***************************************************************************/
void t_Lexer :: init( char *_Mass, long _L )
{
Free( Mass ); Free( Mass1 ); Free( Word ); Free( Str );
Mass=(char *)Calloc(_L,sizeof(char));
Str =(long *)Calloc( max(3,_L/2) ,sizeof(long));
// число слов надо посчитать более корректно
l_Mass=_L ;
memcpy( Mass,_Mass,l_Mass );
remark( );
}
/***************************************************************************/
void t_Lexer :: init1( char *_Mass, long _L )
{
Free( Mass ); Free( Mass1 ); Free( Word ); Free( Str );
Mass=(char *)Calloc(_L,sizeof(char));
Str =(long *)Calloc( max(3,_L/2) ,sizeof(long));
// число слов надо посчитать более корректно
l_Mass=_L ;
memcpy( Mass,_Mass,l_Mass );
remark1( );
}
/***************************************************************************/
// удалить коментарии
/***************************************************************************/
void t_Lexer :: remark( void )
{ long i,j,N ;
char c1,c2=' ' ;
register char f,c ;
N=l_Mass-1 ;
f=0 ;
for( i=j=0 ; i<N ; i++ )
{ c=Mass[i] ;
if( f==0 )
{
f=( c=='#' );
if( c=='/' )
{ c1=Mass[i+1] ;
if( c1=='/' ) f=1 ;
if( c1=='*' ) f=2 ;
}
}
if( f==0 ) continue ;
else Mass[i]=' ' ;
if( c=='\n' && f==1 ) f=0 ;
if( f==2 && c2=='*' && c=='/' ) f=0 ;
c2=c ;
}
}
/***************************************************************************/
// удалить коментарии
/***************************************************************************/
void t_Lexer :: remark1( void )
{ long i,j,N ;
char c1,c2=' ' ;
register char f,c ;
N=l_Mass-1 ;
f=0 ;
for( i=j=0 ; i<N ; i++ )
{ c=Mass[i] ;
if( f==0 )
{
if( c=='/' )
{ c1=Mass[i+1] ;
if( c1=='/' ) f=1 ;
if( c1=='*' ) f=2 ;
}
}
if( f==0 ) continue ;
else Mass[i]=' ' ;
if( c=='\n' && f==1 ) f=0 ;
if( f==2 && c2=='*' && c=='/' ) f=0 ;
c2=c ;
}
}
/***************************************************************************/
// создать из текста массив слов
/***************************************************************************/
void t_Lexer :: make_words( void )
{
long i,j,j_Word,n,j_Str=0 ;
register char t,c ;
Mass1=(char *)Calloc( 2*l_Mass,sizeof(char) );
for( i=j=n=0 ; i<l_Mass ; i++ )
{ c=Mass[i] ;
if( 0<=c )
{ t=Type[c] ;
if( t==1 ) // ------ если разделитель ----------
{
if( 0<j && Mass1[j-1]!=0 )
{ Mass1[j++]=0 ; Str[n]=j_Str ; n++ ; }
Mass1[j++]=c ;
Mass1[j++]=0 ;
Str[n]=j_Str ; /* ABW1 */
n++ ;
continue ;
}
if( t==2 || t==3 ) // ------ если новая строка ----------
{ if( Mass[i]=='\n' ) j_Str++ ;
if( 0<j && Mass1[j-1]!=0 )
{ Mass1[j++]=0 ; Str[n]=j_Str ; n++ ; }
continue ;
}
}
Mass1[j++]=c ;
}
n_Word=n ;
Word =(char **)Calloc( n_Word+1,sizeof(char *));
Word[0]=Mass1 ;
for( i=j_Word=0 ; i<j ; i++ )
{
if( 0==Mass1[i] )
{
Word[++j_Word]=Mass1+i+1 ;
}
}
}
/* ---------------------------------------------------------------------- */
char
* t_Lexer :: word( long i )
{ return Word[i] ; }
/* ---------------------------------------------------------------------- */
long t_Lexer :: n_word( void )
{ return n_Word ; }
/* ---------------------------------------------------------------------- */
long t_Lexer :: str( long i )
{ return Str[i] ; }
/**************************************************************************/
// найти закрывающую скобку для соответствующей открывающей
// Begin - с какого слова начинать искать
// Open - что мы считаем открывающей скобкой
// Close - что мы считаем закрывающей скобкой
/**************************************************************************/
long t_Lexer :: find_paar( long Begin, char *Open, char *Close )
{ long i,s=-1 ;
for( i=Begin ; i<n_Word ; i++ )
if( 0==strcmp(Word[i],Open) ) { s=0 ; break ; }
if( s<0 ) return Begin ;
for( ; i<n_Word ; i++ )
{ Ifstr( Word[i],Open ) s++ ;
Ifstr( Word[i],Close) s-- ;
if( s==0 ) return i ;
}
return -1 ;
}
/**************************************************************************/
// найти в тексте нужное слово
// Begin - с какого слова начинать искать
// W - что за слово мы ищем
/**************************************************************************/
long t_Lexer :: find_word( long Begin, char *W )
{
for( long i=Begin ; i<n_Word ; i++ )
if( 0==strcmp(Word[i],W) ) return i ;
return -1 ;
}
/* ---------------------------------------------------------------------- */
void t_Lexer :: error( long i )
{ printf("\n Строка %ld неизвестное слово %s",Str[i],Word[i] );
throw( -1 );
}