/****************************************************************************/ // "Меркурий"-"Правда" - open source переводчик // распространяется в соответсвии с лицензией GNU v 2.0 // // Грамматический словарь // Анисимов Д.В. сегодня /****************************************************************************/ # include <stdio.h> # include <string.h> # include <stdlib.h> # include <mylib.h> # include <slowo2.h> struct t_Sort { long i ; char *s ; }; t_Form Form0 ; //uchar *SC ; /****************************************************************************/ // инициировать нулями /****************************************************************************/ t_Slowo2 :: t_Slowo2( void ) { Lang =NULL ; Format =NULL ; n_Word=0 ; n_Form=0 ; Mass=NULL ; Word=NULL ; reverce=NULL ; Form0.init(); } /***************************************************************************/ // установить Lang и формат /***************************************************************************/ void t_Slowo2 :: set_lf( t_Lang *_Lang, t_Format *_Format ) { Lang = _Lang ; Format= _Format ; } /***************************************************************************/ // сравнить два слова из словаря (для сортировки) /***************************************************************************/ int wordcmp( const void *s1, const void *s2 ) { return Strcmp( ((t_Sort *)s1)->s,((t_Sort *)s2)->s ); } /***************************************************************************/ // прочесть словарь из файла в соответствии с форматом // File - имя файла // Lang - язык (источник или приемник), которому принадлежит словарь // _Format - формат, которому соответствует этот язык /***************************************************************************/ void t_Slowo2 :: read( char *File, t_Lang *_Lang, t_Format *_Format ) { FILE *fr ; long i,i1,j,z,L ; char *Str ; t_Lexer Lexer ; t_Sort *ss ; try { //SC = SortChar(); Lang = _Lang ; Format= _Format ; n_Form=Format->Record.j ; fr=Fopen( File,"r" ); L=FileLength( fr ); Mass=(char *)Calloc( L,sizeof(char) ); Fread( Mass,L,sizeof(char),fr ); Lexer.clr_breaker( ); Lexer.init( Mass,L ); Lexer.remark(); Lexer.make_words(); for( i=0,n_Word=0 ; i<Lexer.n_Word ; i++ ) if( ';'==Lexer.Word[i][0] ) n_Word++ ; Word=(long *)Calloc( n_Word*n_Form,sizeof(long) ); // ---- отсортировать строки по алфавиту ----- ss=(t_Sort *)Malloc( n_Word,sizeof(t_Sort) ); for( i=0 ; i<n_Word ; i++ ) { ss[i].i=i*(n_Form+1) ; ss[i].s=Lexer.Word[i*(n_Form+1)] ; } qsort( ss,n_Word,sizeof(t_Sort),wordcmp ); for( i=z=0 ; i<n_Word ; i++ ) { for( i1=j=0 ; i1<n_Form+2 ; i1++ ) { Str=Lexer.Word[ ss[i].i+i1 ] ; if( 0==strcmp(Str,";") ) { if( n_Form!=j ) { fprintf( File_Error,"\n Че-то странное с форматом %s",File ); fprintf( File_Error,"\n Строка \"%s\" дурит",Mass+Word[i*n_Form] ); throw(-1); } break ; } // --------------- чтение слова --------------- Word[i*n_Form+j] = z ; strcpy( Mass+z,Str ); z+=strlen( Str )+1 ; j++ ; } } Free( ss ); } catch( int E ) { fprintf( File_Error,"\n Ребята, че-то я словарь %s не могу прочесть.",File ); if( E==Err_Fopen ) fprintf( File_Error,"\n А он вообще-то есть?" ); throw( E ); } } /***************************************************************************/ // построить таблицы для поиска слов, заданных не в начальной форме /***************************************************************************/ void t_Slowo2 :: freverce( void ) { long i,n_All ; t_Sort *ss ; // ---- отсортировать строки по алфавиту ----- n_All=n_Word*n_Form ; ss=(t_Sort *)Malloc( n_All,sizeof(t_Sort) ); for( i=0 ; i<n_All ; i++ ) { ss[i].i=i ; ss[i].s=Mass+Word[i] ; } qsort( ss,n_All,sizeof(t_Sort),wordcmp ); reverce=(long *)Malloc( n_All,sizeof(long) ); for( i=0 ; i<n_All ; i++ ) reverce[i]=ss[i].i ; Free( ss ); } /***************************************************************************/ // вернуть слово в начальной форме // index - индекс слова (строки) /***************************************************************************/ char * t_Slowo2 :: normal( long index ) { return Mass + Word[index*n_Form] ; } /***************************************************************************/ // вернуть слово в заданной форме // index - индекс слова (строки) // Form - форма слова /***************************************************************************/ char * t_Slowo2 :: form( long index, t_Form *Form ) { long i,i1,i_Form ; t_Form *R ; t_Param1List *Param ; Param=&Lang->Part[Format->i_part].Param ; // параметры этой части речи i_Form=0 ; for( i=0 ; i<Format->Record.j ; i++ ) { R=&Format->Record[i] ; for( i1=0 ; i1<Param->j ; i1++ ) if( Param->list[i1].Dir==0 && // переменный параметр слова Form->value[i1]>=0 && // параметр задан в конструкции R->value[i1]>=0 && // параметр задан в словаре Form->value[i1]!=R->value[i1] ) // параметр не соответствует goto M_No; i_Form=i ; break ; M_No:; } return Mass + Word[index*n_Form+i_Form] ; } /***************************************************************************/ // вернуть слово в заданной форме (другой интерфейс) // Str - слово в начальной форме // Form1 - форма слова /***************************************************************************/ char * t_Slowo2 :: form( char *Str, t_Form *Form1 ) { long i,S1,S2,SS ; S1=0 ; S2=n_Word-1 ; while( 1 ) { if( S2-S1<=4 ) break ; SS=(S1+S2)/2 ; if( 0<Strcmp( Str,Mass+Word[SS*n_Form] ) ) S1=SS ; else S2=SS ; } for( i=S1 ; i<=S2 ; i++ ) if( 0==Strcmp( Str,Mass+Word[i*n_Form] ) ) goto M_Found ; return Str ; M_Found: return form( i, Form1 ); } /**************************************************************************/ // найти слово и определить в какой оно форме // Str - искомое слово // Ant - индексы подходящих слов // _Form - их формы /**************************************************************************/ short t_Slowo2 :: quest( char *Str, long *Ant, t_Form *_Form ) { long i,i1,j,S1,S2,S21,SS ; char f ; S1=0 ; S2=S21=n_Word*n_Form ; // ---- установить i на первое слово в массиве reverce, равное Str ---- while( 1 ) { if( S2-S1<=4 ) { for( i=S1 ; i<=S2 && i<S21 ; i++ ) if( 0==Strcmp( Str,Mass+Word[reverce[i]] ) ) break ; S1=i ; break ; } SS=(S1+S2)/2 ; f=Strcmp( Str,Mass+Word[reverce[SS]] ); if( 0<f ) S1=SS ; if( 0>f ) S2=SS ; if( f==0 ) { for( i=SS ; S1<=i ; i--) if( 0!=Strcmp( Str,Mass+Word[reverce[i]] ) ) { S1=i+1 ; break ; } break ; } } // -------------- заполнить масивы ответов --------------------------- for( j=0,i=S1 ; i<n_Word*n_Form ; i++ ) { i1=reverce[i] ; if( 0!=Strcmp( Str,Mass+Word[i1] ) ) break ; Ant[j] = i1/n_Form ; // -------- прописать переменные параметры слова ---------- _Form[j] = Format->Record[ i1%n_Form ] ; j++ ; if( 20<=j ) break ; } return j ; } /***************************************************************************/ // найти номер слова в словаре /***************************************************************************/ long t_Slowo2 :: find( char *str ) { long a,b,c,i ; a=0 ; b=n_Word-1 ; while( 1 ) { if( b-a<10 ) { for( i=a ; i<=b ; i++ ) { if( 0==Strncmp( str,Mass+Word[i*n_Form],40 ) ) return i ; } return -1 ; } c=(a+b)>>1 ; if( 0<Strncmp( str,Mass+Word[c*n_Form],40 ) ) a=c ; else b=c ; } } /***************************************************************************/ // есть ли в словаре такое слово /***************************************************************************/ char t_Slowo2 :: word_exist( char *str ) { if( 0>find( str ) ) return -1 ; else return 0 ; } /***************************************************************************/ // напечатать все формы слова в заданный файл /***************************************************************************/ void t_Slowo2 :: print_word( FILE *fw, long index ) { long i,N ; N=Format->Record.j ; for( i=0 ; i<N ; i++ ) fprintf( fw,"%s ",Mass + Word[index*n_Form+i] ); fprintf( fw,";\n"); }