/****************************************************************************\ * * * C R E A T O R O F L E G E N D S * * (AberMud Version 5) * * * * The Creator Of Legends System is (C) Copyright 1989 Alan Cox, All Rights * * Reserved. * * * \****************************************************************************/ /* * Command Parsing Logic * * 1.00 AGC Created File * 1.01 AGC Added ordinates * 1.02 AGC Minor Fixes * 1.03 AGC Fixes (incomplete) for noun,prep,verb of same text * 1.04 AGC Sorted word list * 1.05 AGC Knows / " ' : are one character tokens * 1.06 AGC Buffers fixed to right size, dunno how it ever used to work.... * 1.07 AGC Strict ANSIfication */ #include "System.h" Module "Parser"; Version "1.07"; Author "----*(A)"; /* * The parser breaks the user input into words in the form requested * by the user. It can * Break a new word {skipping noise words} * Decode a word * Decode an {adjective}/noun pair {skipping unknowns} * Get the rest of the input (through phrases) * Skip to next phrase [,;. AND THEN define phrases] * */ WLIST *WordList=NULL; PCONTEXT ParserData[MAXUSER]; short ParsingPersona; /* * Context Managers */ void SetPersona(int x) { ParsingPersona=x; } PCONTEXT *GetContext(short u) { if(u<0) return(NULL); return(&ParserData[u]); } void ProLoad(short prep, register int *ad, register int *no) { switch(prep) { case 1: *ad=Me()->it_Adjective; *no=Me()->it_Noun; break; case 2: *ad=ParserData[ParsingPersona].pa_It[0]; *no=ParserData[ParsingPersona].pa_It[1]; break; case 3: *ad=ParserData[ParsingPersona].pa_Them[0]; *no=ParserData[ParsingPersona].pa_Them[1]; break; case 4: *ad=ParserData[ParsingPersona].pa_Him[0]; *no=ParserData[ParsingPersona].pa_Him[1]; break; case 5: *ad=ParserData[ParsingPersona].pa_Her[0]; *no=ParserData[ParsingPersona].pa_Her[1]; break; case 6: *ad=ParserData[ParsingPersona].pa_There[0]; *no=ParserData[ParsingPersona].pa_There[1]; break; default: *ad=-1; *no=-1; break; } } void SetItData(short u, ITEM *x, short a, short n) { if(u==-1) u=ParsingPersona; if((IsPlayer(x))&&(x!=Me())) { ParserData[u].pa_Them[0]=a; ParserData[u].pa_Them[1]=n; if(PlayerOf(x)->pl_Flags&PL_MALE) { ParserData[u].pa_Him[0]=a; ParserData[u].pa_Him[1]=n; return; } if(PlayerOf(x)->pl_Flags&PL_FEMALE) { ParserData[u].pa_Her[0]=a; ParserData[u].pa_Her[1]=n; return; } ParserData[u].pa_It[0]=a; ParserData[u].pa_It[1]=n; return; } if(IsObject(x)) { if((ObjectOf(x)->ob_Flags&OB_NOIT)==0) { ParserData[u].pa_It[0]=a; ParserData[u].pa_It[1]=n; } } if(IsRoom(x)) { ParserData[u].pa_There[0]=a; ParserData[u].pa_There[1]=n; } } /* * Word Managers */ void AddWord(char *name, short code, short type) { register WLIST *a=Allocate(WLIST); register WLIST *w,*p; a->wd_Text=malloc(strlen(name)+1); if(a->wd_Text==NULL) Error("Out Of Memory"); strcpy(a->wd_Text,name); a->wd_Code=code; a->wd_Type=type; /* * Sort word list.. mostly for speed of AddVerb etc */ p=NULL; w=WordList; while(w!=NULL) { if(w->wd_Code>code) break; p=w; w=w->wd_Next; } if(p==NULL) { a->wd_Next=WordList; WordList=a; } else { p->wd_Next=a; a->wd_Next=w; } } int FreeWord(char *name, register short type) { register WLIST *a,*b; a=WordList; b=NULL; while(a) { if((a->wd_Type==type)&&(stricmp(a->wd_Text,name)==0)) { if(b==NULL) { WordList=a->wd_Next; free((char *)a); } else { b->wd_Next=a->wd_Next; free((char *)a); } return(0); } b=a; a=a->wd_Next; } return(-1); } char *FindWText(register int num, register short type) { register WLIST *a; a=WordList; if(num==-1) return("ANY"); if(num==-2) return("NONE"); while(a) { if((a->wd_Type==type)&&(a->wd_Code==num)) { return(a->wd_Text); } a=a->wd_Next; } return("<UNSET>"); } /* * We work on two word lists Words holds all the words * Noise holds specific words to skip */ WLIST *FindInList(register WLIST *list, register char *word, register short type) { if(list==NULL) return(NULL); /* NULL is handle for null list */ while(list) { if(((type==0)||(list->wd_Type==type))&&(stricmp(list->wd_Text,word)==0)) { return(list); } list=list->wd_Next;; } return(NULL); } char *BreakWord(register char *iptr, register char *fbuf, WLIST *skiplist, short skiptype) /* returns next iptr wbuf should be 128 bytes */ { if((*iptr=='.')||(*iptr==';')||(*iptr==',')) return(NULL); /* Phrase end */ if((*iptr==':')||(*iptr=='"')||(*iptr=='/')||(*iptr=='\'')) { *fbuf++=*iptr++; *fbuf=0; return(iptr); } l1: while(*iptr) if(isspace(*iptr)) iptr++; else break; if(!*iptr) return(NULL); /* List expired */ if((*iptr=='.')||(*iptr==';')||(*iptr==',')) return(NULL); /* Phrase end */ while(*iptr) if((!isspace(*iptr))&&(*iptr!=',')&&(*iptr!=';')&&(*iptr!='.')) *fbuf++=*iptr++; else break; *fbuf=0; if(stricmp(fbuf,"AND")==0) return(NULL); if(stricmp(fbuf,"THEN")==0) return(NULL); if(FindInList(skiplist,fbuf,skiptype)) goto l1; return(iptr); } char *GetRestOfInput(register char *iptr, char *bfr) { while(*iptr) if(isspace(*iptr)) iptr++; else break; strcpy(bfr,iptr); iptr+=strlen(iptr); return(iptr); } char *FNxPhrs(register char *iptr) { static char fb[512]; register char *fbuf=fb; if(iptr==NULL) return(NULL); l1: while(*iptr) if(isspace(*iptr)) iptr++; else break; if(!*iptr) return(NULL); /* List expired */ if((*iptr=='.')||(*iptr==';')||(*iptr==',')) { iptr++; return(iptr); /* Phrase end */ } while(*iptr) if(!isspace(*iptr)) *fbuf++=*iptr++; else break; *fbuf=0; if(stricmp(fb,"AND")==0) return(iptr); if(stricmp(fb,"THEN")==0) return(iptr); goto l1; } /* * Globals For Normal Parsing */ char *WordPtr; char WordBuffer[514]; WLIST *GetWord(void) { WLIST *a; WordPtr=BreakWord(WordPtr,WordBuffer,WordList,WD_NOISE); if(!WordPtr) return((WLIST *)-1); a=FindInList(WordList,WordBuffer,0); return(a); } int GetOrd(void) { char *WRem=WordPtr; WLIST *a=GetWord(); if(a==NULL) { WordPtr=WRem; return(1); } if(a==(WLIST *)-1) { WordPtr=WRem; return(1); } if(a->wd_Type!=WD_ORDIN) { WordPtr=WRem; return(1); } return(a->wd_Code); } char *GetParsedWord(void) { return(WordPtr=BreakWord(WordPtr,WordBuffer,WordList,WD_NOISE)); } void GetAll(void) { WordPtr=GetRestOfInput(WordPtr,WordBuffer); } int GetNumber(void) { int a; WordPtr=BreakWord(WordPtr,WordBuffer,WordList,WD_NOISE); if(!WordPtr) return(-1); if(sscanf(WordBuffer,"%d",&a)==0) return(-1); return(a); } int GetThing(int *ad, int *no) { char *a=WordPtr; /* Save of */ WLIST *b; WLIST *t; int posnoun=-1; char *backptr; *ad=-1; l1: backptr=WordPtr; b=GetWord(); if(b==(WLIST *)-1) { WordPtr=a; return(-1); } if(b==NULL) goto l1; /* Dud word */ if(FindInList(WordList,WordBuffer,WD_PREP)&& FindInList(WordList,WordBuffer,WD_NOUN)) { if(GetWord()==(WLIST *)-1) { WordPtr=backptr; b=GetWord(); /* Use noun */ } else { WordPtr=backptr; *no= -1; return(-1); } } t=FindInList(WordList,WordBuffer,WD_PRONOUN); if(t) { ProLoad(t->wd_Code,ad,no); return(0); } if(FindInList(WordList,WordBuffer,WD_ADJ)) { t=FindInList(WordList,WordBuffer,WD_ADJ); b=t; } else goto l2; t=FindInList(WordList,WordBuffer,WD_NOUN); if(t) posnoun=t->wd_Code; /* It might still be noun */ if(b) *ad=b->wd_Code; l3: a=WordPtr; b=GetWord(); if(b==(WLIST *)-1) { WordPtr=a; if(posnoun) { *ad=-1; *no=posnoun; return(0); } return(-1); } if(b==NULL) goto l3; /* Dud word */ l2: if(!(b=FindInList(WordList,WordBuffer,WD_NOUN))) { WordPtr=a; if(posnoun!=-1) { *no=posnoun; /* Adj/Noun clasher - noun form */ *ad=-1; return(0); } if(!b) return(-1); } *no=b->wd_Code; return(0); } void SkipPrep(void) /* Skip any preposition which is next word */ { char *a=WordPtr; WLIST *b=GetWord(); if(b==(WLIST *)-1) { WordPtr=a; return; } if(b==NULL) { WordPtr=a; return; } if(b->wd_Type!=WD_PREP) { WordPtr=a; return; } } int GetPrep(void) { char *a=WordPtr; register WLIST *b; l1: b=GetWord(); if(b==(WLIST *)-1) { WordPtr=a; return(-1); } if(b==NULL) goto l1; /* Dud word */ if(b->wd_Type!=WD_PREP) { b=FindInList(WordList,WordBuffer,WD_PREP); if(!b) { WordPtr=a; return(-1); } } return(b->wd_Code); } int GetVerb(void) { char *a=WordPtr; register WLIST *b; b=GetWord(); if(b==(WLIST *)-1) { WordPtr=a; return(-1); } if(b==NULL) { WordPtr=a; return(-1); } if(b->wd_Type!=WD_VERB) { b=FindInList(WordList,WordBuffer,WD_VERB); if(!b) { WordPtr=a; return(-1); } } return(b->wd_Code); } char *NextPhrase(void) { WordPtr=FNxPhrs(WordPtr); return(WordPtr); }