001 I64 ReadUTF8(U8 *st,U8 **en=NULL) { 002 I64 ch=*st; 003 if(0b10000000&ch==0) { 004 if(en) *en=st+1; 005 return ch; 006 } 007 if(0b11100000&ch==0b11000000) { 008 if(en) *en=st+2; 009 return (st[0]&0b11111)<<6|((st[1]&0b111111)); 010 } 011 if(0b11110000&ch==0b11100000) { 012 if(en) *en=st+3; 013 return (st[0]&0b1111)<<12|(st[1]&0b111111)<<6|((st[2]&0b111111)); 014 } 015 if(en) *en=st+4; 016 return (st[1]&0b111)<<18|(st[1]&0b111111)<<12|(st[2]&0b111111)<<6|((st[3]&0b111111)); 017 } 018 U8 Transliterate(U64 ch) { 019 //https://en.wiktionary.org/wiki/Appendix:Unicode/Latin_Extended-A 020 switch(ch) { 021 case 0x100...0x105: 022 ch='a'; 023 break; 024 case 0x106...0x10D: 025 ch='c'; 026 break; 027 case 0x10e...0x11b: 028 ch='e'; 029 break; 030 case 0x11f...0x123: 031 ch='e'; 032 break; 033 case 0x124...0x127: 034 ch='e'; 035 break; 036 case 0x128...0x135: 037 ch='i'; 038 break; 039 case 0x136...0x138: 040 ch='k'; 041 break; 042 case 0x139...0x142: 043 ch='l'; 044 break; 045 case 0x143...0x14b: 046 ch='n'; 047 break; 048 case 0x14c...0x151: 049 ch='o'; 050 break; 051 case 0x154...0x159: 052 ch='e'; 053 break; 054 case 0x15a...0x161: 055 ch='s'; 056 break; 057 case 0x162...0x167: 058 ch='t'; 059 break; 060 case 0x168...0x173: 061 ch='u'; 062 break; 063 case 0x174...0x175: 064 ch='w'; 065 break; 066 case 0x176...0x178: 067 ch='y'; 068 break; 069 case 0x179...0x17e: 070 ch='z'; 071 break; 072 default: 073 if(!ch) 074 return 0; 075 if(!(31<=ch<=128)) 076 ch='?'; 077 } 078 return ch; 079 } 080 081 #define J_STR 1 082 #define J_NUM 2 083 #define J_ARRAY 3 084 #define J_NODE 4 085 class CJson { 086 I64 type; 087 union { 088 U8 *str; 089 F64 num; 090 CHashTable *hash_table; 091 } 092 I64 cnt; 093 }; 094 095 U8 *sqstring(U8 *ptr,U8 **en) { 096 U8 *buf=MAlloc(256); 097 I64 ch=0,C; 098 if(en) *en=ptr; 099 if(*ptr!='\'') return NULL; 100 ptr++; 101 while(*ptr&&*ptr!='\'') { 102 if(*ptr=='\\') { 103 ptr++; 104 read_one: 105 C=ReadUTF8(ptr,&ptr); 106 if(ch<255) 107 buf[ch++]=Transliterate(C); 108 } else 109 goto read_one; 110 } 111 buf[ch]=0; 112 if(en) *en=ptr+1; 113 return buf; 114 } 115 116 U8 *dqstring(U8 *ptr,U8 **en) { 117 U8 *buf=MAlloc(256); 118 I64 ch=0,C; 119 if(en) *en=ptr; 120 if(*ptr!='"') return NULL; 121 ptr++; 122 while(*ptr&&*ptr!='"') { 123 if(*ptr=='\\') { 124 ptr++; 125 read_one: 126 C=ReadUTF8(ptr,&ptr); 127 if(ch<255) 128 buf[ch++]=Transliterate(C); 129 } else 130 goto read_one; 131 } 132 buf[ch]=0; 133 if(en) *en=ptr+1; 134 return buf; 135 } 136 137 138 U8 *SkipWhitespace(U8 *s) { 139 while(*s&&Bt(char_bmp_white_space,*s)) 140 s++; 141 return s; 142 } 143 U8 *word(U8 *ptr,U8 **en) { 144 U8 *buf=MAlloc(256); 145 I64 ch=0; 146 if(en) *en=ptr; 147 if(!Bt(char_bmp_alpha_numeric,*ptr)) return NULL; 148 while(Bt(char_bmp_alpha_numeric,*ptr)) 149 buf[ch++]=*ptr++; 150 buf[ch]=0; 151 if(en) *en=ptr; 152 return buf; 153 } 154 class CIndexBlk { 155 I64 inst_cnt; 156 I64 inst_offsets[32]; 157 U8 *body['z'-'a'+1]; 158 I64 pad[(BLK_SIZE-8-8*('z'-'a'+1))/8]; 159 }; 160 CJson *ParseJson(U8 *st,U8 **en=NULL) { 161 CJson *ret=NULL; 162 U8 *name; 163 CHashGeneric *g; 164 st=SkipWhitespace(st); 165 if(*st=='{') { 166 ret=CAlloc(sizeof CJson); 167 ret->type=J_NODE; 168 ret->hash_table=HashTableNew(0x8); 169 st=SkipWhitespace(st+1); 170 while(*st!='}') { 171 if(!*st) throw('JSON'); 172 switch(*st) { 173 case '\'': 174 name=sqstring(st,&st); 175 break; 176 case '"': 177 name=dqstring(st,&st); 178 break; 179 default: 180 name=word(st,&st); 181 break; 182 } 183 if(!name) throw('JSON'); 184 st=StrFirstOcc(st,":"); 185 if(!st) throw('JSON'); 186 st++; 187 g=CAlloc(sizeof CHashGeneric); 188 g->str=name; 189 g->type=HTT_WORD; 190 g->user_data0=ParseJson(st,&st); 191 HashAdd(g,ret->hash_table); 192 st=StrFirstOcc(st,",}"); 193 if(!st) throw('JSON'); 194 if(*st==',') st++; 195 st=SkipWhitespace(st); 196 } 197 st++; 198 } else if(*st=='\'') { 199 ret=CAlloc(sizeof CJson); 200 ret->type=J_STR; 201 ret->str=sqstring(st,&st); 202 } else if(*st=='\"') { 203 ret=CAlloc(sizeof CJson); 204 ret->type=J_STR; 205 ret->str=dqstring(st,&st); 206 } else if(*st=='[') { 207 st=SkipWhitespace(st+1); 208 ret=CAlloc(sizeof CJson); 209 ret->type=J_ARRAY; 210 ret->hash_table=HashTableNew(0x10); 211 while(*st!=']') { 212 g=CAlloc(sizeof CHashGeneric); 213 g->str=MStrPrint("%d",ret->cnt++); 214 g->type=HTT_DICT_WORD; 215 g->user_data0=ParseJson(st,&st); 216 HashAdd(g,ret->hash_table); 217 st=StrFirstOcc(st,",]"); 218 if(!st) throw('JSON'); 219 if(*st==',') st++; 220 st=SkipWhitespace(st); 221 } 222 st++; 223 } else { 224 name=st; 225 ret=CAlloc(sizeof CJson); 226 ret->type=J_NUM; 227 ret->num=Str2F64(st,&st); 228 if(name==st) 229 throw('JSON'); 230 } 231 if(en) *en=st; 232 if(!ret) throw('JSON'); 233 return ret; 234 } 235 U0 JsonDel(CJson *j) { 236 I64 bucket; 237 CHashGeneric *g; 238 switch(j->type) { 239 case J_STR: 240 Free(j->str); 241 break; 242 case J_NUM: 243 break; 244 case J_NODE: 245 case J_ARRAY: 246 for(bucket=0;bucket<=j->hash_table->mask;bucket++) 247 for(g=j->hash_table->body[bucket];g;g=g->next) { 248 JsonDel(g->user_data0); 249 } 250 HashTableDel(j->hash_table); 251 } 252 Free(j); 253 } 254 U0 DumpJson(CJson *j) { 255 I64 bucket; 256 CHashGeneric *g; 257 switch(j->type) { 258 case J_STR: 259 "\"%Q\"",j->str; 260 break; 261 case J_NUM: 262 "%n",j->num; 263 break; 264 case J_NODE: 265 case J_ARRAY: 266 "{$ID,2$\n"; 267 for(bucket=0;bucket<=j->hash_table->mask;bucket++) 268 for(g=j->hash_table->body[bucket];g;g=g->next) { 269 "%s:",g->str; 270 DumpJson(g->user_data0); 271 ",\n"; 272 } 273 "$ID,-2$\n}"; 274 } 275 } 276 I64 GetWordPtr(I64 *max,CFile *file,U8 *str,I64 ptr=0,Bool *new=NULL) { 277 if(new) *new=FALSE; 278 if(!*str) return ptr; 279 I64 idx=ToUpper(*str)-'A'; 280 CIndexBlk dummy; 281 FBlkRead(file,&dummy,ptr,1); 282 if(new) *new=FALSE; 283 if(!dummy.body[idx]) { 284 dummy.body[idx]=*max; 285 FBlkWrite(file,&dummy,ptr,1); 286 MemSet(&dummy,0,sizeof CIndexBlk); 287 FBlkWrite(file,&dummy,ptr=(*max)++,1); 288 if(new) *new=TRUE; 289 return GetWordPtr(max,file,str+1,ptr); 290 } 291 if(ptr>*max) throw('trie'); 292 return GetWordPtr(max,file,str+1,dummy.body[idx],new); 293 } 294 U0 MakeIndex(U8 *outname,U8 *in_name) { 295 CIndexBlk dummy; 296 U8 *optr=FileRead(in_name),*fptr; 297 Bool new; 298 CFile *file; 299 CHeapCtrl *cc; 300 CHashGeneric *g; 301 CJson *j,*str; 302 Del(outname); 303 file=FOpen(outname,"w"); 304 MemSet(&dummy,0,sizeof CIndexBlk); 305 FBlkWrite(file,&dummy); 306 fptr=optr; 307 I64 off=0,blk,sz=1; 308 do { 309 fptr=SkipWhitespace(fptr); 310 off=fptr-optr; 311 if(!*fptr) break; 312 j=ParseJson(fptr,&fptr); 313 if(j&&j->type==J_NODE) { 314 g=HashFind("word",j->hash_table,-1); 315 str=g->user_data0; 316 if(str&&str->type=J_STR) { 317 //Ensure all charactors are alpha 318 for(blk=0;blk!=StrLen(str->str);blk++) { 319 if(!('A'<=ToUpper(str->str[blk])<='Z')) 320 goto skip; 321 } 322 blk=GetWordPtr(&sz,file,str->str,,&new); 323 FBlkRead(file,&dummy,blk,1); 324 if(new) { 325 dummy.inst_cnt=1; 326 dummy.inst_offsets[0]=off; 327 } else { 328 if(dummy.inst_cnt<32) 329 dummy.inst_offsets[dummy.inst_cnt++]=off; 330 } 331 FBlkWrite(file,&dummy,blk,1); 332 skip:; 333 } 334 } 335 JsonDel(j); 336 } while(TRUE); 337 file->de.size=sz<<BLK_SIZE_BITS; 338 FClose(file); //Flush to disk to avoid long ram buffering 339 Free(optr); 340 } 341 //Yvng poop poodle https://kaikki.org/dictionary/Latin/kaikki.org-dictionary-Latin.json 342 if(!FileFind("/INDEX.TRIE")&&FileFind("/Latin.json")) 343 MakeIndex("/INDEX.TRIE","/Latin.json"); 344 I64 GetWordOffset(U8 *word,U8 *index_file="/INDEX.TRIE",I64 inst=0) { 345 CFile *file=FOpen(index_file,"r"); 346 CIndexBlk dummy; 347 I64 blk=0,idx,off=-1; 348 while(*word) { 349 idx=ToUpper(*word)-'A'; 350 FBlkRead(file,&dummy,blk,1); 351 if(!dummy.body[idx]) 352 break; 353 blk=dummy.body[idx]; 354 word++; 355 } 356 if(!*word) { 357 FBlkRead(file,&dummy,blk,1); 358 off=dummy.inst_offsets[inst]; 359 if(!off) off=-1; 360 } 361 FClose(file); 362 return off; 363 } 364 U8 *GetWordString(U8 *word,U8 *json_file="/Latin.json",U8 *index_file="/INDEX.TRIE",I64 inst=0) { 365 I64 off=GetWordOffset(word,index_file,inst),off2; 366 if(off==-1) return NULL; 367 U8 buffer[0x10000],fbuf[BLK_SIZE],*ret,*tmp; 368 I64 bo=0; 369 CFile *file=FOpen(json_file,"r"); 370 buffer[bo]=0; 371 loop: 372 FBlkRead(file,fbuf,off2=off>>BLK_SIZE_BITS); 373 off2<<=BLK_SIZE_BITS; 374 if(off!=off2) { 375 MemCpy(buffer+bo,fbuf+off-off2,BLK_SIZE-(off-off2)); 376 bo+=BLK_SIZE-(off-off2); 377 off=off2+BLK_SIZE; 378 buffer[bo]=0; 379 } else { 380 MemCpy(buffer+bo,fbuf,BLK_SIZE); 381 bo+=BLK_SIZE; 382 off=off2+BLK_SIZE; 383 buffer[bo]=0; 384 } 385 if(!StrOcc(buffer,'\n')) { 386 goto loop; 387 } else *StrFirstOcc(buffer,"\n")=0; 388 FClose(file); 389 ret=CAlloc(bo+1); 390 tmp=buffer; 391 off=0; 392 while(bo=Transliterate(ReadUTF8(tmp,&tmp))) { 393 ret[off++]=bo; 394 } 395 return ret; 396 } 397 CJson *GetJsonMember(CJson *j,U8 *member,I64 type=-1) { 398 CHashGeneric *g; 399 if(j->type==J_ARRAY||j->type==J_NODE) { 400 g=HashFind(member,j->hash_table,-1); 401 if(g) { 402 j=g->user_data0; 403 if(type==-1) return j; 404 else if(type==j->type) return j; 405 } 406 } 407 return NULL; 408 } 409 U8 *GetBaseWord(U8 *word,I64 inst=0) { 410 U8 *ws=GetWordString(word); 411 if(!ws) return NULL; 412 U8 buf[STR_LEN]; 413 I64 idx,idx2; 414 CJson *j=ParseJson(ws,NULL),*s0,*s,*f,*t; 415 Free(ws); 416 if(s0=GetJsonMember(j,"senses",J_ARRAY)) { 417 if(s=GetJsonMember(s0,StrPrint(buf,"%d",inst),J_NODE)) { 418 f=GetJsonMember(s,"form_of",J_ARRAY); 419 if(f) { 420 for(idx=0;t=GetJsonMember(f,StrPrint(buf,"%d",idx),J_NODE);idx++) { 421 if(t) t=GetJsonMember(t,"word",J_STR); 422 if(t) { 423 word=StrNew(t->str); 424 JsonDel(j); 425 return word; 426 } 427 } 428 } 429 } 430 } 431 JsonDel(j); 432 if(inst) 433 return NULL; 434 return StrNew(word); 435 } 436 Bool IsFormOf(U8 *who,U8 *who2) { 437 I64 i,i2; 438 U8 *b,*b2,ret=FALSE; 439 for(i=0;b=GetBaseWord(who,i);i++) { 440 for(i2=0;b2=GetBaseWord(who,i2);i2++) { 441 if(!StrCmp(b,b2)) 442 ret=TRUE; 443 Free(b2); 444 } 445 Free(b); 446 } 447 return ret; 448 } 449 extern U8 *GetTranslation(U8*,Bool recurse=FALSE); 450 U8 *SmallDefinition(U8 *def) { 451 if(!def) return def; 452 U8 buf[STR_LEN],*bptr=buf,*want; 453 Bool changed=TRUE; 454 I64 len1,len2; 455 def=StrNew(def); 456 if(want=StrIMatch("conjugation of",def)) { 457 StrScan(want,"conjugation of %s:",&bptr); 458 return GetTranslation(buf); 459 } 460 if(want=StrIMatch("inflection of",def)) { 461 StrScan(want,"inflection of %s:",&bptr); 462 return GetTranslation(buf); 463 } 464 if(want=StrIMatch("alternative spelling of",def)) { 465 StrScan(want,"alternative spelling of %s:",&bptr); 466 return GetTranslation(buf); 467 } 468 while(changed) { 469 changed=FALSE; 470 U8 *first=StrFirstOcc(def,"("),*last; 471 if(first) { 472 if(last=StrFirstOcc(first,")")) { 473 StrCpy(first,last+1); 474 changed=TRUE; 475 } 476 } 477 if(first=StrFirstOcc(def,",")) { 478 len1=first-def; 479 len2=StrLen(first+1); 480 if(len1<len2) { 481 *first=0; 482 } else { 483 StrCpy(def,first+1); 484 } 485 changed=TRUE; 486 } 487 } 488 return StrUtil(def,SUF_REM_TRAILING|SUF_REM_LEADING); 489 } 490 //Your on your own 491 U8 *GetTranslation(U8 *word,Bool recurse=TRUE) { 492 I64 inst; 493 U8 *str; 494 if(!word) return NULL; 495 U8 buf[STR_LEN],*best=NULL,buf2[STR_LEN]; 496 I64 idx,idx2; 497 CJson *j,*t,*s0,*g,*s,*f; 498 U8 *trans=NULL,*tmp; 499 for(inst=0;str=GetWordString(word,,,inst);inst++) { 500 j=ParseJson(str,NULL); 501 if(s0=GetJsonMember(j,"senses",J_ARRAY)) { 502 if(s=GetJsonMember(s0,"0",J_NODE)) { //Use first (most common ?) sense of the word 503 f=GetJsonMember(s,"form_of",J_ARRAY); 504 if(f) { 505 for(idx=0;t=GetJsonMember(f,StrPrint(buf,"%d",idx),J_NODE);idx++) { 506 if(t) t=GetJsonMember(t,"word",J_STR); 507 if(!t) goto defacto; 508 if(tmp=GetTranslation(t->str,FALSE)) { 509 if(!trans) trans=tmp; 510 else if(StrLen(trans)>StrLen(tmp)) { 511 Free(trans); 512 trans=tmp; 513 } else 514 Free(tmp); 515 } 516 } 517 //Only use definition of root word 518 goto fin; 519 } else { 520 defacto:; 521 g=GetJsonMember(s,"glosses",J_ARRAY); 522 //Pick shortest translation 523 if(g) { 524 //Use 1st (Most common?) defintion 525 if(t=GetJsonMember(g,"0",J_STR)) { 526 tmp=SmallDefinition(t->str); 527 if(!trans) trans=tmp; 528 else if(StrLen(trans)>StrLen(tmp)) { 529 Free(trans); 530 trans=tmp; 531 } else 532 Free(tmp); 533 } 534 } 535 } 536 } 537 } 538 fin:; 539 JsonDel(j); 540 Free(str); 541 } 542 if(!trans) 543 return trans; 544 return StrUtil(trans,SUF_REM_CTRL_CHARS); 545 } 546 //Returns a long list of translations 547 U8 *GetTranslations(U8 *word,Bool recurse=TRUE,I64 *_which=NULL) { 548 I64 inst; 549 U8 *str; 550 if(!word) return NULL; 551 U8 buf[STR_LEN],*best=NULL,buf2[STR_LEN]; 552 I64 idx,idx2; 553 CJson *j,*t,*s0,*g,*s,*f; 554 I64 which=1; 555 if(!_which) 556 _which=&which; 557 CDoc *trans=DocNew; 558 for(inst=0;str=GetWordString(word,,,inst);inst++) { 559 j=ParseJson(str,NULL); 560 if(s0=GetJsonMember(j,"senses",J_ARRAY)) { 561 for(idx2=0;s=GetJsonMember(s0,StrPrint(buf,"%d",idx2),J_NODE);idx2++) { 562 f=GetJsonMember(s,"form_of",J_ARRAY); 563 if(f) { 564 for(idx=0;t=GetJsonMember(f,StrPrint(buf,"%d",idx),J_NODE);idx++) { 565 if(t) t=GetJsonMember(t,"word",J_STR); 566 if(!t) goto defacto; 567 if(best=GetTranslations(t->str,FALSE,_which)) { 568 DocPrint(trans,"%s",best); 569 Free(best); 570 } 571 } 572 goto defacto; 573 } else { 574 defacto: 575 g=GetJsonMember(s,"glosses",J_ARRAY); 576 //Pick shortest translation 577 if(g) { 578 for(idx=0;t=GetJsonMember(g,StrPrint(buf,"%d",idx),J_STR);idx++) { 579 DocPrint(trans,"%d: %s\n",(*_which)++,t->str); 580 } 581 } 582 } 583 } 584 } 585 JsonDel(j); 586 Free(str); 587 } 588 best=DocSave(trans); 589 DocDel(trans); 590 return StrUtil(best,SUF_REM_CTRL_CHARS); 591 } 592 CTask *p=Fs; 593 U0 LookUpWord(U8 *word) { 594 if(FramePtr(word,trie_task)) 595 return; 596 //avoid renundant 597 FramePtrAdd(word,1,trie_task); 598 U8 dummy[STR_LEN]; 599 U8 *json_file="../Latin.json",*index_file="/INDEX.TRIE"; 600 U8 *str,*trans; 601 I64 inst=0; 602 PrintI(word,1); 603 trans=GetTranslation(word); 604 PrintI(trans,2); 605 loop:; 606 I64 flags=0,idx,idx2,base_flags=0,idx3,added=0; 607 str=GetWordString(word,json_file,index_file,inst++); 608 if(!str) { 609 Free(trans); 610 return; 611 } 612 CJson *j=ParseJson(str,NULL),*n,*f,*senses; 613 if(n=GetJsonMember(j,"pos",J_STR)) { 614 if(!StrICmp(n->str,"verb")) flags|=VERB; 615 else if(!StrICmp(n->str,"noun")) flags|=NOUN; 616 else if(!StrICmp(n->str,"adj")) flags|=ADJECTIVE; 617 else if(!StrICmp(n->str,"conj")) flags|=CONJUNCTION; 618 else if(!StrICmp(n->str,"prep")) flags|=PREPOSITION; 619 else if(!StrICmp(n->str,"adv")) flags|=ADVERB; 620 else if(!StrICmp(n->str,"pron")) flags|=PRONOUN; 621 } 622 base_flags=flags; 623 for(idx3=0;idx3!=2;idx3++) { 624 if(idx3==0) 625 senses=GetJsonMember(j,"senses",J_ARRAY); 626 else if(idx3==1) 627 senses=GetJsonMember(j,"forms",J_ARRAY); 628 if(senses) { 629 for(idx2=0;idx2!=senses->cnt;idx2++) { 630 StrPrint(dummy,"%d",idx2); 631 n=GetJsonMember(senses,dummy);; 632 flags=base_flags; 633 if(idx3==1) { 634 if(f&&(f=GetJsonMember(n,"form",J_STR))) { 635 if(StrICmp(f->str,word)) 636 goto skip; 637 } else 638 goto skip; 639 } 640 if(n&&(n=GetJsonMember(n,"tags",J_ARRAY))) { 641 for(idx=0;idx!=n->cnt;idx++) { 642 StrPrint(dummy,"%d",idx); 643 if(f=GetJsonMember(n,dummy,J_STR)) { 644 DbgPrint("%s for %s\n",f->str,word); 645 if(!StrICmp(f->str,"masculine")) flags|=MASCULINE; 646 if(!StrICmp(f->str,"feminine")) flags|=FEMININE; 647 if(!StrICmp(f->str,"neuter")) flags|=NEUTER; 648 if(!StrICmp(f->str,"singular")) flags|=SINGULAR; 649 if(!StrICmp(f->str,"plural")) flags|=PLURAL; 650 if(!StrICmp(f->str,"nominative")) flags|=NOMITIVE; 651 if(!StrICmp(f->str,"accusative")) flags|=ACCUSATIVE; 652 if(!StrICmp(f->str,"dative")) flags|=DATIVE; 653 if(!StrICmp(f->str,"ablative")) flags|=ABLATIVE; 654 if(!StrICmp(f->str,"genitive")) flags|=GENITIVE; 655 if(!StrICmp(f->str,"infinitive")) flags|=INFINITIVE; 656 if(!StrICmp(f->str,"imperfect")) flags|=IMPERFECT; 657 if(!StrICmp(f->str,"future")) flags|=FUTURE; 658 if(!StrICmp(f->str,"first-person")) flags|=_1P; 659 if(!StrICmp(f->str,"second-person")) flags|=_2P; 660 if(!StrICmp(f->str,"third-person")) flags|=_3P; 661 if(!StrICmp(f->str,"perfect")) flags|=PERFECT; 662 if(!StrICmp(f->str,"pluperfect")) flags|=PLUPERFECT; 663 if(!StrICmp(f->str,"subjunctive")) flags|=SUBJUNCTIVE; 664 if(!StrICmp(f->str,"passive")) flags|=PASSIVE; 665 if(!StrICmp(f->str,"comparative")) flags|=COMPARATIVE; 666 if(!StrICmp(f->str,"superlative")) flags|=SUPERLATIVE; 667 if(!StrICmp(f->str,"participle")) flags|=PARTICIPLE; 668 if(!StrICmp(f->str,"determiner")) flags|=DETIRMINER; 669 if(!StrICmp(f->str,"pronoun")) flags|=PRONOUN; 670 if(!StrICmp(f->str,"declension-1")) flags|=DECLENSION1; 671 if(!StrICmp(f->str,"declension-2")) flags|=DECLENSION2; 672 if(!StrICmp(f->str,"declension-3")) flags|=DECLENSION3; 673 if(!StrICmp(f->str,"declension-4")) flags|=DECLENSION4; 674 if(!StrICmp(f->str,"declension-5")) flags|=DECLENSION5; 675 if(!StrICmp(f->str,"conjugation-1")) flags|=CONJUGATION1; 676 if(!StrICmp(f->str,"conjugation-2")) flags|=CONJUGATION2; 677 if(!StrICmp(f->str,"conjugation-3")) flags|=CONJUGATION3; 678 if(!StrICmp(f->str,"conjugation-4")) flags|=CONJUGATION4; 679 if(!StrICmp(f->str,"active")) flags|=0; //ACTIVE is implicit 680 if(!StrICmp(f->str,"intransitive")) flags|=INTRANSITIVE; 681 if(!StrICmp(f->str,"superlative")) flags|=SUPERLATIVE; 682 if(!StrICmp(f->str,"comparative")) flags|=COMPARATIVE; 683 DbgPrint("%s for %s\n",f->str,word); 684 } 685 } 686 if(!TrieExists(word,flags)) { 687 added++; 688 DeclensionForWord(flags,TrieAdd(word,flags,trans)); 689 } 690 skip:; 691 } 692 } 693 } 694 } 695 if(!added) 696 TrieAdd(word,base_flags,trans); 697 JsonDel(j); 698 Free(str); 699 goto loop; 700 }