/***************************************************************************/
// "Меркурий"-"Правда" - open source переводчик
// распространяется в соответсвии с лицензией GNU v 2.0
//
// главная программа перевода
// Анисимов Д.В. сегодня
/***************************************************************************/
# include <string.h>
# include <stdlib.h>
# include <unistd.h>
# include <mylib.h>
# include <slowo2.h>
# include <slowo3.h>
# include <grammar.h>
# include <core.h>
t_Slowo3 Macro ; // словарь английских сокращений (препроцессор)
t_Slowo3 Micro ; // словарь русских сокращений (постпроцессор)
t_Slowo3 DicConst ; // словарь английских constant
t_Slowo3 Perevod ; // словарь переводов
t_Slowo2 *SlowoF, // грамматические словари языка-оригинала
*SlowoT ; // грамматические словари языка-перевода
short *i_FormatT ; // соответствие часть речи -> SlowoT
short *i_FormatF ; // соответствие часть речи -> SlowoF
t_Core Core ;
static char f_data_read=0 ; // данные уже были прочитаны
void make_dic_const( void );
short find_enum_select( e_Half H, short up_struct, long i_slowo );
char compare_param( t_Param1List *Param, t_Form *Form );
void word_source( short i_struct, char *Word, char *Source, e_Half H );
char is_number( char *Str );
t_Tree *part_of_struct( t_TreeList &Tree, long i_tree, short i_word );
static void print_tree( t_TreeList &Node, char *FileName );
static void make_token( char *Sou, char *Dst );
/***************************************************************************/
char *filename( char *Path, char *File )
{ static char Str[200] ;
Strcpy( Str,Path,200 );
if( Str[strlen(Str)-1]!='/' )
Strcat( Str,"/",200 );
Strcat( Str,File,200 );
return Str ;
}
/***************************************************************************/
// прочесть все данные
/***************************************************************************/
char read_grammar( char *Dir )
{
t_File *F ;
long i,N ;
char *Path="..";
char Path1[200] ;
char r ;
try
{
if( Dir[0]!=0 ) Path=Dir ;
r=Grammar.make_all( filename( Path,"grammar/lang.txt" ) );
if( r<0 ) return r ;
File_Error=Fopen("mercury.err","w+");
Macro.read( filename( Path,"dicts/en_macro" ), &(Grammar.format1()[0]) );
Micro.read( filename( Path,"dicts/en_macro" ), &(Grammar.format1()[0]) );
make_dic_const( );
Strcpy( Path1,Path,200 );
if( Path1[strlen(Path1)-1]!='/' ) Strcat( Path1,"/",200 );
Strcat( Path1,"dicts",200 );
// ---------------- прочитать словари источника --------------------
t_Lang &From=Grammar.from();
N=From.File.j ;
SlowoF =(t_Slowo2 *)Calloc( N,sizeof(t_Slowo2) );
i_FormatF=(short *)Calloc( From.Part.j,sizeof(t_Slowo2) );
for( i=0 ; i<From.Part.j ; i++ )
i_FormatF[i]=-1 ;
for( i=0 ; i<N ; i++ )
{ F=&From.File[i] ;
SlowoF[i].read( filename( Path1,F->FileName[0] ), &From, &From.Format[F->i_format] );
SlowoF[i].freverce();
i_FormatF[F->i_part]=i ;
}
// ---------------- прочитать словари приемника --------------------
t_Lang &To=Grammar.to();
N=To.File.j ;
SlowoT =(t_Slowo2 *)Calloc( N,sizeof(t_Slowo2) );
i_FormatT=(short *)Calloc( To.Part.j,sizeof(t_Slowo2) );
for( i=0 ; i<To.Part.j ; i++ )
i_FormatT[i]=-1 ;
for( i=0 ; i<N ; i++ )
{ F=&To.File[i] ;
SlowoT[i].read( filename( Path1,F->FileName[0]), &To, &To.Format[F->i_format] );
SlowoT[i].freverce();
i_FormatT[F->i_part]=i ;
}
// -------------- прочитать словари перевода ---------------
Perevod.read( filename( Path1,"" ), &Grammar );
/*
strcpy( Filename,Dir ); strcat( Filename,"../dicts/base_enru.bin" );
r=Perevod.read_bin( Filename );
if( r<0 )
{ Perevod.read( &Grammar );
Perevod.write_bin( Filename );
}
*/
Fclose( File_Error );
if( Read_Error==0 )
{ unlink("mercury.err") ; f_data_read=1 ; }
return Read_Error ; // если тут 0, то все в порядке
}
catch( int E )
{
Read_Error=-1 ;
Fclose( File_Error );
return -1 ;
}
}
/***************************************************************************/
// перепрочесть все данные
/***************************************************************************/
char reread_grammar( char *Dir )
{ char r ;
char *Path="..";
char Str[300] ;
if( Dir[0]!=0 ) Path=Dir ;
# ifndef __WIN__
sprintf( Str,"g++ -E -o %s/grammar/lang.txt -I%s/grammar %s/grammar/lang.cpp",
Path,Path,Path );
system( Str );
# endif
if( 0==f_data_read )
return read_grammar( Dir );
r=Grammar.make_all( filename( Path,"grammar/lang.txt" ) ) ;
if( r<0 ) return r ;
set_formats( );
return 0 ;
}
/***************************************************************************/
// сделать словарь для констант, встречаемых в lang.txt
/***************************************************************************/
void make_dic_const( void )
{ t_Struct *S ;
long i,i1,L ;
char *Mass,Str[100] ;
for( i=L=0 ; i<Grammar.n_trans() ; i++ )
{ S=&Grammar[i].From ;
for( i1=0 ; i1<S->Word.j ; i1++ )
if( S->Word[i1].type==TCONST )
L+=strlen( S->Word[i1].literal )+10 ;
}
Mass=(char *)Calloc( L+1,sizeof(char) );
for( i=L=0 ; i<Grammar.n_trans() ; i++ )
{ S=&Grammar[i].From ;
for( i1=0 ; i1<S->Word.j ; i1++ )
if( S->Word[i1].type==TCONST )
{ sprintf( Str,"\n@0[%s]=@0[]",S->Word[i1].literal );
strcpy( Mass+L,Str );
L+=strlen( Str );
}
}
DicConst.make( Mass, &(Grammar.format1()[0]) );
Free( Mass );
}
/***************************************************************************/
// проставить словарям ссылки на форматы,
// порушенные при повторном чтении lang.txt
/***************************************************************************/
void set_formats( void )
{ short i ;
t_File *F ;
t_Lang &From = Grammar.from();
t_Lang &To = Grammar.to();
for( i=0 ; i<From.File.j ; i++ )
{ F=&From.File[i] ;
SlowoF[i].set_lf( &From, &From.Format[F->i_format] );
}
for( i=0 ; i<To.File.j ; i++ )
{ F=&To.File[i] ;
SlowoT[i].set_lf( &To, &To.Format[F->i_format] );
}
}
/***************************************************************************/
t_Core :: t_Core( )
{
n_struct =0 ;
n_word =0 ;
Variants =NULL ;
Meaning =(char *)Calloc( l_Meaning=5000,1 );
j_Meaning=0 ;
rWord.init();
Result=E_NULL ;
}
/***************************************************************************/
t_Core :: ~t_Core( )
{ long i,N ;
N=(long)(n_struct)*(long)(n_word+1) ;
for( i=0 ; i<N ; i++ )
Variants[i].Variant.del();
Free( Variants );
Free( Meaning );
rWord.del();
}
/***************************************************************************/
// конструктор
// _n_struct - число шаблонов в t_Grammar
// _n_word - число слов в переводимой фразе
/***************************************************************************/
void t_Core :: init( short _n_struct, short _n_word )
{ long i,i1,N ;
t_Variants *VV ;
N=(long)(n_struct)*(long)(n_word+1) ;
for( i=0 ; i<N ; i++ )
Variants[i].Variant.del();
Free(Variants);
n_struct=_n_struct ;
n_word =_n_word ;
N=(long)(n_struct)*(long)(n_word+1) ;
Variants=(t_Variants *)Calloc( N,sizeof(t_Variants) );
for( i=0 ; i<n_struct ; i++ )
{ for( i1=0 ; i1<n_word ; i1++ )
{ VV=variants( i1,i );
VV->i_struct=i ;
VV->i_word =i1 ;
}
}
rWord.j=0 ;
}
/***************************************************************************/
// главная программа перевода
// Sou - строка источника
// Dst - строка приемника (должна быть захвачена до вызова)
/***************************************************************************/
void t_Core :: translate( char *_Sou, char *Dst )
{ long i,i_best,nn,r,r1,n_Antwort ;
t_rStruct *pV ;
t_Word Word ;
t_Form Form0 ;
try
{
Result=E_NULL ;
Sou=_Sou ;
if( 0==strncmp(Sou,"\\##",3) )
{ // ----- фраза не нуждается в переводе --------
no_brakets( Sou,Dst );
Strcpy( Antwort.str(),Dst,LFRASA );
Strcpy( Sou1,Dst,LFRASA );
Result=E_NO ;
return ;
}
for( i=0 ; i<LFRASA ; i++ )
Sou0[i]=Sou1[i]=0 ;
Antwort.del();
r =make_from1( Sou );
r1=make_from2( );
if( r!=0 || r1!=0 || From.j==0 ) goto M_Simple ;
universe( 0, i_main_struct );
n_Antwort=Variants[0+i_main_struct].Variant.j ;
if( n_Antwort==0 ) goto M_Simple ;
// -------- определить есть ли "полные" варианты ---------
for( f_Full=0,i=0 ; i<n_Antwort ; i++ )
{ pV=variant( 0,i_main_struct,i );
if( pV->i_last_word==From.j ) { f_Full=1 ; break ; }
}
// -------- найти лучший вариант -------------------------
for( i_best=nn=i=0 ; i<n_Antwort ; i++ )
{
pV=variant( 0,i_main_struct,i );
if( f_Full==1 && pV->i_last_word<From.j ) continue ;
if( nn<pV->i_last_word ) { nn=pV->i_last_word ; i_best=i ; }
}
Dst[0]=0 ;
Antwort.make( 0, i_main_struct, i_best, Form0 ) ;
Strcpy( Dst,Antwort.str(),LFRASA );
if( f_Full ) Result=E_OK ;
else Result=E_FIG ;
return ;
M_Simple:
strcpy( Antwort.str(),"#фигня# " );
Antwort.translate_simple( 0 );
strcpy( Dst,Antwort.str() );
Result=E_FIGNA ;
}
catch( int E )
{
strcpy( Dst,"!!! ошибка !!!.");
Result=E_ERROR ;
}
}
/************************************************************************/
// вытянуть фразу из фигурных скобочек
// ( надо использовать в make_from1 )
/************************************************************************/
void t_Core :: no_brakets( char *Str, char *Str1 )
{ long i,i1,L ;
L=strlen( Str );
for( i=0 ; i<L ; i++ )
if( Str[i]=='{' ) break ;
strcpy( Str1,Str+i+1 );
for( i1=L-i-1 ; 0<=i1 ; i1-- )
if( Str1[i1]=='}' )
{ Str1[i1]=0 ; break ; }
}
/***************************************************************************/
// разбиение фразы на слова
// Source - переводимая фраза
/***************************************************************************/
char t_Core :: make_from1( char *Source )
{
long i,j,f,L ;
char c,c1 ;
t_Item W ;
e_TagType t ;
char sPart[100],Str[100],stmp[2]=" " ;
From.j=0 ;
L=strlen( Source );
if( LFRASA<L ) return 1 ;
if( 0==strncmp(Source,"\\@@",3) )
no_brakets( Source,Sou1 );
else strcpy( Sou1,Source );
// ------- отделить точку от последнего слова ------------
i=strlen( Sou1 ) ;
Sign='.' ;
for( ; 0<i ; i-- )
{ c=Sou1[i] ;
if( c=='}' || c=='.' || c=='!' || c=='?' ) break ;
}
if( c=='.' || c=='!' || c=='?' )
{ Sign=Sou1[i] ;
i++ ;
Sou1[i+1]=0 ; Sou1[i]=Sou1[i-1] ; Sou1[i-1]=' ' ;
}
// ---- вот тут надо разворачивать сокращения ------
for( i=f=j=0 ; i<L ; i++ )
{
c=Sou1[i] ;
if( 0==strncmp( Sou1+i,"\\@~",3 ) ) f=1 ;
if( 0==strncmp( Sou1+i,"\\@=",3 ) ) f=1 ;
if( 0==strncmp( Sou1+i,"\\#<",3 ) ) f=1 ;
if( 0==strncmp( Sou1+i,"\\#>",3 ) ) f=1 ;
if( 0==strncmp( Sou1+i,"\\#" ,2 ) ) f=1 ;
if( f==1 )
{ stmp[0]=c ;
strcat( Sou0,stmp );
}
else
{ if( c==' ' || c=='\t' || c=='\n' )
{ if( 0<j )
{ Str[j]=0 ; j=0 ;
strcat( Sou0, Macro.translate_word_s( Str,-1 ) );
strcat( Sou0," " );
}
}
else
{ if( j<98 ) Str[j++]=c ; }
}
if( c=='}' )
{ f=0 ;
stmp[0]=' ' ;
strcat( Sou0,stmp );
}
}
Str[j]=0 ;
strcat( Sou0, Macro.translate_word_s( Str,-1 ) );
strcpy( Sou1,Sou0 );
// ------- проверить на корректность тегов ---------
L=strlen( Sou1 );
for( i=f=0 ; i<L ; i++ )
{ c=Sou1[i] ;
f+=(c=='{') ;
f-=(c=='}') ;
if( f==0 && (c=='\t' || c=='\n') )
Sou1[i]=' ' ;
if( f==0 && (c=='.' || c=='!' || c=='?' || c==',' ||
c=='(' || c==')' || c==';' || c==':' ) )
Sou1[i]=' ' ;
}
if( f!=0 ) return 1 ;
// ------ сделать массив From ---------------------
c1=' ' ;
t=P_FRASA ;
for( i=0 ; i<L ; i++ )
{
f=0 ;
if( 0==strncmp( Sou1+i,"\\@~",3 ) ){ f=1 ; t=P_STRUCT ; }
if( 0==strncmp( Sou1+i,"\\@=",3 ) ){ f=1 ; t=P_CONST ; }
if( 0==strncmp( Sou1+i,"\\#<",3 ) ){ f=1 ; t=P_TAG_LEFT ; }
if( 0==strncmp( Sou1+i,"\\#>",3 ) ){ f=1 ; t=P_TAG_RIGHT ; }
if( f==1 )
{ Sou1[i]=0 ;
i+=2 ;
if( t==P_STRUCT || t==P_CONST )
{ make_token( Sou1+i+1,sPart );
W.i_struct=Grammar.find_struct( FROM,sPart );
}
continue ;
}
c=Sou1[i] ;
W.type=t ;
if( t==P_FRASA )
{ if( c1==' ' && c!=' ' )
{ W.Str=Sou0+i ; W.Str1=Sou1+i ; W.z_str=i ; From.add( W ); }
}
if( t==P_CONST || t==P_STRUCT )
{ if( c=='{' )
{ W.Str=Sou0+i+1 ; W.Str1=Sou1+i+1 ; W.z_str=i+1 ; From.add( W ); }
}
if( t==P_VERB )
{ if( c=='{' )
{ W.Str=Sou0+i+1 ; W.Str1=Sou1+i+1 ; W.z_str=i+1 ; From.add( W ); }
}
if( t==P_TAG_LEFT || t==P_TAG_RIGHT )
{ if( c=='{' )
{ W.Str=Sou0+i+1 ; W.Str1=Sou1+i+1 ; W.z_str=i+1 ;
if( t==P_TAG_LEFT )
W.i_word = From.j ;
else W.i_word = From.j-1 ;
Tag.add( W );
}
}
if( c==' ' && t==P_FRASA ) Sou0[i]=0 ;
if( c=='}' )
{ t=P_FRASA ; Sou0[i]=Sou1[i]=0 ; W.i_struct=-1 ; }
c1=c ;
}
return 0 ;
}
/************************************************************************/
// заполнене главной таблицы атомарными элементами
/************************************************************************/
char t_Core :: make_from2( void )
{
long i,i1,i2,i3,i4,i_word,N,N1 ;
short i_part ;
char *Str,*Str1 ;
t_Lexer Lexer ;
long Ant1[20] ;
short part[20] ;
t_Form Form[20] ;
t_longList Ant2 ;
t_Variants *VV=NULL ;
init( Grammar.n_trans(), From.j );
// ----- определить для каждого слова какой частью речи, оно может быть -----
for( i_word=0 ; i_word<From.j ; i_word++ )
{
e_TagType t=From[i_word].type ;
if( t==P_STRUCT || t==P_CONST || t==P_VERB )
{ // ------- спец слова ----------------------------
short i_struct=From[i_word].i_struct ;
t_Struct *SS=&Grammar[i_struct].From ;
if( SS->type==TENUM )
{ for( i=0 ; i<SS->Word.j ; i++ )
add_from( i_word, SS->Word[i].i_struct, t_Form(), -1, -1 );
}
else
add_from( i_word, i_struct, t_Form(), -1, -1 );
From[i_word].exist=1 ;
continue ;
}
Str=From[i_word].Str ;
if( is_number(Str) )
{ // -------- проверить, что это числительное -------
add_from( i_word, Grammar.i_number(), t_Form(), -1, -1 );
continue ;
}
// ----------- найти в словарях форм -----------------
for( i1=0 ; i1<Grammar.from().File.j ; i1++ )
{ i_part=SlowoF[i1].Format->i_part ;
N=SlowoF[i1].quest( Str, Ant1, Form );
for( i2=0 ; i2<N ; i2++ )
{
Str1=SlowoF[i1].normal( Ant1[i2] );
Perevod.find( Str1,i_part,&Ant2 );
if( Ant2.j<=0 ) continue ;
for( i3=0 ; i3<Ant2.j ; i3++ )
{ t_Form FormPP=Perevod.word_param( Ant2[i3],-1,0 );
t_Param1List *Param =&Grammar[i_part].From.Param ;
for( i4=0 ; i4<Param->j ; i4++ )
if( Param->list[i4].Dir==0 )
FormPP.value[i4]=Form[i2].value[i4] ;
N1=Perevod.get_n_perevod( Ant2[i3] );
add_from( i_word, i_part, FormPP, Ant2[i3], N1 );
}
From[i_word].exist=1 ;
}
}
// ---------- найти в главном словаре -----------------
N=Perevod.part( Str, part );
for( i2=0 ; i2<N ; i2++ )
{ t_Form FormPP ;
Perevod.find( Str, part[i2], &Ant2 );
if( Ant2.j<=0 ) continue ;
for( i3=0 ; i3<Ant2.j ; i3++ )
{
VV=variants( i_word,part[i2] );
for( i4=0 ; i4<VV->Variant.j ; i4++ )
if( Ant2[i3]==VV->Variant[i4].i_slowo ) goto Now_Exist ;
FormPP =Perevod.word_param( Ant2[i3],-1,0 ) ;
N1=Perevod.get_n_perevod( Ant2[i3] );
add_from( i_word, part[i2], FormPP, Ant2[i3], N1 );
Now_Exist :
From[i_word].exist=1 ;
}
}
// ---------- найти в словаре constant -----------------
DicConst.find( Str, -1, &Ant2 );
if( 0<Ant2.j )
From[i_word].exist=1 ;
}
// ------ проверить на дикое количество неизвестных слов -----
for( i=N=0 ; i<From.j ; i++ )
if( From[i].exist==0 ) N++ ;
if( 6<N || From.j/2<N )
return 1 ;
return 0 ;
}
/**************************************************************************/
// добавить вариант трансляции слова
// i_word - индекс слова в фразе
// i_struct - часть речи
// Form - форма и грамматические параметры слова
// i_slowo - индекс слова в словаре переводов
// i_slowo1 - номер перевода
/**************************************************************************/
void t_Core :: add_from( short i_word, long i_struct, t_Form Form,
long i_slowo, short n_slowo )
{ t_Variants *VV ;
t_rStruct S ;
t_rWord W ;
VV=variants( i_word, i_struct ) ;
S.type = Grammar[i_struct].From.type ;
S.i_word = i_word ;
S.i_last_word = i_word+1 ;
S.i_struct = i_struct ;
S.r_word = rWord.j ;
S.Form = Form ;
S.i_slowo = i_slowo ;
S.i_slowo1 = 0 ;
S.i_meaning = -1 ;
VV->Variant.add(S);
W.type = Grammar[i_struct].From.type ;
W.i_struct = i_struct ;
W.i_variant = VV->Variant.j-1 ;
W.i_word = i_word ;
W.i_last_word = i_word+1 ;
W.index = 0 ;
W.i_slowo = i_slowo ;
W.i_slowo1 = 0 ;
W.n_slowo = n_slowo ;
rWord.add( W );
if( 0<=i_slowo )
set_meaning( &VV->Variant[VV->Variant.j-1], Perevod.word_src1(i_slowo) );
}
/**************************************************************************/
// разбиение фразы на составные части (рекурсивная) //
/**************************************************************************/
void t_Core :: universe( short i_word, long i_struct )
{
t_Variants *VV0,*VV1 ;
t_rStruct V1,*pV ;
t_Tree N,*pN1 ;
t_rWord R,*pR ;
t_Struct *SS ;
t_Word *W ;
e_Type t ;
long i,i1,z,i1_struct ;
char q ;
SS=&Grammar[i_struct].From ;
if( n_word<i_word ) return ;
VV0=variants( i_word,i_struct ) ;
if( VV0->absend==1 ) return ; // если такую структуру нельзя построить
if( 0<VV0->Variant.j ) return ; // если уже построена
if( SS->type==TSTRUCT1 || SS->type==TSTRUCT2 ||
SS->type==TUNORDER1 || SS->type==TUNORDER2 )
{ // ---- структура из словаря -----
Perevod.s_universe( i_word, i_struct );
return ;
}
if( SS->type==TSTRUCT || SS->type==TUNORDER )
{ t_TreeList Node ;
make_node( Node, i_word, i_struct );
// ---- собирание вариантов ----------------
for( i=0 ; i<Node.j ; i++ )
{ if( Node[i].down!=(-10) ) continue ;
V1.i_word =i_word ;
V1.i_last_word=Node[i].i_last_word ;
V1.i_struct =i_struct ;
V1.r_word =rWord.j ;
V1.i_slowo =-1 ;
VV0->Variant.add(V1);
for( i1=0 ; i1<SS->Word.j ; i1++ )
rWord.add(R);
z=i ;
for( i1=SS->Word.j-1 ; 0<=i1 ; i1-- )
{ pN1=&Node[z] ;
pR =&rWord[V1.r_word+pN1->index] ;
pR->type =pN1->type ;
pR->i_word =pN1->i_word ;
pR->i_last_word=pN1->i_last_word ;
pR->i_struct =pN1->i_struct ;
pR->i_variant =pN1->i_variant ;
pR->index =pN1->index ;
pR->i_slowo =pN1->i_slowo ;
pR->i_slowo1 =pN1->i_slowo1 ;
pR->n_slowo =pN1->n_slowo ;
z=Node[z].up ;
}
// ------ сформировать meaning ----------
{
char Str[200]="" ;
for( i1=0 ; i1<SS->Word.j ; i1++ )
{ if( 0!=SS->Word[i1].meaning_use )
{ if( Str[0]!=0 ) strcat( Str," " );
strcat( Str,get_meaning( variant(rWord[V1.r_word+i1]) ) );
}
}
set_meaning( &VV0->Variant[VV0->Variant.j-1], Str );
}
real_param_up( &VV0->Variant[VV0->Variant.j-1] );
}
if( VV0->Variant.j==0 ) VV0->absend=1 ;
}
if( IF_SELECT( SS->type ) )
{
for( i=0 ; i<SS->Word.j ; i++ )
{ // ------- цикл по составляющим выбора ---------
t =SS->Word[i].type ;
i1_struct=SS->Word[i].i_struct ;
if( t==TCONST || t==TWORD0 )
{ if( -1==(q=atom( i_word,SS->Word[i] )) ) continue ;
if( SS->type==TSELECT2 &&
1==select2_exist( i_word, i_struct, i_word+q ) ) continue ;
V1.i_word = i_word ;
V1.i_last_word= i_word+q ;
V1.i_struct = i_struct ;
V1.r_word = rWord.j ;
VV0->Variant.add(V1);
R.i_struct = i1_struct ;
R.i_variant = VV0->Variant.j-1 ;
R.i_word = i_word ;
R.i_last_word = i_word+q ;
R.index = i ;
rWord.add( R );
continue ;
}
if( t==TWORD || t==TCONST1 )
{ if( -1==atom( i_word,SS->Word[i] ) ) continue ; }
else
{ universe( i_word, i1_struct ); }
VV1=variants( i_word,i1_struct ) ;
for( i1=0 ; i1<VV1->Variant.j ; i1++ )
{ // ---- цикл по вариантам каждой составляющей -----
W =&SS->Word[i] ;
pV=&VV1->Variant[i1] ;
if( 0!=compare_param( &W->Param, &pV->Form ) ) continue ;
if( SS->type==TSELECT2 &&
1==select2_exist( i_word, i_struct, VV1->Variant[i1].i_last_word ) )
continue ;
V1 =VV1->Variant[i1] ;
V1.i_struct =i_struct ;
V1.r_word =rWord.j ;
V1.i_meaning =-1 ;
VV0->Variant.add(V1);
R.type =VV1->Variant[i1].type ;
R.i_struct =SS->Word[i].i_struct ;
R.i_variant =i1 ;
R.i_word =V1.i_word ;
R.i_last_word=V1.i_last_word ;
R.index =i ;
R.i_slowo =V1.i_slowo ;
R.i_slowo1 =V1.i_slowo1 ;
rWord.add( R );
if( 0!=SS->Word[i].meaning_use )
{ char *Str ;
Str=get_meaning( variant(rWord[V1.r_word]) );
// Free memory reading !!!
set_meaning( &VV0->Variant[VV0->Variant.j-1], Str );
}
real_param_up( &VV0->Variant[VV0->Variant.j-1] );
}
}
// ---- исключение "просто слов" если у нас есть "устойчивое выражение"
/* не всегда так можно безнаказанно делать,
иногда теряются нужные варианты
char f=0 ;
long j,n_word ;
for( i=0 ; i<VV0->Variant.j ; i++ )
{ t=rWord[VV0->Variant[i].r_word].type ;
n_word=VV0->Variant[i].i_last_word-VV0->Variant[i].i_word ;
if( (t==TSTRUCT1 || t==TSTRUCT2 || t==TSELECT1) && 1<n_word )
{ f=1 ; break ; }
}
if( f==1 )
{ for( i=j=0 ; i<VV0->Variant.j ; i++ )
{ t=rWord[VV0->Variant[i].r_word].type ;
n_word=VV0->Variant[i].i_last_word-VV0->Variant[i].i_word ;
if( (t==TSTRUCT1 || t==TSTRUCT2 || t==TSELECT1) && 1<n_word )
{ VV0->Variant[j++]=VV0->Variant[i] ; }
}
VV0->Variant.j=j ;
}
*/
if( VV0->Variant.j==0 ) VV0->absend=1 ;
}
}
/***************************************************************************/
// построение дерева вариантов
// Node - дерево вариантов перевода фразы
// Node[i].select используется как счетчик уровня вершины
/***************************************************************************/
void t_Core :: make_node( t_TreeList &Node, short i_word, long i_struct )
{
t_Variants *VV1 ;
t_rStruct *pV ;
t_Tree N,*pN ;
t_Struct *SS ;
t_Word *W ;
e_Type t ;
char *use=NULL ;
long i,i1,i2,z,index,i1_word,i1_struct ;
SS=&Grammar[i_struct].From ;
Node.j=0 ;
N.i_struct =i_struct ;
N.i_last_word=i_word ;
N.select =0 ;
Node.add(N);
if( SS->type==TUNORDER )
use=(char *)Calloc( SS->Word.j, sizeof(char) );
for( i=0 ; i<Node.j ; i++ )
{
if( 256000<Node.j )
{ print_tree( Node, "NodeError.txt" );
throw(-1);
}
pN=&Node[i] ;
if( pN->select==SS->Word.j )
{ pN->down=-10 ; continue ; }
i1_word=pN->i_last_word ;
if( n_word<i1_word ) continue ;
if( SS->type==TUNORDER )
{ // ----------- заполнить used -----------------
for( i2=0 ; i2<SS->Word.j ; i2++ )
use[i2]=0 ;
z=i ;
while( z!=0 )
{ use[Node[z].index]=1 ;
z=Node[z].up ;
}
}
for( i2=0 ; i2<SS->Word.j ; i2++ )
{
if( SS->type==TSTRUCT && i2!=pN->index+1 ) continue ;
if( SS->type==TUNORDER && use[i2]!=0 ) continue ;
index=i2 ;
// ----------- основной цикл -----------------
t=SS->Word[index].type ;
i1_struct=SS->Word[index].i_struct ;
N.type = t ;
N.up = i ;
N.i_word = i1_word ;
N.index = index ;
N.i_struct = i1_struct ;
N.select = pN->select+1 ;
if( t==TWORD0 )
{ N.i_variant = 0 ;
N.i_last_word= i1_word ;
Node.add(N);
break ;
}
if( t==TCONST || t==TCONST1 )
{ if( -1==atom( i1_word,SS->Word[index] ) ) continue ;
N.i_variant = 0 ;
N.i_last_word= i1_word+1 ;
Node.add(N);
break ;
}
if( t==TWORD )
{ if( -1==atom( i1_word,SS->Word[index] ) ) continue ; }
else
{ universe( i1_word, i1_struct ); }
VV1=variants( i1_word,i1_struct ) ;
for( i1=0 ; i1<VV1->Variant.j ; i1++ )
{ W =&SS->Word[index] ;
pV=&VV1->Variant[i1] ;
if( 0!=compare_param( &W->Param, &pV->Form ) )
continue ;
if( W->literal[0]!=0 ) // сравнить литералы
{ char *Str=Core.get_meaning( pV ) ;
if( 0!=Strcmp( W->literal,Str) )
continue ;
}
N.type = Grammar[N.i_struct].From.type ;
N.i_variant = i1 ;
N.i_last_word= pV->i_last_word ;
N.i_slowo = pV->i_slowo ;
N.i_slowo1 = pV->i_slowo1 ;
Node.add(N);
}
}
}
Free(use);
}
/***************************************************************************/
// попробовать подходит ли атомарный элемент фразы
// return -1 - не подходит, 0 - пустой выбор, 1 - подходит
/***************************************************************************/
char t_Core :: atom( short i_word, t_Word &Word )
{
// ---------------- если это пустой выбор --------
if( Word.type==TWORD0 )
return 0 ;
if( From.j<=i_word ) return -1 ;
if( Word.type==TCONST )
{ // ---------------- если это константное слово ----------
if( 0==Strcmp( From[i_word].Str,Word.literal ) )
return 1 ;
return -1 ;
}
if( Word.type==TWORD )
{ // ---------------- если это слово ----------
t_Variants *VV=variants( i_word,Word.i_struct ) ;
if( VV->absend==1 ) return -1 ;
if( 0<VV->Variant.j ) return 1 ;
if( From[i_word].exist==0 )
{ // ----слово отсутствует в словаре - сделать вид, что оно подходит --
add_from( i_word, Word.i_struct, t_Form(), -1, -1 );
return 1 ;
}
if( Word.literal[0]!=0 )
{ // ---- если это литерал, найти начальную форму слова и
// ---- проверить на совпадение----
char Str1[100] ;
word_source( Word.i_struct, From[i_word].Str, Str1, FROM );
if( 0==Strcmp(Str1,Word.literal ) )
return 1 ;
else return -1 ;
}
}
return -1 ;
}
/***************************************************************************/
// сравнить требуемые параметры слова с фактическими
/***************************************************************************/
char t_Core :: Compare_Param( t_rStruct *V, t_Word *Word )
{
if( Word->type==TWORD &&
0!=compare_param( &Word->Param, &V->Form ) )
return 1 ;
return 0 ;
}
/***************************************************************************/
char t_Core :: select2_exist( short i_word, short i_struct, short i_last_word )
{ long i ;
t_Variants *VV=variants( i_word,i_struct ) ;
for( i=0 ; i<VV->Variant.j ; i++ )
if( VV->Variant[i].i_last_word==i_last_word ) return 1 ;
return 0 ;
}
/***************************************************************************/
// передать параметры вверх на один шаг при построении universe
// V - конструкция, для которой определяются параметры на основе ее сыновей
/***************************************************************************/
void t_Core :: real_param_up( t_rStruct *V )
{
long i,ii ;
t_rStruct *V1,*V2 ;
t_Struct *SS ;
t_RelationList1 RR ;
t_Relation R ;
if( V->i_struct<0 ) return ;
SS=&Grammar[V->i_struct].From ;
if( SS->type==TWORD0 || SS->type==TCONST ) return ;
if( SS->type==TSTRUCT2 )
RR=Perevod.get_relation( V->i_slowo, -1 );
else RR=Grammar[V->i_struct].From.Relation ;
if( IF_STRUCT( SS->type ) )
{ for( i=0 ; i<RR.j ; i++ )
{ R=RR.list[i] ;
if( R.s1==0 ) V1= V ;
else V1=variant( rWord[V->r_word+R.s1-1] ) ;
if( R.s2==0 ) V2= V ;
else V2=variant( rWord[V->r_word+R.s2-1] ) ;
V2->Form.value[R.p2] = V1->Form.value[R.p1] ;
}
}
if( IF_SELECT( SS->type ) )
{
ii=rWord[V->r_word].index+1 ;
for( i=0 ; i<RR.j ; i++ )
{ R=RR.list[i] ;
if( R.s1!=ii ) continue ;
if( R.s1==0 ) V1=V ;
else V1=variant( rWord[V->r_word] ) ;
if( R.s2==0 ) V2=V ;
else V2=variant( rWord[V->r_word] ) ;
V2->Form.value[R.p2] = V1->Form.value[R.p1] ;
}
}
}
/**************************************************************************/
// первая попавшаяся часть речи, которой может быть это слово
/**************************************************************************/
long t_Core :: struct_of_word( short i_word )
{ long i ;
e_Type t ;
t_Variants *VV ;
for( i=0 ; i<Core.n_struct ; i++ )
{ t=Grammar[i].From.type ;
if( t!=TWORD && t!=TSTRUCT1 && t!=TSTRUCT2 ) continue ;
VV=Core.variants( i_word, i );
if( 0<VV->Variant.j ) return i ;
}
return -1 ;
}
/***************************************************************************/
// дать варианты перевода слова i_word как структуры i_struct
/***************************************************************************/
t_Variants * t_Core :: variants( short i_word, long i_struct )
{
if( i_word<0 || n_word<i_word || i_struct<0 )
{ printf("\n t_Core :: Variants := Error index !!!"); exit(-1) ; }
return &Variants[ n_struct*i_word+i_struct ] ;
}
/***************************************************************************/
// дать один вариант перевода
/***************************************************************************/
t_rStruct * t_Core :: variant( short i_word, long i_struct, long i_variant )
{
if( i_word<0 || n_word<i_word || i_struct<0 )
{ printf("\n t_Core :: variant := Error index !!!"); exit(-1) ; }
if( Variants[ n_struct*i_word+i_struct ].Variant.j<=i_variant )
{ printf("\n t_Core :: variant := Error i_variant !!!"); exit(-1) ; }
return &Variants[ n_struct*i_word+i_struct ].Variant[i_variant] ;
}
/***************************************************************************/
// дать один вариант перевода
/***************************************************************************/
t_rStruct * t_Core :: variant( t_rWord R )
{
if( R.i_word<0 || n_word<R.i_word || R.i_struct<0 )
{ printf("\n t_Core :: variant := Error index !!!"); exit(-1) ; }
if( Variants[ n_struct*R.i_word+R.i_struct ].Variant.j<=R.i_variant )
{ printf("\n t_Core :: variant := Error i_variant !!!"); exit(-1) ; }
return &Variants[ n_struct*R.i_word+R.i_struct ].Variant[R.i_variant] ;
}
/***************************************************************************/
// установить смысл варианту перевода
/***************************************************************************/
void t_Core :: set_meaning( t_rStruct *V, char *Str )
{ long L,LL ;
if( 0<=V->i_meaning )
{ printf("\n t_Core :: meaning != NULL !!!"); exit(-1) ; }
L=strlen(Str);
if( L==0 ) return ;
if( l_Meaning<=j_Meaning+L+1 )
{ LL=l_Meaning+max(l_Meaning>>2,L+1) ;
Meaning=(char *)Realloc( Meaning,LL );
l_Meaning=LL ;
}
V->i_meaning=j_Meaning ;
strcpy( Meaning+j_Meaning, Str );
j_Meaning+=L+1 ;
}
/***************************************************************************/
// прочесть смысл варианта перевода
/***************************************************************************/
char
* t_Core :: get_meaning( t_rStruct *V )
{ static char *s="" ;
static char s1[1000] ;
if( V->i_meaning<0 ) return s ;
Strcpy( s1,Meaning+V->i_meaning,1000 );
return s1 ;
}
/***************************************************************************/
t_Antwort & t_Core :: antwort( )
{
return Antwort ;
}
/***************************************************************************/
long t_Core :: n_antwort( void )
{
return Variants[0+i_main_struct].Variant.j ;
}
/***************************************************************************/
char t_Core :: sign( void )
{
return Sign ;
}
/***************************************************************************/
char t_Core :: f_full( void )
{
return f_Full ;
}
/***************************************************************************/
t_ItemList & t_Core :: from( void )
{
return From ;
}
/***************************************************************************/
t_ItemList & t_Core :: tag( void )
{
return Tag ;
}
/***************************************************************************/
t_rWord & t_Core :: rword( long i )
{
return rWord[i] ;
}
/***************************************************************************/
short t_Core :: fn_word( void )
{
return n_word ;
}
/***************************************************************************/
e_Result t_Core :: result( void )
{
return Result ;
}
/***************************************************************************/
char
* t_Core :: sou( void )
{
return Sou ;
}
/***************************************************************************/
// сделать вариант ответа
// i - индекс варианта ответа
/***************************************************************************/
void t_Antwort :: make( short i_word, short i_struct, long i_variant, t_Form Form )
{
short L ;
t_rStruct *pV ;
Str[0]=0 ;
Tree1.j=Tree2.j=aWord.j=0 ;
pV=Core.variant( i_word ,i_struct, i_variant );
make_sou( i_word, i_struct, i_variant );
make_dst();
make_to( 0 );
if( 0<Tree2.j ) Tree2[0].Form=Form ;
param_from();
param_transmit();
param_to( );
if( pV->i_last_word < Core.from().j )
strcpy( Str,"#фиг# " );
insert_tag();
print_antwort( 0,1 );
post_proc( );
if( i_struct==i_main_struct && pV->i_last_word < Core.from().j )
{ strcat( Str,"## " );
translate_simple( pV->i_last_word );
}
L=strlen(Str);
if( 0<L ) Str[L-1]=Core.sign() ;
else { Str[0]=Core.sign() ; Str[1]=0 ; }
}
/***************************************************************************/
// построение дерева разбора (Tree1)
// i_Variant - индекс варианта ответа
/***************************************************************************/
void t_Antwort :: make_sou( short i_word, short i_struct, long i_variant )
{
long i,i1 ;
e_Type t ;
t_Tree T,*pT ;
t_Struct *SS ;
t_rStruct *pS ;
t_sStruct *sS ;
t_rWord W ;
pS = Core.variant( i_word, i_struct, i_variant ) ;
W = Core.rword( pS->r_word ) ;
// -------- внести в дерево первый элемент ---------------
T.type = Grammar[i_struct].From.type ;
T.i_word = i_word ;
T.i_last_word = Core.from().j ;
T.i_struct = i_struct ;
T.i_variant = i_variant ;
T.select = W.index ;
T.i_slowo = W.i_slowo ;
Tree1.j=0 ;
Tree1.add(T);
// -------- внести все последующие -----------------------
for( i=0 ; i<Tree1.j ; i++ )
{
pT=&Tree1[i] ;
pT->down=Tree1.j ;
t=pT->type ;
if( t==TWORD || t==TCONST || t==TCONST1 || t==TWORD0 )
continue ;
pS=Core.variant( pT->i_word, pT->i_struct, pT->i_variant ) ;
SS=&Grammar[pT->i_struct].From ;
if( IF_STRUCT( t ) || t==TUNORDER || t==TUNORDER1 )
{
if( t==TSTRUCT || t==TSTRUCT1 || t==TUNORDER || t==TUNORDER1 )
{ // ------ нормальная структура ---------
pT->i_slowo = pS->i_slowo ;
Tree1[i].n_down =SS->Word.j ;
for( i1=0 ; i1<SS->Word.j ; i1++ )
{
set_tree( &T, pS, i1 );
T.up = i ;
Tree1.add(T);
}
}
if( t==TSTRUCT2 )
{ // ------ структура из словаря ------
sS=Perevod.get_from( pS->i_slowo );
pT->i_slowo = pS->i_slowo ;
pT->n_down = sS->n_Word ;
for( i1=0 ; i1<sS->n_Word ; i1++ )
{ set_tree( &T, pS, i1 );
T.up = i ;
Tree1.add(T);
}
}
}
if( IF_SELECT( t ) )
{
Tree1[i].n_down = 1 ;
set_tree( &T, pS, 0 );
T.up = i ;
Tree1[i].select =Core.rword( pS->r_word ).index ;
Tree1.add(T);
}
}
}
/**************************************************************************/
// присвоить должные значения полям t_Tree, нужные для make_sou()
// T - элемент дерева, который присваивается
// pS - структура, которая соответствует элементу Tree1[T->up]
// i - номер каким сыном является T по отношению к Tree1[T->up]
/**************************************************************************/
void t_Antwort :: set_tree( t_Tree *T, t_rStruct *pS, long i )
{ t_rWord W = Core.rword( pS->r_word+i ) ;
t_Struct *SS = &Grammar[pS->i_struct].From ;
if( SS->type==TSTRUCT || SS->type==TSTRUCT1 )
T->type = SS->Word[i].type ;
if( SS->type==TUNORDER || SS->type==TUNORDER1 )
T->type = W.type ;
if( SS->type==TSELECT || SS->type==TSELECT1 || SS->type==TSELECT2 )
T->type = SS->Word[W.index].type ;
if( SS->type==TSTRUCT2 )
T->type = W.type ;
if( SS->type==TWORD )
{ printf("\n Error"); throw(-1); }
T->down =-1 ;
T->n_down = 0 ;
T->i_word = W.i_word ;
T->i_last_word = W.i_last_word ;
T->i_struct = W.i_struct ;
T->i_variant = W.i_variant ;
T->Form = pS->Form ;
T->link =-1 ;
T->select =-1 ;
T->i_slowo = W.i_slowo ;
T->i_slowo1 = W.i_slowo1 ;
T->n_slowo = W.n_slowo ;
}
/**************************************************************************/
// Построение дерева приемников по дереву источников //
/**************************************************************************/
void t_Antwort :: make_dst( void )
{ long i,i1,i2,is ;
t_Trans *Tr ;
t_Tree TT,*T2 ;
t_sStruct *S1,*S2 ;
e_Type t ;
Tree2.j=0 ;
TT.i_struct=is=Tree1[0].i_struct ;
if( 0<=is && (Grammar[is].From.type==TSTRUCT1 || Grammar[is].From.type==TSTRUCT2 ) )
{ S2=Perevod.get_to( Tree1[0].i_slowo,Tree1[0].i_slowo1 );
TT.i_struct=S2->i_struct ;
}
TT.up=-1 ;
TT.type=Tree1[0].type ;
TT.down=1 ;
TT.n_down=0 ;
TT.select=0 ;
TT.i_word=0 ;
TT.link =0 ;
TT.Form.init();
Tree2.add( TT );
Tree1[0].link=0 ;
for( i=0 ; i<Tree2.j ; i++ )
{ T2=&Tree2[i] ;
t=T2->type ;
if( t==TWORD0 || t==TWORD || t==TCONST || t==TCONST1 )
continue ;
Tr=&Grammar[ T2->i_struct ] ;
T2->down =Tree2.j ;
if( t==TSTRUCT2 || t==TSTRUCT1 )
{ i2=Tree1[T2->link].i_slowo ;
S1=Perevod.get_from( i2 );
S2=Perevod.get_to( i2,Tree1[T2->link].i_slowo1 );
T2->n_down =S2->n_Word ;
T2->i_slowo =i2 ;
T2->i_slowo1 =Tree1[T2->link].i_slowo1 ;
T2->i_variant=Tree1[T2->link].i_variant ;
for( i2=0 ; i2<S2->n_Word ; i2++ )
make_dst2( i, i2, S1, S2 );
}
if( t==TSTRUCT || t==TUNORDER )
{ T2->n_down =Tr->To.Word.j ;
if( 0<=T2->link )
{ T2->i_slowo =Tree1[T2->link].i_slowo ;
T2->i_slowo1 =Tree1[T2->link].i_slowo1 ;
T2->i_variant=Tree1[T2->link].i_variant ;
}
for( i2=0 ; i2<Tr->To.Word.j ; i2++ )
make_dst1( i, i2, Tr );
}
if( t==TSELECT || t==TSELECT2 )
{ T2->n_down =1 ;
if( 0<=T2->link )
{ T2->i_slowo =Tree1[T2->link].i_slowo ;
T2->i_slowo1 =Tree1[T2->link].i_slowo1 ;
T2->i_variant=Tree1[T2->link].i_variant ;
}
make_dst1( i, Tree1[T2->link].select, Tr );
}
if( t==TSELECT1 )
{ i1=T2->i_struct ;
i2=Tree1[T2->link].i_slowo ;
T2->n_down =1 ;
T2->i_slowo =i2 ;
T2->i_slowo1 =Tree1[T2->link].i_slowo1 ;
T2->i_variant=Tree1[T2->link].i_variant ;
T2->select=find_enum_select( TO, i1, i2 );
make_dst1( i, T2->select, Tr );
}
}
}
/**************************************************************************/
// добавление одного элемента в дерево приемников
// up - индекс родителя, к которому добавляется новый потомок
// Tr - шаблон, соответствующий Tree2[up]
// i2 - индекс слова в структуре-приемнике
/**************************************************************************/
void t_Antwort :: make_dst1( long up, long i2, t_Trans *Tr )
{
t_Tree TT,*pT ;
t_Struct *S2 ;
t_sStruct *sS ;
long i_link,i3 ;
e_Type type ;
S2=&Tr->To ;
type=S2->Word[i2].type ;
TT.i_struct=S2->Word[i2].i_struct ;
TT.up=up ;
i_link=Tree2[up].link ;
// ------ проставить i_link --------------
TT.link=-1 ;
if( (Tree2[up].type==TSTRUCT || Tree2[up].type==TUNORDER ) &&
0<=Tr->Relation2[i2] )
TT.link=Tree1[i_link].down+Tr->Relation2[i2] ;
if( Tree2[up].type==TSTRUCT1 )
{ sS=Perevod.get_to( Tree2[up].i_slowo );
//if( sS->Word[i2].str[0]==0 ) // ----- слово не константа
if( 0<=sS->Word[i2].i_struct )
{ pT=&Tree1[Tree2[up].link] ;
for( i3=0 ; i3<pT->n_down ; i3++ )
if( Tree1[pT->down+i3].i_struct==TT.i_struct )
TT.link=pT->down+i3 ;
}
}
if( IF_SELECT( Tree2[up].type ) )
TT.link=Tree1[i_link].down ;
if( 0<=TT.link )
Tree1[TT.link].link=Tree2.j ;
// ------ проставить все остальное ---------------------------
if( type==TCONST || type==TCONST1 || type==TWORD0 )
{ TT.type =type ;
TT.select=0 ;
}
else
{ TT.type =Grammar[TT.i_struct].To.type ;
if( 0<=TT.link )
{
TT.select =Tree1[TT.link].select ;
TT.i_slowo =Tree1[TT.link].i_slowo ;
TT.i_slowo1=Tree1[TT.link].i_slowo1 ;
}
}
TT.down=0 ;
TT.n_down=0 ;
TT.i_word=-1 ;
TT.index=i2 ;
// ------ прописать параметры --------------
for( i3=0 ; i3<S2->Word[i2].Param.j ; i3++ )
TT.Form.value[i3]=S2->Word[i2].Param[i3].value ;
Tree2.add( TT );
}
/**************************************************************************/
// добавление одного элемента в дерево приемников
// если родитель - произвольная структура (TSTRUCT2)
// up - индекс родителя, к которому добавляется новый потомок
// i2 - индекс слова в структуре-приемнике
// S1 - структура в языке оригинала
// S2 - структура в языке перевода
/**************************************************************************/
void t_Antwort :: make_dst2( long up, long i2, t_sStruct *S1, t_sStruct *S2 )
{
t_Tree TT ;
long z,i3 ;
TT.up=up ;
TT.i_struct=S2->Word[i2].i_struct ;
if( TT.i_struct<0 )
{ TT.type=TCONST ;
TT.link=-1 ;
}
else
{ TT.type=Grammar[TT.i_struct].To.type ;
for( i3=0,z=-1 ; i3<S1->n_Word ; i3++ )
if( S1->Word[i3].i_struct==S2->Word[i2].i_struct &&
S1->Word[i3].order ==S2->Word[i2].order ) { z=i3 ; break ; }
if( z<0 ) TT.link=-1 ;
else TT.link= Tree1[Tree2[up].link].down+z ;
}
if( 0<=TT.link )
{ Tree1[TT.link].link=Tree2.j ;
TT.select =Tree1[TT.link].select ;
TT.i_slowo =Tree1[TT.link].i_slowo ;
TT.i_slowo1=Tree1[TT.link].i_slowo1 ;
}
TT.down =0 ;
TT.n_down=0 ;
TT.i_word=-1 ;
TT.index =i2 ;
TT.Form =S2->Word[i2].Param ;
Tree2.add( TT );
}
/***************************************************************************/
// задание строковых значений дереву приемников
/***************************************************************************/
void t_Antwort :: make_to( long i_tree )
{ long i ;
t_Tree *T,*T1 ;
t_Struct *SS ;
t_sStruct *S ;
char *Str2,Str1[100] ;
T=&Tree2[i_tree] ;
if( T->type==TWORD0 )
return ;
if( 0<T->i_struct )
SS=&Grammar[T->i_struct].To ;
if( T->type==TWORD )
{ if( T->link<0 ) return ;
if( T->Str1[0]!=0 ) return ;
T1=&Tree1[T->link] ;
word_source( T1->i_struct, Core.from()[T1->i_word].Str, Str1, FROM );
Str2=Perevod.translate_word_i( Str1, T1->i_slowo, T1->i_slowo1 );
if( Str2!=NULL ) Strcpy( T->Str1, Str2, LWORD );
else Strcpy( T->Str1, Str1, LWORD );
}
if( T->type==TCONST || T->type==TCONST1 )
{ t_Struct *S1=&Grammar[Tree2[T->up].i_struct].To ;
Strcpy( T->Str1, S1->Word[T->index].literal, LWORD );
}
if( IF_SELECT( T->type ) )
{
if( SS->Word[T->select].literal[0]!=0 )
Strcpy( Tree2[T->down].Str1, SS->Word[T->select].literal, LWORD );
if( SS->Word[T->select].meaning_use!=0 && T->Str1[0]!=0 )
Strcpy( Tree2[T->down].Str1, T->Str1, LWORD );
make_to( T->down );
}
if( IF_STRUCT( T->type ) || IF_UNORDER( T->type ) )
{ if( T->type==TSTRUCT || T->type==TUNORDER )
{ for( i=0 ; i<T->n_down ; i++ )
{ T1=&Tree2[T->down+i] ;
if( SS->Word[i].literal[0]!=0 )
Strcpy( T1->Str1, SS->Word[i].literal, LWORD );
if( SS->Word[i].meaning_use!=0 && T->Str1[0]!=0 )
Strcpy( T1->Str1, T->Str1, LWORD );
make_to( T->down+i );
}
}
else
{ // ---- структура из словаря --------
S=Perevod.get_to( T->i_slowo,T->i_slowo1 );
for( i=0 ; i<S->n_Word; i++ )
{ T1=&Tree2[T->down+i] ;
if( T1->type==TWORD )
{ if( S->Word[i].str[0]==0 )
{ make_to( T->down+i ); }
else
{ word_source( S->Word[i].i_struct, S->Word[i].str, Str1, FROM );
Strcpy( T1->Str1, Str1, LWORD );
}
}
if( T1->type==TCONST || T1->type==TCONST1 )
Strcpy( T1->Str1, S->Word[i].str, LWORD );
if( IF_CONSTR( T1->type ) )
{ if( S->Word[i].str[0]!=0 )
Strcpy( T1->Str1, S->Word[i].str, LWORD );
make_to( T->down+i );
}
}
}
}
}
/***************************************************************************/
// Пословный перевод, если разбор не удался
// Begin - на каком слове надорвался штатный алгоритм
/***************************************************************************/
char
* t_Antwort :: translate_simple( short Begin )
{ short i_word,i_slowar,i_struct,N,z_begin ;
t_Slowo2 *Slowo ;
t_Form Form1[20] ;
char *Str0,*Str1 ;
long Ant1[20] ;
t_ItemList &From=Core.from();
i_slowar=i_struct=-1 ;
z_begin=strlen( Str );
if( Begin<0 ) Begin=0 ;
for( i_word=Begin ; i_word<From.j ; i_word++ )
{
if( From[i_word].exist )
{ i_struct=Core.struct_of_word( i_word ) ;
if( 0<=i_struct )
i_slowar=i_FormatF[i_struct] ;
}
if( 0<=i_slowar )
{ Slowo=&SlowoF[ i_slowar ];
N=Slowo->quest( From[i_word].Str, Ant1, Form1 );
}
else N=0 ;
if( 0<N ) Str1=Slowo->normal(Ant1[0]) ;
else Str1=From[i_word].Str ;
Str0=Perevod.translate_word_s( Str1, i_struct );
strcat( Str,Str0 );
strcat( Str," " );
}
strcat( Str,"." );
return Str+z_begin ;
}
/***************************************************************************/
/* вычислить параметры структур на основании сыновей (в источнике) */
/***************************************************************************/
void t_Antwort :: param_from( void )
{
long i,i1 ;
t_Tree *F,*F1,*F2 ;
t_rStruct *V ;
t_RelationList1 RR ;
t_Relation R ;
for( i=Tree1.j-1 ; 0<=i ; i-- )
{ F=&Tree1[i] ;
if( F->type==TWORD0 || F->type==TCONST || F->type==TCONST1 ) continue ;
if( F->type==TSTRUCT2 )
RR=Perevod.get_relation( F->i_slowo, -1 );
else
{
if( F->i_struct<0 || i_main_struct<F->i_struct )
printf("\n ABR !!!");
RR=Grammar[F->i_struct].From.Relation ;
}
if( F->type==TWORD )
{ // -------- по хорошему это надо через Grammar делать ----
V=Core.variant( F->i_word,F->i_struct,F->i_variant );
F->Form=V->Form ;
continue ;
}
for( i1=0 ; i1<RR.j ; i1++ )
{ R=RR.list[i1] ;
if( IF_SELECT( F->type ) && (R.s1-1)!=F->select ) continue ;
F1=part_of_struct( Tree1, i, R.s1 );
F2=part_of_struct( Tree1, i, R.s2 );
F2->Form.value[R.p2] = F1->Form.value[R.p1] ;
}
}
}
/**************************************************************************/
// Передача параметров источник - приемник //
/**************************************************************************/
void t_Antwort :: param_transmit( void )
{ short I,i,i1,i2,i3 ;
t_Tree *Dst,*Sou,*T1 ;
t_Trans *Trans ;
t_Table *TT ;
for( I=0 ; I<Tree2.j ; I++ )
{
Dst=&Tree2[I] ;
if( Dst->link<0 ) continue ;
Sou=&Tree1[Dst->link] ;
if( Dst->type==TCONST || Dst->type==TCONST1 ) continue ;
if( Dst->type==TWORD0 || Sou->type==TWORD0 ) continue ;
Trans=&Grammar[ Dst->i_struct ] ;
for( i=0 ; i<Trans->Table.j ; i++ )
{ TT=&Trans->Table[i] ;
for( i1=0 ; i1<TT->Value.j ; i1+=TT->Size )
{ // --------- цикл по строчкам в таблице --------------
for( i2=0 ; i2<TT->In.j ; i2++ )
{ // ---------- найти строчку, соответствующую вычисленным
// ---------- значениям параметров ------------
i3=TT->In[i2].i1 ;
if( TT->In[i2].i2<0 ) // ------- когда параметр - строка @Выбор'а
{ if( (Sou->select+1)!=TT->Value[i1+i2] ) goto M_Next ;
}
else
{ T1=part_of_struct( Tree1, Dst->link, i3 );
if( T1->Form.value[TT->In[i2].i2]!=TT->Value[i1+i2] &&
0<=TT->Value[i1+i2] ) goto M_Next ;
}
}
for( i2=0 ; i2<TT->Out.j ; i2++ )
{ // ---------- записать параметры в приемник
i3=TT->Out[i2].i1 ;
T1=part_of_struct( Tree2, I, i3 );
T1->Form.value[TT->Out[i2].i2]=TT->Value[i1+TT->In.j+i2] ;
}
M_Next: ;
}
}
}
}
/***************************************************************************/
// Передача параметров в приемнике //
/***************************************************************************/
void t_Antwort :: param_to( void )
{
long i,i1,i2 ;
short v ;
t_Tree *T,*T1,*T2 ;
t_Struct *SS ;
t_sStruct *sS ;
t_RelationList1 RR ;
t_Relation R ;
t_Form Form ;
for( i=Tree2.j-1 ; 0<=i ; i-- )
{ T=&Tree2[i] ;
if( T->type==TSTRUCT1 || T->type==TSTRUCT2 )
T->Form=Perevod.struct_param( T->i_slowo, T->i_slowo1 );
}
for( i=Tree2.j-1 ; 0<=i ; i-- )
{ // ------------- проход снизу вверх ------------------
T=&Tree2[i] ;
if( T->i_struct<0 ) continue ;
SS=&Grammar[T->i_struct].To ;
if( T->type==TSTRUCT2 )
RR=Perevod.get_relation( T->i_slowo, T->i_slowo1 );
else RR=SS->Relation ;
// ------------- вычисление постоянных параметров ----
if( T->type==TWORD )
{
if( 0<=T->link )
{ // ----- up - нормальная структура -------
Form=Perevod.word_param( T->i_slowo, T->i_slowo1 ,0 );
}
else
{ // ----- up - TSTRUCT1 или TSTRUCT2 ------
t_Tree *T_up=&Tree2[T->up] ;
Form=Perevod.word_param( T_up->i_slowo, T_up->i_slowo1 , T->index );
}
for( i1=0 ; i1<SS->Param.j ; i1++ )
if( SS->Param[i1].Dir==1 )
T->Form.value[i1]=Form.value[i1] ;
}
// ------------- передача параметров наверх ----------
for( i1=0 ; i1<RR.j ; i1++ )
{ R=RR.list[i1] ;
if( R.s2!=0 ) continue ;
if( SS->Param[R.p2].Dir!=0 ) continue ; // ---- лишнее условие ?
if( IF_SELECT( T->type ) && (R.s1-1)!=T->select ) continue ;
T1=part_of_struct( Tree2, i, R.s1 );
T2=part_of_struct( Tree2, i, R.s2 );
T2->Form.value[R.p2] = T1->Form.value[R.p1] ;
}
}
for( i=0 ; i<Tree2.j ; i++ )
{ // ------------- проход сверху вниз ----------------
T=&Tree2[i] ;
if( T->i_struct<0 ) continue ;
SS=&Grammar[T->i_struct].To ;
if( T->type==TSTRUCT2 )
RR=Perevod.get_relation( T->i_slowo, T->i_slowo1 );
else RR=SS->Relation ;
for( i1=0 ; i1<RR.j ; i1++ )
{ R=RR.list[i1] ;
if( R.s2==0 ) continue ;
if( R.s1==0 )
{ // ------- передача параметров от вышестоящей структуры -------
if( SS->Param[R.p1].Dir==0 ) continue ;
if( IF_SELECT( T->type ) && (R.s2-1)!=T->select ) continue ;
T2=part_of_struct( Tree2, i, R.s2 );
T2->Form.value[R.p2] = T->Form.value[R.p1] ;
}
else
{ // ------- передача параметров от соседних структур -------
T1=part_of_struct( Tree2, i, R.s1 );
T2=part_of_struct( Tree2, i, R.s2 );
T2->Form.value[R.p2] = T1->Form.value[R.p1] ;
}
}
// -------- задание константных параметров ----------
if( IF_SELECT( T->type ) )
{ // ---------- для выборов ------------
i1=T->select ;
for( i2=0 ; i2<SS->Word[i1].Param.j ; i2++ )
{ v=SS->Word[i1].Param[i2].value ;
if( 0<=v )
{ T2=&Tree2[T->down] ;
T2->Form.value[i2]=v ;
}
}
}
if( T->type==TSTRUCT || T->type==TSTRUCT1 )
{ // --------- и для структур ----------
if( T->type==TSTRUCT1 ) sS=Perevod.get_to( T->i_slowo );
for( i1=0 ; i1<SS->Word.j ; i1++ )
{ for( i2=0 ; i2<SS->Word[i1].Param.j ; i2++ )
{ v=-1 ;
if( T->type==TSTRUCT1 )
{ if( SS->Word[i1].Param[i2].Dir==1 )
v=sS->Word[i1].Param.value[i2] ;
}
else v=SS->Word[i1].Param[i2].value ;
if( 0<=v )
{ T2=&Tree2[T->down+i1] ;
T2->Form.value[i2]=v ;
}
}
}
}
}
}
/***************************************************************************/
// выдать адрес части(слова) структуры
// Tree - дерево
// Tree[i_tree] - та самая структура
// i_word - индекс части (если i_word==0 возвращается
// сама Tree[i_tree])
/***************************************************************************/
t_Tree *part_of_struct( t_TreeList &Tree, long i_tree, short i_word )
{
t_Tree *T=&Tree[i_tree] ;
if( i_word==0 ) return T ;
else
{ if( IF_SELECT( T->type ) )
return &Tree[T->down] ;
else return &Tree[T->down+i_word-1] ;
}
}
/***************************************************************************/
// развешать теги (как сопли) на дерево приемника
/***************************************************************************/
void t_Antwort :: insert_tag()
{ long i,i1,i_word ;
e_TagType t ;
t_Tree *T ;
for( i=0 ; i<Core.tag().j ; i++ )
{ t=Core.tag()[i].type ;
i_word=Core.tag()[i].i_word ;
if( t==P_TAG_LEFT )
{ for( i1=0 ; i<Tree2.j ; i1++ )
{ T=&Tree2[i1] ;
if( IF_WORD(T->type) && 0<=T->link && i_word<=Tree1[T->link].i_word )
{ T->left_tag =i ; break ; }
}
}
if( t==P_TAG_RIGHT )
{ for( i1=Tree2.j-1 ; 0<=i1 ; i1-- )
{ T=&Tree2[i1] ;
if( IF_WORD(T->type) && 0<=T->link && Tree1[T->link].i_word<=i_word )
{ T->right_tag =i ; break ; }
}
}
}
}
/***************************************************************************/
// напечатать ответ (рекурсивная) //
/***************************************************************************/
# define F_LEFT_TAG if( 0<=T->left_tag ) strcat( Str,Core.tag()[T->left_tag].Str );
# define F_RIGHT_TAG if( 0<=T->right_tag ) strcat( Str,Core.tag()[T->right_tag].Str );
void t_Antwort :: print_antwort( long i_tree, char fword )
{ t_Tree *T ;
t_Slowo2 *Slowo ;
short i ;
static short sp=0 ;
sp++ ;
if( 80<sp )
{ printf("\n Стек исчерпался"); exit(-1); }
T=&Tree2[i_tree] ;
if( T->type==TCONST || T->type==TCONST1 )
{
F_LEFT_TAG
strcpy( T->Str,T->Str1 );
Strcat( Str,T->Str,LFRASA ); Strcat( Str," ",LFRASA );
add_word( *T,fword );
F_RIGHT_TAG
}
if( T->type==TWORD )
{
F_LEFT_TAG
if( 0<=i_FormatT[T->i_struct] )
{ Slowo=&SlowoT[ i_FormatT[T->i_struct] ];
Strcpy( T->Str, Slowo->form( T->Str1,&T->Form),LWORD );
}
else
{ strcpy( T->Str, T->Str1 );
}
Strcat( Str,T->Str,LFRASA ); Strcat( Str," ",LFRASA );
add_word( *T,fword );
F_RIGHT_TAG
}
// ---------- заполнить и оттранслировать сыновей --------
if( IF_STRUCT( T->type ) || IF_UNORDER( T->type ) )
{ // ---- возможно, что тут еще надо теги вставлять
for( i=0 ; i<T->n_down ; i++ )
print_antwort( T->down+i,fword );
if( T->type==TSTRUCT1 || T->type==TSTRUCT2 )
if( 0==Perevod.is_atom(T->i_slowo) )
{ F_LEFT_TAG
add_word( *T,fword );
F_RIGHT_TAG
}
}
if( IF_SELECT( T->type ) )
{ short z_str =strlen( Str );
short z_word=aWord.j ;
print_antwort( T->down,fword && (T->type!=TSELECT2 ) );
if( T->type==TSELECT2 && fword )
{ add_word( *T,1 );
Strcpy( aWord[z_word].Str,Str+z_str,LWORD );
}
}
sp-- ;
}
# undef F_LEFT_TAG
# undef F_RIGHT_TAG
/***************************************************************************/
void t_Antwort :: add_word( t_Tree &T, char fword )
{
t_aWord W,W1 ;
t_Tree *T_up ;
if( 0<=T.up ) T_up=&Tree2[T.up] ;
else return ;
if( (T_up->type==TSTRUCT1 || T_up->type==TSTRUCT2) &&
0==Perevod.is_atom(T_up->i_slowo) ) return ;
if( fword==0 ) return ;
W.meaning=W1.meaning=-1 ;
if( 0<T.link )
{ W.i_word = Tree1[T.link].i_word ;
W.i_last_word = Tree1[T.link].i_last_word ;
}
else
{ W.i_word = -1 ;
W.i_last_word = -1 ;
}
W.i_struct = T.i_struct ;
W.i_slowo = T.i_slowo ;
if( 0<=T.i_slowo ) W.n_slowo = Perevod.get_n_perevod( T.i_slowo );
else W.n_slowo = 1 ;
W.Form = T.Form ;
W.Str[0] = 0 ;
if( IF_WORD( T.type ) )
strcpy( W.Str,T.Str1 );
W1.i_word =W.i_word ;
W1.i_last_word=W.i_last_word ;
// ----- внесение слова, и прикрепленных к нему тегов ----
if( 0<=T.left_tag )
{ Strcpy( W1.Str,Core.tag()[T.left_tag].Str,LWORD );
aWord.add( W1 );
}
aWord.add( W );
if( 0<=T.right_tag )
{ Strcpy( W1.Str,Core.tag()[T.right_tag].Str,LWORD );
aWord.add( W1 );
}
}
/***************************************************************************/
void t_Antwort :: post_proc( void )
{
long i,i1,i2,j ;
t_sStruct *S ;
t_longList Ant ;
char c,Str1[LFRASA] ;
c=' ' ;
for( i=j=0 ; i<LFRASA && Str[i]!=0 ; i++ )
{ if( !(Str[i]!=' ' && c==' ' ) ) goto M_Normal ;
Micro.find( Str+i,-1,&Ant );
if( Ant.j<=0 ) goto M_Normal ;
// ------ внести новые слова ---------------
S=Micro.get_to( Ant[0],0 );
for( i1=0 ; i1<S->n_Word ; i1++ )
{ for( i2=0 ; i2<LFRASA && S->Word[i1].str[i2]!=0 ; i2++ )
Str1[j++]=S->Word[i1].str[i2] ;
Str1[j++]=' ' ;
}
// ------ убрать старые слова ---------------
S=Micro.get_from( Ant[0] );
i2=0 ;
for( ; i<LFRASA && Str[i]!=0 ; i++ )
{ if( Str[i]!=' ' && c==' ' ) i2++ ;
if( S->n_Word<i2 ) break ;
c=Str[i] ;
}
// возможно здесь i увеличится лишний раз
continue ;
M_Normal:
Str1[j++]=c=Str[i] ;
}
Str1[j]=0 ;
Strcpy( Str,Str1,LFRASA );
}
/***************************************************************************/
char
* t_Antwort :: str( void )
{
return Str ;
}
/***************************************************************************/
t_aWordList * t_Antwort :: aword( void )
{
return &aWord ;
}
/***************************************************************************/
t_TreeList & t_Antwort :: tree1( void )
{
return Tree1 ;
}
/***************************************************************************/
t_TreeList & t_Antwort :: tree2( void )
{
return Tree2 ;
}
/***************************************************************************/
// найти начальную форму слова
// i_struct - часть речи
// Word - слово
// Source - начальная форма слова
/***************************************************************************/
void word_source( short i_struct, char *Word, char *Source, e_Half H )
{
t_Slowo2 *Slowo ;
long Ant1[20] ;
t_Form Form1[20] ;
short i_slowar,N ;
i_slowar=-1 ;
if( H==FROM )
{ if( 0<=i_struct ) i_slowar=i_FormatF[i_struct] ;
if( 0<=i_slowar )
{ Slowo=&SlowoF[ i_slowar ];
N=Slowo->quest( Word, Ant1, Form1 );
if( 0<N ) { strcpy( Source,Slowo->normal(Ant1[0]) ); return ; }
}
}
else
{ if( 0<=i_struct ) i_slowar=i_FormatT[i_struct] ;
if( 0<=i_slowar )
{ Slowo=&SlowoT[ i_slowar ];
N=Slowo->quest( Word, Ant1, Form1 );
if( 0<N ) { strcpy( Source,Slowo->normal(Ant1[0]) ); return ; }
}
}
strcpy( Source,Word );
}
/**************************************************************************/
// найти в конструкции типа TSELECT1 выбор соответствующий строке словаря
// up_struct - номер структуры
// i_slowo - номер строки словаря
/**************************************************************************/
short find_enum_select( e_Half H, short up_struct, long i_slowo )
{ t_Struct *S0 ;
t_sStruct *S1 ;
short i ;
if( H==FROM )
{ S0=&Grammar[up_struct].From ;
S1=Perevod.get_from( i_slowo );
}
else
{ S0=&Grammar[up_struct].To ;
S1=Perevod.get_to( i_slowo );
}
for( i=0 ; i<S0->Word.j ; i++ )
if( S0->Word[i].i_struct==S1->i_struct )
return i ;
return -1 ;
}
/**************************************************************************/
// проверить, что данная строка является числом
/**************************************************************************/
char is_number( char *Str )
{
for( short i=0 ; i<99 && Str[i]!=0 ; i++ )
if( Str[i]<'0' || '9'<Str[i] ) return 0 ;
return 1 ;
}
/**************************************************************************/
// сравнить параметры
// Param - что должно быть согласно lang.txt
// Form - что есть фактически
/**************************************************************************/
char compare_param( t_Param1List *Param, t_Form *Form )
{ short i ;
for( i=0 ; i<Param->j ; i++ )
{ if( Param->list[i].value==-1 ) continue ;
if( Form->value[i]==-1 ) continue ;
if( Param->list[i].value!=Form->value[i] ) return -1 ;
}
return 0 ;
}
/**************************************************************************/
t_Antwort :: t_Antwort( void )
{
Str[0]=0 ;
}
/**************************************************************************/
void t_Antwort :: del( void )
{ Tree1.del();
Tree2.del();
aWord.del();
}
/***************************************************************************/
t_rWord :: t_rWord( )
{
type = TNULL ;
i_word =-1 ;
i_last_word =-1 ;
i_struct =-10;
i_variant =-1 ;
index =-1 ;
i_slowo =-1 ;
i_slowo1 = 0 ;
n_slowo = 0 ;
}
/***************************************************************************/
t_rStruct :: t_rStruct( void )
{
type = TNULL ;
i_word =-1 ;
i_last_word =-1 ;
i_struct =-10;
r_word =-1 ;
i_slowo =-1 ;
i_meaning =-1 ;
Form.init() ;
}
/***************************************************************************/
t_Tree :: t_Tree( void )
{ init( );
}
t_Tree :: ~t_Tree( void )
{ del( ); }
/***************************************************************************/
void t_Tree :: init( void )
{
type = TSTRUCT ;
up =-1 ;
down =-1 ;
n_down = 0 ;
i_word = 0 ;
i_last_word=-1 ;
i_struct=0 ;
select =-1 ;
link =-1 ;
index =-1 ;
i_slowo =-1 ;
i_slowo1= 0 ;
left_tag=-1 ;
right_tag=-1 ;
Form.init();
Str[0]=Str1[0]=0 ;
}
void t_Tree :: del( void )
{ ; }
/***************************************************************************/
static void p_type( char *Str, e_Type type )
{ char *s1 ;
switch( type )
{
case TNULL : s1="TNULL" ; break ;
case TCONST : s1="TCONST" ; break ;
case TCONST1 : s1="TCONST1" ; break ;
case TWORD : s1="TWORD" ; break ;
case TWORD0 : s1="TWORD1" ; break ;
case TSTRUCT : s1="TSTRUCT" ; break ;
case TSTRUCT1 : s1="TSTRUCT1" ; break ;
case TSTRUCT2 : s1="TSTRUCT2" ; break ;
case TSELECT : s1="TSELECT" ; break ;
case TSELECT1 : s1="TSELECT1" ; break ;
case TSELECT2 : s1="TSELECT2" ; break ;
}
strcpy( Str,s1 );
}
/***************************************************************************/
// вывести дерево вариантов в Файл (для отладки)
/***************************************************************************/
void print_tree( t_TreeList &Node, char *FileName )
{ long i ;
char s2[20] ;
FILE *fw ;
fw=fopen( FileName,"wb" );
fprintf( fw, "\n i type - up down n_down - iw i_last Name i_var - select link index i_slowo");
for( i=0 ; i<Node.j ; i++ )
{
p_type( s2,Node[i].type );
fprintf( fw, "\n %2ld %8s - %2ld %4ld %4ld - %2d %2d %12s %2ld - %4d %4ld %4d %4ld",
i,
s2,
Node[i].up,
Node[i].down,
Node[i].n_down,
Node[i].i_word,
Node[i].i_last_word,
Grammar[Node[i].i_struct].From.Name,
Node[i].i_variant,
Node[i].select,
Node[i].link,
Node[i].index,
Node[i].i_slowo );
}
fclose( fw );
}
/************************************************************************/
void make_token( char *Sou, char *Dst )
{ long i,j ;
for( i=0 ; Sou[i]==' ' ; i++ ) ;
for( j=0 ; Sou[i]!=0 && Sou[i]!=' ' ; i++ )
Dst[j++]=Sou[i] ;
Dst[j]=0 ;
}
/************************************************************************/
DEFINE_LIST_BTYPE( t_aWord,t_aWordList )
DEFINE_LIST_BTYPE( t_rWord,t_rWordList )
DEFINE_LIST_BTYPE( t_rStruct,t_rStructList )
DEFINE_LIST_BTYPE( t_Item, t_ItemList )
DEFINE_LIST_TYPE ( t_Tree, t_TreeList )