/***************************************************************************/ // "Меркурий"-"Правда" - 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 ); }