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