001 Cd(__DIR__);
002 #include "GrammarAST.HC"
003 #define LIMIT_FP "GenCap"
004 #define CNT_FP "GenCnt"
005 #define RESULTS_FP "Results"
006 CTask *grammar_task=Fs;
007 class CRule {
008   U8 name[STR_LEN]; //Rule name or word name
009   I64 raw_type;
010   U8 *validate_fun; //CallExtStr HasForm Bool Fun(I64 argc,CAST **argc);
011   U8 *flags_fun; //CallExtStr HasForm Bool Fun(...); Sets the flags of the node
012   I64Set *made_from;
013 //add_to_member is a list of member types (AST_xxx) to add made_from's too 
014 //NULL for default
015   I64Set *member_types;
016   I64 main_item_idx;
017   I64 is_word;
018   I64 word_flags; //Flags to match
019   F64 weight; //.5 by default
020 };
021 
022 I64 MemberNameToI64(U8 *str) {
023   if(!StrCmp(str,"NOUN"))
024     return AST_NOUN;
025   else if(!StrCmp(str,"VERB"))
026     return AST_VERB;
027   else if(!StrCmp(str,"CONJUNCTION"))
028     return AST_CONJUNCTION;
029   else if(!StrCmp(str,"OF"))
030     return AST_OF;
031   else if(!StrCmp(str,"WHERE"))
032     return AST_WHERE;
033   else if(!StrCmp(str,"ADJECTIVE"))
034     return AST_ADJECTIVE;
035   else if(!StrCmp(str,"INFINITIVE"))
036     return AST_INFINITIVE;
037   else if(!StrCmp(str,"MEASURE"))
038     return AST_MEASURE;
039   else if(!StrCmp(str,"ADVERB"))
040     return AST_ADVERB;
041   else if(!StrCmp(str,"CLAUSE"))
042     return AST_INDIRECT_CLAUSE;
043   else if(!StrCmp(str,"COMPARE"))
044     return AST_COMPARSION;
045   else if(!StrCmp(str,"QUESTION"))
046     return AST_QUESTION;
047   else
048     return -1;
049 }
050 #define CASE_MASK (NOMITIVE|ACCUSATIVE|ABLATIVE|DATIVE|GENITIVE)
051 #define NUMBER_MASK (PLURAL)
052 I64 FlagsSingle(I64 argc,AST **argv) {
053   I64 i=0;
054   AST *ast;
055   I64 or=0;
056   for(i=0;i!=argc;i++)  {
057     ast=argv[i];
058     if(ast->act_as_type==AST_NOUN)
059       or|=ast->flags;
060   }
061   return or;
062 } 
063 I64 FlagsPlural(I64 argc,AST **argv) {
064   I64 i=0;
065   AST *ast;
066   I64 or=PLURAL;
067   for(i=0;i!=argc;i++)  {
068     ast=argv[i];
069     if(ast->act_as_type==AST_NOUN)
070       or|=ast->flags;
071   }
072   return or;
073 } 
074 I64 FlagsAppositive(I64 argc,AST **argv) {
075   I64 i=0;
076   AST *ast;
077   I64 or=0;
078   for(i=0;i!=argc;i++)  {
079     ast=argv[i];
080     if(ast->act_as_type==AST_NOUN)
081       or|=ast->flags;
082   }
083   return or;
084 } 
085 I64 FlagsTransfer(I64 argc,AST **argv) {
086   I64 i=0;
087   AST *ast;
088   I64 or=0;
089   for(i=0;i!=argc;i++)  {
090     ast=argv[i];
091     or|=ast->flags;
092   }
093   return or;
094 } 
095 I64 FlagsAcc(I64 argc,AST **argv) {
096   I64 i=0;
097   AST *ast;
098   I64 or=ACCUSATIVE;
099   for(i=0;i!=argc;i++)  {
100     ast=argv[i];
101     or|=ast->flags;
102   }
103   return or;
104 } 
105 
106 Bool NumberAgree(I64 argc,AST **argv) {
107   I64 i=0;
108   AST *ast;
109   Bool plural=FALSE;
110   Bool nomitive_only=FALSE;
111   for(i=0;i!=argc;i++)  {
112     ast=argv[i];
113     if(ast->act_as_type==AST_ADJECTIVE) {
114       if(ast->flags&PLURAL)
115         plural=TRUE;
116     } else if(ast->act_as_type==AST_VERB) {
117       nomitive_only=TRUE;
118       if(ast->flags&PLURAL)
119         plural=TRUE;
120     }
121   }
122   for(i=0;i!=argc;i++)  {
123     ast=argv[i];
124     if(ast->act_as_type==AST_NOUN)
125       if(nomitive_only) {
126         if(ast->flags&NOMITIVE)
127           if(ToBool(ast->flags&PLURAL)^^plural)
128             return FALSE;
129       } else if(ToBool(ast->flags&PLURAL)^^plural)
130         return FALSE;
131   }
132   return TRUE;
133 }
134 
135 Bool Transitive(I64 argc,AST **argv) {
136   if(!NumberAgree(argc,argv))
137     return FALSE;
138   I64 i=0;
139   AST *ast;
140   for(i=0;i!=argc;i++)  {
141     ast=argv[i];
142     if(ast->act_as_type==AST_VERB)
143       if(ast->flags&INTRANSITIVE)
144           return FALSE;
145   }
146   return TRUE;
147 }
148 Bool Intransitive(I64 argc,AST **argv) {
149   if(!NumberAgree(argc,argv))
150     return FALSE;
151   I64 i=0;
152   AST *ast;
153   for(i=0;i!=argc;i++)  {
154     ast=argv[i];
155     if(ast->act_as_type==AST_VERB)
156       if(ast->flags&INTRANSITIVE)
157         return TRUE;
158   }
159   return FALSE;
160 }
161 
162 
163 Bool CaseAgree(I64 argc,AST **argv) {
164   I64 i=0;
165   AST *ast;
166   I64 cs=0,mask=CASE_MASK;
167   while(i<argc) {
168     ast=argv[i];
169     if(ast->act_as_type==AST_NOUN) {
170       if(!cs) {
171         cs=ast->flags&mask;
172       } else  {
173         if((ast->flags&mask)!=cs) {
174           return FALSE;
175         }
176      }
177     }
178     i++;
179   }
180   return TRUE;
181 }
182 //Momitive quam albative
183 Bool CaseQuam(I64 argc,AST **argv) {
184   I64 i=0;
185   AST *ast;
186   I64 cs=NOMITIVE,mask=CASE_MASK;
187   Bool has_nomitive=FALSE;
188   Bool has_ablative=FALSE;
189   while(i<argc) {
190     ast=argv[i];
191     if(ast->act_as_type==AST_NOUN) {
192       if((ast->flags&mask)!=cs) {
193         return FALSE;
194       }
195       if(cs&mask==NOMITIVE) {
196         has_nomitive=TRUE;
197         cs=ABLATIVE;
198       }
199       if(cs&mask==ABLATIVE) {
200         has_ablative=TRUE;
201         cs=ABLATIVE;
202       }
203     }
204     i++;
205   }
206   return has_nomitive&&has_ablative;
207 }
208 Bool CaseX(I64 x,I64 argc,AST **argv) {
209   I64 i=0;
210   AST *ast;
211   I64 cs=x,mask=CASE_MASK;
212   while(i<argc) {
213     ast=argv[i];
214     if(ast->act_as_type==AST_NOUN) {
215       if(!cs) {
216         cs=ast->flags&mask;
217       } else  {
218         if(ast->flags&mask!=cs) {
219           return FALSE;
220         }
221      }
222     }
223     i++;
224   }
225   return TRUE;
226 }
227 Bool CaseNom(I64 argc,AST **argv) {
228   return CaseX(NOMITIVE,argc,argv);
229 }
230 Bool CaseAcc(I64 argc,AST **argv) {
231   return CaseX(ACCUSATIVE,argc,argv);
232 }
233 Bool CaseAbl(I64 argc,AST **argv) {
234   return CaseX(ABLATIVE,argc,argv);
235 }
236 Bool CaseDat(I64 argc,AST **argv) {
237   return CaseX(DATIVE,argc,argv);
238 }
239 Bool CaseGen(I64 argc,AST **argv) {
240   return CaseX(GENITIVE,argc,argv);
241 }
242 
243 U0 ParseRules(U8 *text) {
244   CCmpCtrl *cc=CmpCtrlNew(text,CCF_DONT_FREE_BUF|CCF_NO_DEFINES);
245   CRule *rule;
246   I64 s,member_type;
247   Lex(cc);
248   while(cc->token) {
249     rule=CAlloc(sizeof CRule);
250     rule->weight=.5;
251 //Name
252     if(cc->token!=TK_IDENT) 
253       LexExcept(cc,"Expected a rule name at ");
254     rule->name[0]='!';
255     StrCpy(rule->name+1,cc->cur_str);
256     Lex(cc);
257     if(cc->token=='(') {
258       Lex(cc);
259       if(cc->token==TK_IDENT) {
260         rule->validate_fun=StrNew(cc->cur_str);
261       } else
262         LexExcept(cc,"Expected function name at ");
263       Lex(cc); //')'
264       if(cc->token!=')')
265         LexExcept(cc,"Expected ')' at ");
266       Lex(cc); 
267     }
268     if(cc->token=='[') {
269       Lex(cc);
270       if(cc->token==TK_IDENT) {
271         rule->flags_fun=StrNew(cc->cur_str);
272       } else
273         LexExcept(cc,"Expected function name at ");
274       Lex(cc); //')'
275       if(cc->token!=']')
276         LexExcept(cc,"Expected ']' at ");
277       Lex(cc); 
278     }
279 //Put in member
280     if(cc->token!=TK_IDENT) 
281       LexExcept(cc,"Expected a rule class at ");
282     rule->raw_type=MemberNameToI64(cc->cur_str);
283     if(rule->raw_type==-1)
284       LexExcept(cc,"Expected valid type at ");
285     Lex(cc);
286     if(cc->token==TK_DEREFERENCE) { //->
287       rule->main_item_idx=-1;
288       Lex(cc);
289       while(cc->token==TK_IDENT||cc->token=='!'||cc->token==TK_STR) {
290         member_type=-1;
291         if(cc->token=='!') {
292           Lex(cc);
293           if(!rule->made_from)
294             rule->main_item_idx=0;
295           else
296             rule->main_item_idx=rule->made_from->cnt;
297           if(cc->token!=TK_IDENT&&cc->token!=TK_STR)
298             LexExcept(cc,"Expected a rule name at ");
299         }
300         rule->made_from=I64SetAdd(rule->made_from,StrNew(cc->cur_str),TRUE);
301         Lex(cc);
302         if(cc->token=='(') {
303           if(Lex(cc)!=TK_IDENT)
304             LexExcept(cc,"Expected a valid member type at ");
305           member_type=MemberNameToI64(cc->cur_str);;
306           if(member_type==-1)
307             LexExcept(cc,"Expected a valid member type at ");
308           if(Lex(cc)!=')')
309             LexExcept(cc,"Expected a ')' at ");
310           Lex(cc);
311         }
312         rule->member_types=I64SetAdd(rule->member_types,member_type,TRUE);
313       }
314       if(cc->token!=';')
315         LexExcept(cc,"Expected a ',' or a ';' at ");
316     } else if(cc->token=='=') {
317       rule->is_word=TRUE;
318       Lex(cc);
319       while(cc->token==TK_IDENT) {
320         rule->word_flags|=ExePrint("%s;",Define(cc->cur_str));
321         if(Lex(cc)==',')
322           Lex(cc);
323         else
324           break;
325       }
326       if(cc->token!=';')
327         LexExcept(cc,"Expected a ',' or a ';' at ");
328     }
329     Lex(cc);
330     if(cc->token=='(') {
331       Lex(cc);
332       if(cc->token==TK_F64) {
333         rule->weight=cc->cur_f64;
334       } else
335         LexExcept(cc,"Expected a rule weight at ");
336       Lex(cc);
337       if(cc->token!=')')
338         LexExcept(cc,"Expected a ')' at ");
339       Lex(cc);
340     }
341     FramePtrAdd(rule->name,rule);
342   }
343   CmpCtrlDel(cc);
344 }
345 U0 AddThingToAST(AST *have,AST *to,I64 where=-1) {
346   if(where==-1)
347     where=have->raw_type;
348   to->prob*=have->prob;
349   to->args=I64SetAdd(to->args,have);
350   switch(where) {
351     case AST_NOUN:
352       if(have->flags&CASE_MASK==0) {
353         //???
354         to->nomitive=ASTSetAdd(to->nomitive,have);
355       } else if(have->flags&NOMITIVE){
356         to->flags|=NOMITIVE;
357         to->nomitive=ASTSetAdd(to->nomitive,have);
358       } else if(have->flags&ACCUSATIVE){
359         to->flags|=ACCUSATIVE;
360         to->accusative=ASTSetAdd(to->accusative,have);
361       } else if(have->flags&DATIVE){
362         to->flags|=DATIVE;
363         to->dative=ASTSetAdd(to->dative,have);
364       } else if(have->flags&ABLATIVE){
365         to->flags|=ABLATIVE;
366         to->ablative=ASTSetAdd(to->ablative,have);
367       } else if(have->flags&GENITIVE){
368         to->flags|=GENITIVE;
369         to->genitive=ASTSetAdd(to->genitive,have);
370       }
371       break;
372     case AST_CONJUNCTION:
373       to->flags|=PLURAL|have->flags;
374       to->conjunction=ASTSetAdd(to->conjunction,have);
375       break;
376     case AST_OF:
377       to->genitive=ASTSetAdd(to->genitive,have);
378       break;
379     case AST_WHERE:
380       to->flags|=PREPOSITION;
381       to->preposition=ASTSetAdd(to->preposition,have);
382       break;
383     case AST_ADJECTIVE:
384       to->flags|=ADJECTIVE;
385       to->adjective=ASTSetAdd(to->adjective,have);
386       break;
387     case AST_INFINITIVE:
388       to->flags|=INFINITIVE;
389       to->nomitive=ASTSetAdd(to->nomitive,have);
390       break;
391     case AST_MEASURE:
392       to->measurement=ASTSetAdd(to->measurement,have);
393       break;
394     case AST_ADVERB:
395       to->flags|=ADVERB;
396       to->adverb=ASTSetAdd(to->adverb,have);
397       break;
398     case AST_INDIRECT_CLAUSE:
399       to->nomitive=ASTSetAdd(to->nomitive,have);
400       break;
401     case AST_COMPARSION:
402       to->measurement=ASTSetAdd(to->measurement,have);
403       break;
404     case AST_QUESTION:
405       to->question=ASTSetAdd(to->question,have);
406       break;
407 default:
408   }
409 }
410 extern U0 Chain(CRule *chain,I64 idx,ASTSet *add_to,CGrammarState *st,I64 start_woff=0,I64 recursion_level=0);
411 
412 Bool IsLeftRecursive(CRule *r) {
413   if(!r) return FALSE;
414   if(r->made_from)
415 //r->name starts with a "!"
416     return !StrCmp(r->name+1,r->made_from->body[0]);
417   return FALSE;
418 }
419 
420 U0 RunRule(CGrammarState *st) {
421   if(st->cnt<=0) return;
422   U8 dummy[STR_LEN];
423   StrPrint(dummy,"!%s",st->rule);
424   FramePtrAdd(RESULTS_FP,NULL);
425   I64 inst=1,idx,depth,en2,try2;
426   I64 left_recursive=0;
427   I64 attempt=0,find_cnt;
428   CHashGeneric *h;
429   CRule *r;
430   AST *ret;
431   CTrie **flat;
432   ASTSet *results=NULL,*dummy_set;
433   CGenerator *g;
434   CGrammarState orig,clone;
435   CTrie *word;
436   MemCpy(&orig,st,sizeof CGrammarState);
437 again: 
438   for(inst=1;h=HashFind(dummy,grammar_task->hash_table,HTT_FRAME_PTR,inst);inst++) {
439     MemCpy(st,&orig,sizeof CGrammarState);
440     MemCpy(&clone,st,sizeof CGrammarState);
441     r=h->user_data0;
442     left_recursive|=IsLeftRecursive(r);
443 //TODO allow other forms of the word
444     if(GetWord(r->name)&&IsFormOf(r->name,st->words[0])) {
445       word=GetWord(st->words[0]);
446       while(word) {
447         ret=CAlloc(sizeof(AST),mem_task);
448         ret->prob=1.;
449         ret->word_idx=st->woff;
450         if(r->raw_type) { 
451           ret->act_as_type=ret->raw_type=r->raw_type;
452         } else if(word->flags&NOUN) {
453           ret->act_as_type=ret->raw_type=AST_NOUN;
454         } else if(word->flags&VERB) {
455           ret->act_as_type=ret->raw_type=AST_VERB;
456         } else if(word->flags&CONJUNCTION) {
457           ret->act_as_type=ret->raw_type=AST_CONJUNCTION;
458         } else if(word->flags&ADJECTIVE) {
459           ret->act_as_type=ret->raw_type=AST_ADJECTIVE;
460         } else if(word->flags&INFINITIVE) {
461           ret->act_as_type=ret->raw_type=AST_INFINITIVE;
462         } else if(word->flags&ADVERB) {
463           ret->act_as_type=ret->raw_type=AST_ADVERB;
464         }
465 
466         ret->word=word;
467         ret->flags=word->flags;
468         ret->end=1;
469         ret->prob=r->weight;
470         ret->args=I64SetAdd(ret->args,ret);
471         FramePtrSet(RESULTS_FP,ASTSetAdd(FramePtr(RESULTS_FP),ASTClone(ret)));
472         GeneratorYield(ret);
473         word=word->next;
474       }
475     }
476     if(r->is_word) {
477       word=GetWord(st->words[0]);
478       while(word&&!attempt) {
479         if(st->en) *st->en=1;
480         if(word->flags&r->word_flags==r->word_flags) {
481           ret=CAlloc(sizeof(AST),mem_task);
482           ret->prob=1.;
483           ret->word_idx=st->woff;
484           ret->act_as_type=ret->raw_type=r->raw_type;
485           ret->word=word;
486           ret->flags=word->flags;
487           ret->end=1;
488           ret->prob=r->weight;
489           ret->args=I64SetAdd(ret->args,ret);
490           FramePtrSet(RESULTS_FP,ASTSetAdd(FramePtr(RESULTS_FP),ASTClone(ret)));
491           GeneratorYield(ret);
492         }
493         word=word->next;
494       }
495     } else {
496       if(r->made_from) {
497         if(attempt) {
498           if(results&&IsLeftRecursive(r)) {
499             for(idx=0;idx!=results->cnt;idx++) {
500               ret=results->body[idx];
501               dummy_set=ASTSetAdd(NULL,ASTClone(ret));
502               MemCpy(&clone,st,sizeof CGrammarState);
503               clone.is_conj2=TRUE;
504               clone.woff+=ret->end;
505               clone.cnt-=ret->end;
506               clone.words+=ret->end;
507               Chain(r,1,dummy_set,&clone,st->woff,attempt);
508               ASTSetDel(dummy_set);
509             }
510           }
511         } else if(!IsLeftRecursive(r)) {
512           MemCpy(&clone,st,sizeof CGrammarState);
513           Chain(r,0,NULL,&clone,st->woff,attempt);
514         }
515       }
516     }
517 skip:;
518   }
519 //Do "sub-parts" outside of the nain loop;WE ONLY NEED TO COMPUTE ONCE
520   if(!attempt)
521     if(!StrCmp(st->words[0],"[")) {
522       depth=0;
523       for(idx=0;idx<st->cnt;idx++) {
524         if(!StrCmp(st->words[idx],"["))
525           depth++;
526         else if(!StrCmp(st->words[idx],"]"))
527           depth--;
528         if(!depth) break;
529       }
530       if(!depth) {
531         MemCpy(&clone,st,sizeof CGrammarState);
532         clone.woff++;
533         clone.words++;
534         clone.cnt=idx-1;
535         clone.en=&en2;
536         g=GeneratorNewC(&RunRule,&clone);
537         while(GeneratorGet(g,&ret)) {
538           if(en2==idx-1) {
539             if(st->en) *st->en=idx+1;
540             ret->end=idx+1;
541             FramePtrSet(RESULTS_FP,ASTSetAdd(FramePtr(RESULTS_FP),ASTClone(ret)));
542             GeneratorYield(ret);
543           } else 
544             ASTDel(ret);
545         }
546       }
547     }
548   if(!left_recursive)
549     goto fin;
550   results=FramePtr(RESULTS_FP);
551   FramePtrSet(RESULTS_FP,NULL);
552   if(attempt++) {
553 fin:
554     if(FramePtr(RESULTS_FP))
555       ASTSetDel(FramePtr(RESULTS_FP));
556     FramePtrDel(RESULTS_FP);
557     return;
558   }
559   goto again;
560 }
561 
562 U0 Chain(CRule *rule,I64 idx,ASTSet *add_to,CGrammarState *st,I64 start_woff=0,I64) {
563   CGrammarState orig,clone,clone2;
564   AST *grab,*tmp,*main=NULL,*conj2;
565   CGenerator *g;
566   I64Set *chain=rule->made_from;
567   I64 width,dummy,main_idx,depth,idx2,cnt;
568   CTrie **flat;
569 //Avoid infinitie left recursion
570   CHashGeneric *h;
571   U8 buf[STR_LEN];
572   StrPrint(buf,"PrntRule:%d,%x",st->woff,rule);
573   if(!idx)  {
574     dummy=1;
575     if(FramePtr(buf)) {
576       return;
577     }
578     FramePtrAdd(buf,1);
579   }
580   if(!st->en) st->en=&dummy;
581   if(idx>chain->cnt)
582     return;
583   if(idx==chain->cnt) {
584     if(!add_to) return;
585     if(st->en) *st->en=st->woff-start_woff;
586     for(idx=0;idx!=add_to->cnt;idx++) {
587       if(idx==rule->main_item_idx) {
588         main=add_to->body[idx];
589         main_idx=idx;
590         break;
591       }
592     } 
593 
594     if(!main) {
595       main=add_to->body[0];
596       main_idx=0;
597     }
598 
599     main=ASTClone(main);
600     main->end=st->woff-start_woff;
601     main->raw_type=main->act_as_type=rule->raw_type;
602     for(idx=0;idx!=add_to->cnt;idx++) {
603       if(main_idx!=idx)
604         AddThingToAST(ASTClone(add_to->body[idx]),main,rule->member_types->body[idx]);
605     }
606     main->prob*=rule->weight;
607     if(rule->flags_fun&&main->args)
608       main->flags|=CallExtStr(rule->flags_fun,main->args->cnt,main->args->body);
609     if(rule->validate_fun&&main->args) {
610       if(CallExtStr(rule->validate_fun,main->args->cnt,main->args->body)) {
611         FramePtrSet(RESULTS_FP,ASTSetAdd(FramePtr(RESULTS_FP),ASTClone(main)));    
612         GeneratorYield(main);
613       }
614     } else {
615       FramePtrSet(RESULTS_FP,ASTSetAdd(FramePtr(RESULTS_FP),ASTClone(main)));
616       GeneratorYield(main);
617     }
618     return;
619   }
620   MemCpy(&orig,st,sizeof CGrammarState);
621   MemCpy(&clone,st,sizeof CGrammarState);
622   clone.en=&width;
623   clone.rule=chain->body[idx];
624   g=GeneratorNewC(&RunRule,&clone);
625   while(GeneratorGet(g,&grab)) {
626     MemCpy(&clone2,&orig,sizeof CGrammarState);
627     clone2.woff+=width;
628     clone2.cnt-=width;
629     clone2.words+=width;
630     tmp=ASTSetClone(add_to);
631     tmp=ASTSetAdd(tmp,ASTClone(grab));
632     Chain(rule,idx+1,tmp,&clone2,start_woff,0);
633     if(!st->is_conj2) {
634       MemCpy(&clone2,&orig,sizeof CGrammarState);
635       clone2.woff+=width;
636       clone2.cnt-=width;
637       clone2.words+=width;
638       cnt=ASTGetTrieWords(grab,NULL);
639       flat=CAlloc(8*(cnt+1)); //cnt here is the last word_idx,add 1
640       ASTGetTrieWords(grab,flat);
641       for(idx2=0;idx2<=cnt;idx2++) {
642         if(flat[idx2]) {
643           if(flat[idx2]->flags&CONJUNCTION2) {
644             main=CAlloc(sizeof(AST),mem_task);
645             main->prob=1.;
646             main->word_idx=st->woff;
647             main->act_as_type=main->raw_type=AST_CONJUNCTION;
648             main->word=flat[idx2];
649             main->end=1;
650             main->args=I64SetAdd(main->args,main);
651             conj2=ASTSetClone(add_to);
652             conj2=ASTSetAdd(conj2,main);
653             conj2=ASTSetAdd(conj2,ASTClone(grab));
654             Chain(rule,idx+2,tmp,&clone2,start_woff,0);
655           }
656           break;
657         }
658       }
659       Free(flat);
660     }
661     ASTDel(grab);
662     ASTSetDel(tmp);
663   }
664   if(!idx)
665     FramePtrDel(buf);
666 }
667 U8 *rules=FileRead("Latin.GMR");
668 ParseRules(rules);
669 Free(rules);