/*
HEPARSE.C
Input parsing functions:
Available
CallLibraryParse
FindWord
KillWord
Match routines
AnyObjWord
AddAllObjects
AddObj
AddPossibleObject
AdvanceGrammar
DomainObj
InList
ObjWord
ObjWordType
SubtractObj
SubtractPossibleObject
TryObj
ValidObj
Parse
ParseError
RemoveWord
ResetFindObject
SeparateWords
for the Hugo Engine
Copyright (c) 1995-2006 by Kent Tessman
*/
#include "heheader.h"
/* Function prototypes: */
void AddObj(int obj);
void AddPossibleObject(int obj, char type, unsigned int w);
void AdvanceGrammar(void);
int DomainObj(int obj);
int InList(int obj);
int MatchObject(int *wordnum);
int MatchWord(int *wordnum);
int ObjWordType(int obj, unsigned int w, int type);
void ResetFindObject(void);
void SubtractObj(int obj);
void SubtractPossibleObject(int obj);
void TryObj(int obj);
int GetVal(void); /* from heexpr.c */
#define MAXOBJLIST 32
#define STARTS_AS_NUMBER(a) (((a[0]>='0' && a[0]<='9') || a[0]=='-')?1:0)
char buffer[MAXBUFFER+MAXWORDS]; /* input buffer */
char errbuf[MAXBUFFER+1]; /* last invalid input */
char line[1025]; /* line buffer */
int words = 0; /* parsed word count */
char *word[MAXWORDS+1]; /* breakdown into words */
unsigned int wd[MAXWORDS+1]; /* " " dict. entries */
unsigned int parsed_number; /* needed for numbers in input */
signed char remaining = 0; /* multiple commands in input */
char parseerr[MAXBUFFER+1]; /* for passing to RunPrint, etc. */
char parsestr[MAXBUFFER+1]; /* for passing quoted string */
char xverb; /* flag; 0 = regular verb */
char starts_with_verb; /* input line; 0 = no verb word */
unsigned int grammaraddr; /* address in grammar */
char *obj_parselist = NULL; /* objects with noun/adjective */
int domain, odomain; /* of object(s) */
int objlist[MAXOBJLIST]; /* for objects of verb */
char objcount; /* of objlist */
char parse_allflag = false; /* for "all" in MatchObject() */
struct pobject_structure
pobjlist[MAXPOBJECTS]; /* for possible objects */
int pobjcount; /* of pobjlist */
int pobj; /* last remaining suspect */
int obj_match_state; /* see MatchCommand() for details */
char objword_cache[MAXWORDS]; /* for MatchWord() xobject, etc. */
char object_is_number; /* number used in player command */
unsigned int objgrammar; /* for 2nd pass */
int objstart; /* " " " */
int objfinish; /* " " " */
char addflag; /* true if adding to objlist[] */
int speaking; /* if command is addressed to obj. */
char oops[MAXBUFFER+1]; /* illegal word */
int oopscount = 0; /* # of corrections in a row */
char parse_called_twice;
char reparse_everything;
char punc_string[64]; /* punctuation string */
char full_buffer = false;
static char recursive_call = false; /* to MatchObject() */
/* Necessary for proper disambiguation when addressing a character;
i.e., when 'held' doesn't refer to held by the player, etc.
*/
int parse_location; /* usually var[location] */
/* ADDALLOBJECTS
*/
void AddAllObjects(int loc)
{
int i;
if (loc==var[player] && domain!=loc)
return;
/* Try to add everything in the specified domain
to objlist[]
*/
for (i=Child(loc); i!=0; i=Sibling(i))
{
if (i==var[xobject]) continue;
TryObj(i);
if (domain==0)
{
if (Child(i)) AddAllObjects(i);
}
}
}
/* ADDOBJ
Adds the object <obj> to objlist[], making all related adjustments.
*/
void AddObj(int obj)
{
int i;
for (i=0; i<objcount; i++)
{
if (objlist[i]==obj)
return;
}
objlist[(int)objcount] = obj;
if (++objcount> MAXOBJLIST) objcount = MAXOBJLIST;
}
/* ADDPOSSIBLEOBJECT
Adds <obj> as a contender to the possible object list, noting that
it was referred to as either a noun or an adjective.
*/
void AddPossibleObject(int obj, char type, unsigned int w)
{
int i;
if (pobjcount==MAXPOBJECTS)
return;
for (i=0; i<pobjcount; i++)
{
/* If it is already in the list */
if (pobjlist[i].obj==obj)
{
/* Being referred to with a noun outweighs being
referred to previously with an adjective
*/
if (type==(char)noun || ObjWordType(obj, w, noun))
pobjlist[i].type = (char)noun;
return;
}
}
/* Getting this to point is presuming that we're adding an object
referred to with an adjective, but check just to be sure it isn't
also a noun for that same object
*/
if (ObjWordType(obj, w, noun)) type = (char)noun;
pobjlist[pobjcount].obj = obj;
pobjlist[pobjcount].type = type;
pobjcount++;
#ifdef DEBUG_PARSER
{
char buf[100];
sprintf(buf, "AddPossibleObject(%d:\"%s\")", obj, Name(obj));
Printout(buf);
}
#endif
}
/* ADVANCEGRAMMAR
Move the address in the grammar table past the current token.
*/
void AdvanceGrammar(void)
{
int a;
defseg = gameseg;
switch (a = Peek(grammaraddr))
{
case FORWARD_SLASH_T:
case HELD_T:
case MULTI_T:
case MULTIHELD_T:
case ANYTHING_T:
case NUMBER_T:
case PARENT_T:
case NOTHELD_T:
case MULTINOTHELD_T:
case WORD_T:
case OBJECT_T:
case XOBJECT_T:
case STRING_T:
grammaraddr++;
break;
case ASTERISK_T:
case ATTR_T:
grammaraddr += 2;
break;
case DICTENTRY_T:
case ROUTINE_T:
case OBJECTNUM_T:
grammaraddr += 3;
break;
case OPEN_BRACKET_T:
grammaraddr +=5;
break;
}
}
/* ANYOBJWORD
For when it's only necessary to know if word[wn] is an object word for
any object, not a particular object. Returns 1 for an object word or -1
for a non-object word.
*/
int AnyObjWord(int wn)
{
int i;
if (objword_cache[wn])
return objword_cache[wn];
for (i=0; i<objects; i++)
{
if (ObjWord(i, wd[wn]))
{
return (objword_cache[wn] = 1);
}
}
return (objword_cache[wn] = -1);
}
/* AVAILABLE
The non_grammar argument is true when called from a non-
grammar function such as RunEvents().
*/
int Available(int obj, char non_grammar)
{
int temp_stack_depth;
if (findobjectaddr)
{
passlocal[0] = obj;
/* if anything or (Routine) grammar */
if ((Peek(grammaraddr)==ANYTHING_T
|| (Peek(grammaraddr)==OPEN_BRACKET_T && Peek(grammaraddr+1)==ROUTINE_T))
&& non_grammar==0)
{
passlocal[1] = 0;
}
else
{
if (domain > 0)
passlocal[1] = domain;
else if (speaking && non_grammar==0)
passlocal[1] = GrandParent(speaking);
/* domain of -1 is an explicit 'parent' */
/*
else if (domain==-1)
passlocal[1] = parse_location;
*/
else
passlocal[1] = parse_location;
}
ret = 0;
PassLocals(2);
temp_stack_depth = stack_depth;
SetStackFrame(stack_depth, RUNROUTINE_BLOCK, 0, 0);
#if defined (DEBUGGER)
DebugRunRoutine((long)findobjectaddr*address_scale);
#else
RunRoutine((long)findobjectaddr*address_scale);
#endif
retflag = 0;
stack_depth = temp_stack_depth;
return ret;
}
else
return 1;
}
/* CALLLIBRARYPARSE */
void CallLibraryParse(void)
{
if (parseaddr)
{
#ifdef DEBUG_PARSER
Printout("CallLibraryParse()");
#endif
parse_called_twice = false;
SetStackFrame(RESET_STACK_DEPTH, RUNROUTINE_BLOCK, 0, 0);
ret = 0;
PassLocals(0);
#if defined (DEBUGGER)
DebugRunRoutine((long)parseaddr*address_scale);
#else
RunRoutine((long)parseaddr*address_scale);
#endif
retflag = 0;
/* Returning non-zero return calls the
engine's Parse routine again.
*/
if (ret)
{
parse_called_twice = true;
Parse();
}
#ifdef DEBUG_PARSER
if (ret)
Printout("CallLibraryParse() returned true");
else
Printout("CallLibraryParse() returned false");
#endif
}
}
/* DOMAINOBJ
Takes into account the preset domain for checking an object's
presence; <domain> is 0, -1, or an object number..
*/
int DomainObj(int obj)
{
int yes = false;
if (obj != var[actor])
{
switch (domain)
{
case 0:
case -1:
{
if (Parent(obj)==parse_location)
yes = true;
else if ((parse_allflag) && GrandParent(obj)==parse_location)
yes = true;
else
{
if (Parent(obj)==parse_location && !InList(Parent(obj)))
yes = true;
}
if (Peek(grammaraddr)==MULTINOTHELD_T)
{
if (Parent(obj)==var[actor])
yes = false;
}
break;
}
default:
{
if (Parent(obj)==domain)
yes = true;
}
}
}
return yes;
}
/* FINDWORD
Returns the dictionary address of <a>.
*/
unsigned int FindWord(char *a)
{
unsigned int ptr = 0;
int i, p, alen;
if (a[0]=='\0')
return 0;
alen = strlen(a);
defseg = dicttable;
for (i=1; i<=dictcount; i++)
{
if (alen==(p = Peek(ptr+2)) && (unsigned char)(MEM(dicttable*16L+ptr+3)-CHAR_TRANSLATION)==(unsigned char)a[0])
{
if (!strcmp(GetString(ptr + 2), a))
{
defseg = gameseg;
return ptr;
}
}
ptr += (p + 1);
}
/* As a last resort, see if the first 6 characters of the word (if it
has at least six characters) match a dictionary word:
*/
if (alen >= 6)
{
unsigned int possible = 0;
int posscount = 0;
ptr = 0;
for (i=1; i<=dictcount; i++)
{
if (alen<=(p = Peek(ptr+2)) && (unsigned char)MEM(dicttable*16L+ptr+3)-CHAR_TRANSLATION==a[0])
{
if (!strncmp(GetString(ptr + 2), a, alen))
{
/* As long as the dictionary word
doesn't contain a space */
if (!strrchr(GetString(ptr+2), ' '))
{
possible = ptr;
posscount++;
}
}
}
ptr += (p + 1);
}
if (posscount==1)
return possible;
}
defseg = gameseg;
return UNKNOWN_WORD; /* not found */
}
/* INLIST
Checks to see if <obj> is in objlist[].
*/
int InList(int obj)
{
int i;
for (i=0; i<objcount; i++)
{
if (objlist[i]==obj)
return true;
Lines 1–500 of 2874. Load more
/* HEPARSE.C Input parsing functions: Available CallLibraryParse FindWord KillWord Match routines AnyObjWord AddAllObjects AddObj AddPossibleObject AdvanceGrammar DomainObj InList ObjWord ObjWordType SubtractObj SubtractPossibleObject TryObj ValidObj Parse ParseError RemoveWord ResetFindObject SeparateWords for the Hugo Engine Copyright (c) 1995-2006 by Kent Tessman */ #include "heheader.h" /* Function prototypes: */ void AddObj(int obj); void AddPossibleObject(int obj, char type, unsigned int w); void AdvanceGrammar(void); int DomainObj(int obj); int InList(int obj); int MatchObject(int *wordnum); int MatchWord(int *wordnum); int ObjWordType(int obj, unsigned int w, int type); void ResetFindObject(void); void SubtractObj(int obj); void SubtractPossibleObject(int obj); void TryObj(int obj); int GetVal(void); /* from heexpr.c */ #define MAXOBJLIST 32 #define STARTS_AS_NUMBER(a) (((a[0]>='0' && a[0]<='9') || a[0]=='-')?1:0) char buffer[MAXBUFFER+MAXWORDS]; /* input buffer */ char errbuf[MAXBUFFER+1]; /* last invalid input */ char line[1025]; /* line buffer */ int words = 0; /* parsed word count */ char *word[MAXWORDS+1]; /* breakdown into words */ unsigned int wd[MAXWORDS+1]; /* " " dict. entries */ unsigned int parsed_number; /* needed for numbers in input */ signed char remaining = 0; /* multiple commands in input */ char parseerr[MAXBUFFER+1]; /* for passing to RunPrint, etc. */ char parsestr[MAXBUFFER+1]; /* for passing quoted string */ char xverb; /* flag; 0 = regular verb */ char starts_with_verb; /* input line; 0 = no verb word */ unsigned int grammaraddr; /* address in grammar */ char *obj_parselist = NULL; /* objects with noun/adjective */ int domain, odomain; /* of object(s) */ int objlist[MAXOBJLIST]; /* for objects of verb */ char objcount; /* of objlist */ char parse_allflag = false; /* for "all" in MatchObject() */ struct pobject_structure pobjlist[MAXPOBJECTS]; /* for possible objects */ int pobjcount; /* of pobjlist */ int pobj; /* last remaining suspect */ int obj_match_state; /* see MatchCommand() for details */ char objword_cache[MAXWORDS]; /* for MatchWord() xobject, etc. */ char object_is_number; /* number used in player command */ unsigned int objgrammar; /* for 2nd pass */ int objstart; /* " " " */ int objfinish; /* " " " */ char addflag; /* true if adding to objlist[] */ int speaking; /* if command is addressed to obj. */ char oops[MAXBUFFER+1]; /* illegal word */ int oopscount = 0; /* # of corrections in a row */ char parse_called_twice; char reparse_everything; char punc_string[64]; /* punctuation string */ char full_buffer = false; static char recursive_call = false; /* to MatchObject() */ /* Necessary for proper disambiguation when addressing a character; i.e., when 'held' doesn't refer to held by the player, etc. */ int parse_location; /* usually var[location] */ /* ADDALLOBJECTS */ void AddAllObjects(int loc) { int i; if (loc==var[player] && domain!=loc) return; /* Try to add everything in the specified domain to objlist[] */ for (i=Child(loc); i!=0; i=Sibling(i)) { if (i==var[xobject]) continue; TryObj(i); if (domain==0) { if (Child(i)) AddAllObjects(i); } } } /* ADDOBJ Adds the object <obj> to objlist[], making all related adjustments. */ void AddObj(int obj) { int i; for (i=0; i<objcount; i++) { if (objlist[i]==obj) return; } objlist[(int)objcount] = obj; if (++objcount> MAXOBJLIST) objcount = MAXOBJLIST; } /* ADDPOSSIBLEOBJECT Adds <obj> as a contender to the possible object list, noting that it was referred to as either a noun or an adjective. */ void AddPossibleObject(int obj, char type, unsigned int w) { int i; if (pobjcount==MAXPOBJECTS) return; for (i=0; i<pobjcount; i++) { /* If it is already in the list */ if (pobjlist[i].obj==obj) { /* Being referred to with a noun outweighs being referred to previously with an adjective */ if (type==(char)noun || ObjWordType(obj, w, noun)) pobjlist[i].type = (char)noun; return; } } /* Getting this to point is presuming that we're adding an object referred to with an adjective, but check just to be sure it isn't also a noun for that same object */ if (ObjWordType(obj, w, noun)) type = (char)noun; pobjlist[pobjcount].obj = obj; pobjlist[pobjcount].type = type; pobjcount++; #ifdef DEBUG_PARSER { char buf[100]; sprintf(buf, "AddPossibleObject(%d:\"%s\")", obj, Name(obj)); Printout(buf); } #endif } /* ADVANCEGRAMMAR Move the address in the grammar table past the current token. */ void AdvanceGrammar(void) { int a; defseg = gameseg; switch (a = Peek(grammaraddr)) { case FORWARD_SLASH_T: case HELD_T: case MULTI_T: case MULTIHELD_T: case ANYTHING_T: case NUMBER_T: case PARENT_T: case NOTHELD_T: case MULTINOTHELD_T: case WORD_T: case OBJECT_T: case XOBJECT_T: case STRING_T: grammaraddr++; break; case ASTERISK_T: case ATTR_T: grammaraddr += 2; break; case DICTENTRY_T: case ROUTINE_T: case OBJECTNUM_T: grammaraddr += 3; break; case OPEN_BRACKET_T: grammaraddr +=5; break; } } /* ANYOBJWORD For when it's only necessary to know if word[wn] is an object word for any object, not a particular object. Returns 1 for an object word or -1 for a non-object word. */ int AnyObjWord(int wn) { int i; if (objword_cache[wn]) return objword_cache[wn]; for (i=0; i<objects; i++) { if (ObjWord(i, wd[wn])) { return (objword_cache[wn] = 1); } } return (objword_cache[wn] = -1); } /* AVAILABLE The non_grammar argument is true when called from a non- grammar function such as RunEvents(). */ int Available(int obj, char non_grammar) { int temp_stack_depth; if (findobjectaddr) { passlocal[0] = obj; /* if anything or (Routine) grammar */ if ((Peek(grammaraddr)==ANYTHING_T || (Peek(grammaraddr)==OPEN_BRACKET_T && Peek(grammaraddr+1)==ROUTINE_T)) && non_grammar==0) { passlocal[1] = 0; } else { if (domain > 0) passlocal[1] = domain; else if (speaking && non_grammar==0) passlocal[1] = GrandParent(speaking); /* domain of -1 is an explicit 'parent' */ /* else if (domain==-1) passlocal[1] = parse_location; */ else passlocal[1] = parse_location; } ret = 0; PassLocals(2); temp_stack_depth = stack_depth; SetStackFrame(stack_depth, RUNROUTINE_BLOCK, 0, 0); #if defined (DEBUGGER) DebugRunRoutine((long)findobjectaddr*address_scale); #else RunRoutine((long)findobjectaddr*address_scale); #endif retflag = 0; stack_depth = temp_stack_depth; return ret; } else return 1; } /* CALLLIBRARYPARSE */ void CallLibraryParse(void) { if (parseaddr) { #ifdef DEBUG_PARSER Printout("CallLibraryParse()"); #endif parse_called_twice = false; SetStackFrame(RESET_STACK_DEPTH, RUNROUTINE_BLOCK, 0, 0); ret = 0; PassLocals(0); #if defined (DEBUGGER) DebugRunRoutine((long)parseaddr*address_scale); #else RunRoutine((long)parseaddr*address_scale); #endif retflag = 0; /* Returning non-zero return calls the engine's Parse routine again. */ if (ret) { parse_called_twice = true; Parse(); } #ifdef DEBUG_PARSER if (ret) Printout("CallLibraryParse() returned true"); else Printout("CallLibraryParse() returned false"); #endif } } /* DOMAINOBJ Takes into account the preset domain for checking an object's presence; <domain> is 0, -1, or an object number.. */ int DomainObj(int obj) { int yes = false; if (obj != var[actor]) { switch (domain) { case 0: case -1: { if (Parent(obj)==parse_location) yes = true; else if ((parse_allflag) && GrandParent(obj)==parse_location) yes = true; else { if (Parent(obj)==parse_location && !InList(Parent(obj))) yes = true; } if (Peek(grammaraddr)==MULTINOTHELD_T) { if (Parent(obj)==var[actor]) yes = false; } break; } default: { if (Parent(obj)==domain) yes = true; } } } return yes; } /* FINDWORD Returns the dictionary address of <a>. */ unsigned int FindWord(char *a) { unsigned int ptr = 0; int i, p, alen; if (a[0]=='\0') return 0; alen = strlen(a); defseg = dicttable; for (i=1; i<=dictcount; i++) { if (alen==(p = Peek(ptr+2)) && (unsigned char)(MEM(dicttable*16L+ptr+3)-CHAR_TRANSLATION)==(unsigned char)a[0]) { if (!strcmp(GetString(ptr + 2), a)) { defseg = gameseg; return ptr; } } ptr += (p + 1); } /* As a last resort, see if the first 6 characters of the word (if it has at least six characters) match a dictionary word: */ if (alen >= 6) { unsigned int possible = 0; int posscount = 0; ptr = 0; for (i=1; i<=dictcount; i++) { if (alen<=(p = Peek(ptr+2)) && (unsigned char)MEM(dicttable*16L+ptr+3)-CHAR_TRANSLATION==a[0]) { if (!strncmp(GetString(ptr + 2), a, alen)) { /* As long as the dictionary word doesn't contain a space */ if (!strrchr(GetString(ptr+2), ' ')) { possible = ptr; posscount++; } } } ptr += (p + 1); } if (posscount==1) return possible; } defseg = gameseg; return UNKNOWN_WORD; /* not found */ } /* INLIST Checks to see if <obj> is in objlist[]. */ int InList(int obj) { int i; for (i=0; i<objcount; i++) { if (objlist[i]==obj) return true;