C:/Users/Dennis/src/lang/Life_start/Life/life-1.02/source/parser.c

Go to the documentation of this file.
00001 /* Copyright 1991 Digital Equipment Corporation.
00002 ** Distributed only by permission.
00003 **
00004 ** Last modified on Thu Mar  3 14:16:16 MET 1994 by rmeyer
00005 **      modified on Mon Sep 27 09:37:03 1993 by Rmeyer
00006 **      modified on Tue Jun  9 14:03:14 1992 by vanroy
00007 **      modified on Thu Aug 22 18:14:49 1991 by herve
00008 *****************************************************************/
00009 /*      $Id: parser.c,v 1.2 1994/12/08 23:32:03 duchier Exp $    */
00010 
00011 #ifndef lint
00012 static char vcid[] = "$Id: parser.c,v 1.2 1994/12/08 23:32:03 duchier Exp $";
00013 #endif /* lint */
00014 
00015 #include "extern.h"
00016 #include "memory.h"
00017 #include "trees.h"
00018 #include "token.h"
00019 #include "print.h"
00020 #include "copy.h"
00021 #include "modules.h"
00022 #include "login.h"
00023 
00024 
00025 #define NOP 2000
00026   
00027 psi_term read_life_form();
00028 
00029 psi_term psi_term_stack[PARSER_STACK_SIZE];
00030 long int_stack[PARSER_STACK_SIZE];
00031 operator op_stack[PARSER_STACK_SIZE];
00032 
00033 long parse_ok;
00034 long parser_stack_index;
00035 ptr_node var_tree;
00036 long no_var_tree;
00037 
00038 /*** RICHARD Nov_4 start ***/
00039 psi_term parse_list();
00040 /*** RICHARD Nov_4 end ***/
00041 
00042 
00043 
00044 /******** BAD_PSI_TERM(t)
00045   This returns true if T is a psi_term which is not allowed to be considered
00046   as a constant by the parser.
00047 
00048   Example: "A=)+6."  would otherwise be parsed as: "=(A,+(')',6))", this was
00049                      going a bit far.
00050 */
00051 bad_psi_term(t)
00052 ptr_psi_term t;
00053 {
00054   char *s,c;
00055   long r;
00056 
00057   
00058   if(t->type==final_dot || t->type==final_question) /*  RM: Jul  9 1993  */
00059     return TRUE;
00060   
00061   s=t->type->keyword->symbol;
00062   c=s[0];
00063   r=(s[1]==0 &&
00064      (c=='(' ||
00065       c==')' ||
00066       c=='[' ||
00067       c==']' ||
00068       c=='{' ||
00069       c=='}'
00070       /* || c=='.' || c=='?'  RM: Jul  7 1993  */
00071       )
00072      );
00073   
00074   return r;
00075 }
00076 
00077 
00078    
00079 /******** SHOW(limit)
00080   This prints the parser's stack, for debugging purposes
00081   only, LIMIT marks the bottom of the current stack.
00082 */
00083 void show(limit)
00084 long limit;
00085 {
00086   long i;
00087   
00088   for (i=1;i<=parser_stack_index;i++) {
00089     if (i==limit)
00090       printf("-> ");
00091     else
00092       printf("   ");
00093     printf("%3d: ",i);
00094     switch (op_stack[i]) {
00095     case fx:
00096       printf("FX  ");
00097       break;
00098     case xfx:
00099       printf("XFX ");
00100       break;
00101     case xf:
00102       printf("XF  ");
00103       break;
00104     case nop:
00105       printf("NOP ");
00106       break;
00107     default:
00108       printf("??? ");
00109     }
00110     printf(" prec=%4d  ",int_stack[i]);
00111     display_psi_stdout(&(psi_term_stack[i]));
00112     printf("\n");
00113   }
00114   printf("\n");
00115 }
00116 
00117 
00118 
00119 /******** PUSH(tok,prec,op)
00120   Push psi_term and precedence and operator onto parser stack.
00121 */
00122 void push(tok,prec,op)
00123 psi_term tok;
00124 long prec;
00125 operator op;
00126 {
00127   if (parser_stack_index==PARSER_STACK_SIZE) {
00128     perr("*** Parser error ");
00129     psi_term_error();
00130     perr(": stack full.\n");
00131   }
00132   else {
00133     parser_stack_index++;
00134     psi_term_stack[parser_stack_index]=tok;
00135     int_stack[parser_stack_index]=prec;
00136     op_stack[parser_stack_index]=op;
00137   }
00138 }
00139 
00140 
00141 
00142 /******** POP(psi_term,op);
00143   This function pops PSI_TERM and OP off the parser stack and returns
00144   its precedence.
00145 */
00146 long pop(tok,op)
00147 ptr_psi_term tok;
00148 operator *op;
00149 {
00150   long r=0;
00151   
00152   if (parser_stack_index==0) {
00153     /*
00154       perr("*** Parser error ");
00155       psi_term_error();
00156       perr(": stack empty.\n");
00157     */
00158 
00159     (*tok)= *error_psi_term;
00160     parse_ok=FALSE;
00161   }
00162   else {
00163     (*tok)=psi_term_stack[parser_stack_index];
00164     (*op)=op_stack[parser_stack_index];
00165     r=int_stack[parser_stack_index];
00166     parser_stack_index--;
00167   }
00168   
00169   return r;
00170 }
00171 
00172 
00173 
00174 /******** LOOK()
00175   This function returns the precedence of the stack top.
00176 */
00177 long look()
00178 {
00179   return int_stack[parser_stack_index];
00180 }
00181 
00182 
00183 
00184 /******** PRECEDENCE(tok,typ)
00185   This function returns the precedence of
00186   TOK if it is an operator of type TYP where TYP is FX XFX XF etc...
00187   Note that this allows both a binary and unary minus.
00188   The result is NOP if tok is not an operator.
00189 */
00190 long precedence(tok,typ)
00191 psi_term tok;
00192 operator typ;
00193 {
00194   long r=NOP;
00195   ptr_operator_data o;
00196 
00197   o=tok.type->op_data;
00198   while(o && r==NOP) {
00199     if(typ==o->type)
00200       r=o->precedence;
00201     else
00202       o=o->next;
00203   }
00204   
00205   return r;
00206 }
00207 
00208 
00209 
00210 /******** STACK_COPY_PSI_TERM(tok)
00211   Return the address of a copy of TOK on the STACK.
00212   All psi_terms read in by the parser are read into the stack.
00213 */
00214 ptr_psi_term stack_copy_psi_term(t)
00215 psi_term t;
00216 {
00217   ptr_psi_term p;
00218   
00219   p=STACK_ALLOC(psi_term);
00220   (*p)=t;
00221 #ifdef TS
00222   p->time_stamp=global_time_stamp; /* 9.6 */
00223 #endif
00224   
00225   return p;
00226 }
00227 
00228 
00229 
00230 /******** HEAP_COPY_PSI_TERM(tok)
00231   Return the address of a copy of TOK on the HEAP.
00232 */
00233 ptr_psi_term heap_copy_psi_term(t)
00234 psi_term t;
00235 {
00236   ptr_psi_term p;
00237   
00238   p=HEAP_ALLOC(psi_term);
00239   (*p)=t;
00240 #ifdef TS
00241   p->time_stamp=global_time_stamp; /* 9.6 */
00242 #endif
00243   
00244   return p;
00245 }
00246 
00247 
00248 
00249 
00250 /******** FEATURE_INSERT(keystr,tree,psi)
00251   Insert the psi_term psi into the attribute tree.
00252   If the feature already exists, create a call to the unification
00253   function.
00254 */
00255 feature_insert(keystr,tree,psi)
00256 char *keystr;
00257 ptr_node *tree;
00258 ptr_psi_term psi;
00259 {
00260   ptr_node loc;
00261   /* ptr_psi_term stk_psi=stack_copy_psi_term(*psi); 19.8 */
00262 
00263   if (loc=find(featcmp,keystr,*tree)) {
00264     /* Give an error message if there is a duplicate feature: */
00265     Syntaxerrorline("duplicate feature %s (%E)\n",keystr);
00266   }
00267   else {
00268     /* If the feature does not exist, insert it. */
00269     ptr_psi_term stk_psi=stack_copy_psi_term(*psi); /* 19.8 */
00270     stack_insert_copystr(keystr,tree,(GENERIC)stk_psi); /* 10.8 */
00271   }
00272 }
00273 
00274 
00275 
00276 
00277 /*** RM 9 Dec 1992 START ***/
00278 
00279 
00280 /******** LIST_NIL(type)
00281   Returns the atom NIL to mark the end of a list.
00282   */
00283 
00284 psi_term list_nil(type) /*  RM: Feb  1 1993  */
00285 
00286      ptr_definition type;
00287 {
00288   psi_term nihil;
00289 
00290   if(type==disjunction) /*  RM: Feb  1 1993  */
00291     nihil.type=disj_nil;
00292   else
00293     nihil.type=nil;
00294   
00295   nihil.status=0;
00296   nihil.flags=FALSE; /* 14.9 */
00297   nihil.attr_list=NULL;
00298   nihil.resid=NULL;
00299   nihil.value=NULL;
00300   nihil.coref=NULL;
00301 
00302   return nihil;
00303 }
00304 
00305 
00306 
00307 /******** PARSE_LIST(type,end,separator)
00308 
00309   This function provides a replacement for the function 'read_list'. It does
00310   not create the old (slightly more compact and a lot more complicated) list
00311   structure, but instead creates a generic psi-term with 2 features. The list
00312   is terminated by the atom 'nil'.
00313 
00314   Example:
00315 
00316         [a,b,c|d] -> cons(a,cons(b,cons(c,d))).
00317         [] -> nil
00318         {a;b;c} -> disj(a,disj(b,disj(c,{}))).
00319         {} -> {} = *bottom*
00320 
00321         
00322   Example:
00323   TYP=disjunction,
00324   END="}",
00325   SEPARATOR=";" will read in disjunctions.
00326 
00327   Example:
00328   TYP=list,
00329   END="]",
00330   SEPARATOR="," will read lists such as [1,2,a,b,c|d]
00331   */
00332 
00333 psi_term parse_list(typ,e,s)
00334      ptr_definition typ;
00335      char e,s;
00336 
00337 {
00338   ptr_psi_term car=NULL;
00339   ptr_psi_term cdr=NULL;
00340   psi_term result;
00341   psi_term t;
00342   char a;
00343 
00344 
00345 
00346   result=list_nil(typ); /*  RM: Feb  1 1993  */
00347   
00348   if (parse_ok) {
00349 
00350     /* Character used for building cons pairs */
00351     a='|'; /*  RM: Jan 11 1993  */
00352     
00353 
00354     read_token(&t);
00355 
00356     if(!equ_tokc(t,e)) {
00357 
00358       /* Read the CAR of the list */
00359       put_back_token(t);
00360       car=stack_copy_psi_term(read_life_form(s,a));
00361 
00362       /* Read the CDR of the list */
00363       read_token(&t);
00364       if(equ_tokch(t,s))
00365         cdr=stack_copy_psi_term(parse_list(typ,e,s));
00366       else if(equ_tokch(t,e))
00367         cdr=stack_copy_psi_term(list_nil(typ));
00368       else if(equ_tokch(t,'|')) {
00369         cdr=stack_copy_psi_term(read_life_form(e,0));
00370         read_token(&t);
00371         if(!equ_tokch(t,e)) {
00372           if (stringparse) parse_ok=FALSE;
00373           else {
00374             perr("*** Syntax error ");psi_term_error();
00375             perr(": bad symbol for end of list '");
00376             display_psi_stderr(&t);
00377             perr("'.\n");
00378             put_back_token(t);
00379           }
00380         }
00381       }
00382       else 
00383         if (stringparse) parse_ok=FALSE;
00384         else {
00385           perr("*** Syntax error ");psi_term_error();
00386           perr(": bad symbol in list '");
00387           display_psi_stderr(&t);
00388           perr("'.\n");
00389           put_back_token(t);
00390         }
00391 
00392       result.type=typ;
00393       if(car)
00394         stack_insert(featcmp,one,&(result.attr_list),car);
00395       if(cdr)
00396         stack_insert(featcmp,two,&(result.attr_list),cdr);
00397     }
00398   }
00399   
00400   return result;
00401 }
00402 /*** RM 9 Dec 1992 END ***/
00403 
00404 
00405 
00406 
00407 /******** READ_PSI_TERM()
00408   This reads in a complex object from the input
00409   stream, that is, a whole psi-term.
00410 
00411   Examples:
00412 
00413   [A,B,C]
00414 
00415   {0;1;2+A}
00416 
00417   <a,b,c> death(victim => V,murderer => M)
00418 
00419   which(x,y,z)
00420 
00421   A:g(f)
00422 
00423   I have allowed mixing labelled with unlabelled attributes.
00424 
00425   Example:
00426   
00427   f(x=>A,B,y=>K,"hklk",D) is parsed as f(1=>B,2=>"hklk",3=>D,x=>A,y=>K).
00428 */
00429 psi_term read_psi_term()
00430 {
00431   psi_term t,t2,t3;
00432   char s[10];
00433   long count=0,f=TRUE,f2,v;
00434   ptr_psi_term module;
00435 
00436   
00437   if(parse_ok) {
00438     
00439     read_token(&t);
00440     
00441     if(equ_tokch(t,'['))
00442       t=parse_list(alist,']',','); /*** RICHARD Nov_4 ***/
00443     else
00444       if(equ_tokch(t,'{')) 
00445         t=parse_list(disjunction,'}',';'); /*** RICHARD Nov_4 ***/
00446 
00447       /* The syntax <a,b,c> for conjunctions has been abandoned.
00448         else
00449         if(equ_tokch(t,'<'))
00450         t=parse_list(conjunction,'>',',');
00451         */
00452   
00453     if(parse_ok 
00454        && t.type!=eof
00455        && !bad_psi_term(&t)
00456        /* && (precedence(t,fx)==NOP)
00457           && (precedence(t,fy)==NOP) */
00458        ) {
00459       read_token(&t2);
00460       if(equ_tokch(t2,'(')) {
00461         
00462         do {
00463           
00464           f2=TRUE;
00465           read_token(&t2);
00466           
00467           if(wl_const(t2) && !bad_psi_term(&t2)) {
00468             read_token(&t3);
00469             if(equ_tok(t3,"=>")) {
00470               t3=read_life_form(',',')');
00471               
00472               if(t2.type->keyword->private_feature) /*  RM: Mar 11 1993  */
00473                 feature_insert(t2.type->keyword->combined_name,
00474                                /*  RM: Jan 13 1993  */
00475                                &(t.attr_list),
00476                                &t3);
00477               else
00478                 feature_insert(t2.type->keyword->symbol,
00479                                /*  RM: Jan 13 1993  */
00480                                &(t.attr_list),
00481                                &t3);
00482               
00483               f2=FALSE;
00484             }
00485             else 
00486               put_back_token(t3);
00487           }
00488           
00489           if(parse_ok && equal_types(t2.type,integer)) {
00490             read_token(&t3);
00491             if(equ_tok(t3,"=>")) {
00492               t3=read_life_form(',',')');
00493               v= *(REAL *)t2.value;
00494               sprintf(s,"%ld",v,0);
00495               feature_insert(s,&(t.attr_list),&t3);
00496               f2=FALSE;
00497             }
00498             else 
00499               put_back_token(t3);
00500           }
00501           
00502           if(f2) {
00503             put_back_token(t2);
00504             t2=read_life_form(',',')');
00505             ++count;
00506             sprintf(s,"%ld",count,0);
00507             feature_insert(s,&(t.attr_list),&t2);
00508           }
00509           
00510           read_token(&t2);
00511           
00512           if(equ_tokch(t2,')'))
00513             f=FALSE;
00514           else
00515             if(!equ_tokch(t2,',')) {
00516               if (stringparse) parse_ok=FALSE;
00517               else {
00518                 /*
00519                   perr("*** Syntax error ");psi_term_error();
00520                   perr(": ',' expected in argument list.\n");
00521                   */
00522 
00523                 /*  RM: Feb  1 1993  */
00524                 Syntaxerrorline("',' expected in argument list (%E)\n");
00525 
00526                 f=FALSE;
00527               }
00528             }
00529           
00530         } while(f && parse_ok);
00531       }
00532       else
00533         put_back_token(t2);
00534     }
00535   }
00536   else
00537     t= *error_psi_term;
00538 
00539   if(t.type==variable && t.attr_list) {
00540     t2=t;
00541     t.type=apply;
00542     t.value=NULL;
00543     t.coref=NULL;
00544     t.resid=NULL;
00545     stack_insert(featcmp,functor->keyword->symbol,
00546                  &(t.attr_list),
00547                  stack_copy_psi_term(t2));
00548   }
00549 
00550 
00551   /*  RM: Mar 12 1993  Nasty hack for Bruno's features in modules */
00552   if((t.type==add_module1 || t.type==add_module2 || t.type==add_module3) &&
00553      !find(featcmp,two,t.attr_list)) {
00554 
00555     module=stack_psi_term(4);
00556     module->type=quoted_string;
00557     module->value=(GENERIC)heap_copy_string(current_module->module_name);
00558     
00559     stack_insert(featcmp,two,&(t.attr_list),module);
00560   }
00561   
00562   return t;
00563 }
00564 
00565 
00566 
00567 /******** MAKE_LIFE_FORM(tok,arg1,arg2)
00568   This routine inserts ARG1 and ARG2 as the first and second attributes of
00569   psi_term TOK, thus creating the term TOK(1=>arg1,2=>arg2).
00570 
00571   If TOK is ':' then a conjunction is created if necessary.
00572   Example:
00573   a:V:b:5:long => V: <a,b,5,int> (= conjunction list).
00574 */
00575 psi_term make_life_form(tok,arg1,arg2)
00576 ptr_psi_term tok,arg1,arg2;
00577 {  
00578   ptr_list l;
00579   ptr_psi_term a1,a2;
00580 
00581   deref_ptr(tok);
00582   tok->attr_list=NULL;
00583   tok->resid=NULL;
00584 
00585     
00586   /* Here beginneth a terrible FIX,
00587      I will have to rewrite the tokeniser and the parser to handle
00588      POINTERS to psi-terms instead of PSI_TERMS !!!
00589      */
00590   
00591   a1=arg1;
00592   a2=arg2;
00593 
00594   if(a1)
00595     deref_ptr(a1);
00596   if(a2)
00597     deref_ptr(a2);
00598   
00599   /* End of extremely ugly fix. */
00600   
00601   if (/* UNI FALSE */ equ_tokch((*tok),':') && arg1 && arg2) {
00602     
00603     if(a1!=a2) {
00604       if(a1->type==top && 
00605          !a1->attr_list &&
00606          !a1->resid) {
00607         if(a1!=arg1)
00608           /* push_ptr_value(psi_term_ptr,&(a1->coref)); 9.6 */
00609           push_psi_ptr_value(a1,&(a1->coref));
00610         a1->coref=stack_copy_psi_term(*arg2);
00611         tok=arg1;
00612       }
00613       else
00614         if(a2->type==top && 
00615            !a2->attr_list &&
00616            !a2->resid) {
00617           if(a2!=arg2)
00618             /* push_ptr_value(psi_term_ptr,&(a2->coref)); 9.6 */
00619             push_psi_ptr_value(a2,&(a2->coref));
00620           a2->coref=stack_copy_psi_term(*arg1);
00621           tok=arg2;
00622         }
00623         else { /*  RM: Feb 22 1993  Now reports an error */
00624           Syntaxerrorline("':' occurs where '&' required (%E)\n");
00625           *tok= *error_psi_term;
00626           /* make_unify_pair(tok,arg1,arg2); Old code */
00627         }
00628     }
00629     else
00630       tok=arg1;
00631   }
00632   else {
00633 
00634     /*  RM: Jun 21 1993  */
00635     /* And now for another nasty hack: reading negative numbers */
00636     if(tok->type==minus_symbol &&
00637        a1 &&
00638        !a2 &&
00639        a1->value &&
00640        (a1->type==integer || a1->type==real))  {
00641       
00642       tok->type=a1->type;
00643       tok->value=(GENERIC)heap_alloc(sizeof(REAL));
00644       *(REAL *)tok->value = - *(REAL *)a1->value;
00645       
00646       return *tok;
00647     }
00648     /* End of other nasty hack */
00649     
00650     stack_insert(featcmp,one,&(tok->attr_list),stack_copy_psi_term(*arg1));
00651     if (arg2)
00652       stack_insert(featcmp,two,&(tok->attr_list),stack_copy_psi_term(*arg2));
00653   }
00654   
00655   return *tok;
00656 }
00657 
00658 
00659 
00660 /******** CRUNCH(prec,limit)
00661   Crunch up = work out the arguments of anything on the stack whose precedence
00662   is <= PREC, and replace it with the corresponding psi-term. Do not go any
00663   further than LIMIT which is the end of the current expression.
00664 */
00665 void crunch(prec,limit)
00666 long prec;
00667 long limit;
00668 {
00669   psi_term t,t1,t2,t3;
00670   operator op1,op2,op3;
00671   
00672   if(parse_ok && prec>=look() && parser_stack_index>limit) {
00673     
00674     pop(&t1,&op1);
00675     
00676     switch(op1) {
00677       
00678     case nop:
00679       pop(&t2,&op2);
00680       if(op2==fx)
00681         t=make_life_form(&t2,&t1,NULL);
00682       else
00683         if(op2==xfx) {
00684           pop(&t3,&op3);
00685           if(op3==nop)
00686             t=make_life_form(&t2,&t3,&t1);
00687           else {
00688             printf("*** Parser: ooops, NOP expected.\n");
00689             parse_ok=FALSE;
00690             t= *error_psi_term;
00691           }
00692         }
00693       break;
00694       
00695     case xf:
00696       pop(&t2,&op2);
00697       if(op2==nop)
00698         t=make_life_form(&t1,&t2,NULL);
00699       else {
00700         printf("*** Parser: ugh, NOP expected.\n");
00701         t= *error_psi_term;
00702         parse_ok=FALSE;
00703       }
00704       break;
00705       
00706     default:
00707       printf("*** Parser: yuck, weirdo operator.\n");
00708     }
00709     
00710     push(t,look(),nop);
00711     
00712     crunch(prec,limit);
00713   }
00714 }
00715 
00716 
00717 
00718 /******** READ_LIFE_FORM(str1,str2)
00719   This reads in one life-form from the input stream which finishes with
00720   the psi_term whose name is STR1 or STR2, typically if we're reading a list
00721   [A,4*5,b-4!] then STR1="," and STR2="|" . It would be incorrect if "," were
00722   taken as an operator.
00723 
00724   This routine implements the two state expression parser as described in the
00725   implementation guide. It deals with all the various types of operators,
00726   precedence is dealt with by the CRUNCH function. Each time an opening
00727   parenthesis is encountered a new expression is started.
00728 */
00729 psi_term read_life_form(ch1,ch2)
00730 char ch1,ch2;
00731 {
00732   psi_term t,t2;
00733   long limit,pr_op,pr_1,pr_2,start=0;
00734   long fin=FALSE;
00735   long state=0;
00736   long prec=0;
00737   
00738   operator op;
00739   
00740   limit=parser_stack_index+1;
00741   
00742   if(parse_ok)
00743     do {
00744       if(state)
00745         read_token(&t);
00746       else
00747         t=read_psi_term();
00748       
00749       if(!start)
00750         start=line_count;
00751       
00752       if(!fin)
00753         if(state) {
00754           if(equ_tokc(t,ch1) || equ_tokc(t,ch2)) {
00755             fin=TRUE;
00756             put_back_token(t);
00757           }
00758           else {
00759             
00760             pr_op=precedence(t,xf);
00761             pr_1=pr_op-1;
00762             
00763             if(pr_op==NOP) {
00764               pr_op=precedence(t,yf);
00765               pr_1=pr_op;
00766             }
00767             
00768             if(pr_op==NOP) {
00769               
00770               pr_op=precedence(t,xfx);
00771               pr_1=pr_op-1;
00772               pr_2=pr_op-1;
00773               
00774               if(pr_op==NOP) {
00775                 pr_op=precedence(t,xfy);
00776                 pr_1=pr_op-1;
00777                 pr_2=pr_op;
00778               }
00779               
00780               if(pr_op==NOP) {
00781                 pr_op=precedence(t,yfx);
00782                 pr_1=pr_op;
00783                 pr_2=pr_op-1;
00784               }
00785               
00786               /* if(pr_op==NOP) {
00787                 pr_op=precedence(t,yfy);
00788                 pr_1=pr_op;
00789                 pr_2=pr_op-1;
00790               }
00791               */
00792               
00793               if(pr_op==NOP) {
00794                 fin=TRUE;
00795                 put_back_token(t);
00796               }
00797               else
00798                 {
00799                   crunch(pr_1,limit);
00800                   push(t,pr_2,xfx);
00801                   prec=pr_2;
00802                   state=0;
00803                 }
00804             }
00805             else {
00806               crunch(pr_1,limit);
00807               push(t,pr_1,xf);
00808               prec=pr_1;
00809             }
00810           }
00811         }
00812         else {
00813 
00814           if(t.attr_list)
00815             pr_op=NOP;
00816           else {
00817             pr_op=precedence(t,fx);
00818             pr_2=pr_op-1;
00819                   
00820             if(pr_op==NOP) {
00821               pr_op=precedence(t,fy);
00822               pr_2=pr_op;
00823             }
00824           }
00825 
00826           if(pr_op==NOP) {
00827             if(equ_tokch(t,'(')) {
00828               t2=read_life_form(')',0);
00829               if(parse_ok) {
00830                 push(t2,prec,nop);
00831                 read_token(&t2);
00832                 if(!equ_tokch(t2,')')) {
00833                   if (stringparse) parse_ok=FALSE;
00834                   else {
00835                     /*
00836                       perr("*** Syntax error ");psi_term_error();
00837                       perr(": ')' missing.\n");
00838                       */
00839 
00840                     /*  RM: Feb  1 1993  */
00841                     Syntaxerrorline("')' missing (%E)\n");
00842 
00843                     put_back_token(t2);
00844                   }
00845                 }
00846                 state=1;
00847               }
00848             }
00849             else 
00850               if(bad_psi_term(&t)) {
00851                 put_back_token(t);
00852                 /* psi_term_error(); */
00853                 fin=TRUE;
00854               }
00855               else {
00856                 push(t,prec,nop);
00857                 state=1;
00858               }
00859           }
00860           else {
00861             push(t,pr_2,fx);
00862             prec=pr_2;
00863           }
00864           
00865         }
00866       
00867     } while (!fin && parse_ok);
00868   
00869   if (state)
00870     crunch(MAX_PRECEDENCE,limit);
00871   
00872   if (parse_ok && parser_stack_index!=limit) {
00873     if (stringparse) parse_ok=FALSE;
00874     else {
00875       /*
00876         perr("*** Syntax error ");psi_term_error();
00877         perr(": bad expression.\n");
00878         */
00879       
00880       /*  RM: Feb  1 1993  */
00881       Syntaxerrorline("bad expression (%E)\n");
00882     }
00883   }
00884   else
00885     pop(&t,&op);
00886   
00887   if (!parse_ok)
00888     t= *error_psi_term;
00889 
00890   parser_stack_index=limit-1;
00891   
00892   return t;
00893 }
00894 
00895 
00896 
00897 /******** PARSE(is_it_a_clause)
00898   This returns one clause or query from the input stream.
00899   It also indicates the type psi-term read, that is whether it was a clause
00900   or a query in the IS_IT_A_CLAUSE variable. This is the top level of the
00901   parser.
00902 
00903   The whole parser is, rather like the psi_termiser, not too well written.
00904   It handles psi_terms rather than pointers which causes a lot of messy code
00905   and is somewhat slower.
00906 */
00907 psi_term parse(q)
00908 long *q;
00909 {
00910   psi_term s,t,u;
00911   long c;
00912 
00913   parser_stack_index=0;
00914   parse_ok=TRUE;
00915 
00916   /*s=read_life_form('.','?');*/
00917   s=read_life_form(0,0);
00918 
00919   if (parse_ok) {
00920     if (s.type!=eof) {
00921       read_token(&t);
00922       
00923       /*
00924       if (equ_tokch(t,'?'))
00925         *q=QUERY;
00926       else if (equ_tokch(t,'.'))
00927         *q=FACT;
00928         */
00929 
00930       /*  RM: Jul  7 1993  */
00931       if (t.type==final_question)
00932         *q=QUERY;
00933       else if (t.type==final_dot)
00934         *q=FACT;
00935       else {
00936         if (stringparse) parse_ok=FALSE;
00937         else {
00938           /*
00939           perr("*** Syntax error ");psi_term_error();perr(": ");
00940           display_psi_stderr(&t);
00941           perr(".\n");
00942           */
00943 
00944           /*  RM: Feb  1 1993  */
00945           Syntaxerrorline("'%P' (%E)\n",&t);
00946 
00947         }
00948         *q=ERROR;
00949       }
00950     }
00951   }
00952 
00953       
00954   if (!parse_ok) {
00955 
00956     while (saved_psi_term!=NULL) read_token(&u);
00957 
00958     prompt="error>";
00959     while((c=read_char()) && c!=EOF && c!='.' && c!='?' && c!=EOLN) {}
00960 
00961     *q=ERROR;
00962   }
00963   else if (saved_char)
00964     do {
00965       c=read_char();
00966       if (c==EOLN)
00967         c=0;
00968       else if (c<0 || c>32) {
00969         put_back_char(c);
00970         c=0;
00971       }
00972     } while(c && c!=EOF);
00973 
00974   /* Make sure arguments of nonstrict terms are marked quoted. */
00975   if (parse_ok) mark_nonstrict(&s); /* 25.8 */
00976 
00977   /* mark_eval(&s); 24.8 XXX */
00978 
00979   /* Mark all the psi-terms corresponding to variables in the var_tree as    */
00980   /* quoted.  This is needed for correct parsing of inputs; otherwise vars   */
00981   /* that occur in an increment of a query are marked to be evaluated again! */
00982   /* mark_quote_tree(var_tree); 24.8 XXX */
00983 
00984   
00985   return s;
00986 }

Generated on Sat Jan 26 08:48:07 2008 for WildLife by  doxygen 1.5.4