home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
draco
/
draco-1.ark
/
QPARSE.DRC
< prev
next >
Wrap
Text File
|
1986-11-12
|
8KB
|
461 lines
#util.g
/*
* QPARSE.DRC - parsing routines for Quest.
*/
extern
_scAbort(*char message)void;
type
DICTENTRY = struct {
*DICTENTRY d_next;
*char d_text;
int d_id;
int d_type;
},
FORMTYPE = enum {REQID, REQTYPE, OPTID, OPTTYPE, MULTIPLE},
FORMLIST = struct {
*FORMLIST f_next;
FORMTYPE f_kind;
int f_data;
},
GRAMMAR = struct {
*GRAMMAR g_next;
*FORMLIST g_sentence;
int g_id;
},
WORDLIST = struct {
*WORDLIST wl_next;
int wl_position;
int wl_type;
int wl_id;
};
*DICTENTRY Dictionary;
*GRAMMAR Grammar;
**FORMLIST WordPtr;
*WORDLIST InputSentence;
*GRAMMAR MatchedSentence;
*char UnknownWord;
*WORDLIST PrefixList;
int ScanPos;
ushort ScanCount;
bool PrefixEnabled;
/*
* psInit - initialize the parser.
*/
proc nonrec psInit(bool prefixEnabled;)void:
PrefixEnabled := prefixEnabled;
Dictionary := nil;
Grammar := nil;
InputSentence := nil;
UnknownWord := nil;
PrefixList := nil;
ScanPos := 0;
corp;
/*
* psWord - add a word to the dictionary.
*/
proc nonrec psWord(int id; *char txt; int typ)void:
*DICTENTRY d;
d := new(DICTENTRY);
d*.d_next := Dictionary;
d*.d_text := txt;
d*.d_id := id;
d*.d_type := typ;
Dictionary := d;
corp;
/*
* psDel - delete a word from the dictionary.
*/
proc nonrec psDel(int id)void:
**DICTENTRY pd;
*DICTENTRY d;
pd := &Dictionary;
while pd* ~= nil and pd**.d_id ~= id do
pd := &pd**.d_next;
od;
if pd* ~= nil then
d := pd*;
pd* := d*.d_next;
free(d);
fi;
corp;
/*
* psgBegin - set up to start a new sentence in the grammar.
*/
proc nonrec psgBegin(int id)void:
**GRAMMAR pg;
*GRAMMAR g;
pg := &Grammar;
while pg* ~= nil do
pg := &pg**.g_next;
od;
g := new(GRAMMAR);
g*.g_next := nil;
g*.g_id := id;
WordPtr := &g*.g_sentence;
pg* := g;
corp;
/*
* psgWord - add a word to the current grammar sentence.
*/
proc nonrec psgWord(FORMTYPE kind; int data)void:
*FORMLIST w;
w := new(FORMLIST);
w*.f_kind := kind;
w*.f_data := data;
WordPtr* := w;
WordPtr := &w*.f_next;
corp;
/*
* psgEnd - end of the current grammar sentence.
*/
proc nonrec psgEnd()void:
WordPtr* := nil;
corp;
/*
* psgDel - delete a rule from the grammar.
*/
proc nonrec psgDel(int id)void:
**GRAMMAR pg;
*GRAMMAR g;
*FORMLIST f, temp;
pg := &Grammar;
while pg* ~= nil and pg**.g_id ~= id do
pg := &pg**.g_next;
od;
if pg* ~= nil then
g := pg*;
pg* := g*.g_next;
f := g*.g_sentence;
free(g);
while f ~= nil do
temp := f;
f := f*.f_next;
free(temp);
od;
fi;
corp;
/*
* CAP - capitalize a letter.
*/
proc nonrec CAP(char ch)char:
if ch >= 'a' and ch <= 'z' then
ch - 32
else
ch
fi
corp;
/*
* psFind - look a word up in the dictionary.
*/
proc nonrec psFind(*char wrd)int:
*DICTENTRY d;
*char p1, p2;
d := Dictionary;
while
if d = nil then
false
else
p1 := wrd;
p2 := d*.d_text;
while p1* ~= '\e' and CAP(p1*) = CAP(p2*) do
p1 := p1 + 1;
p2 := p2 + 1;
od;
CAP(p1*) ~= CAP(p2*)
fi
do
d := d*.d_next;
od;
if d = nil then
0
else
d*.d_id
fi
corp;
/*
* _psLookup - return the DICTENTRY for the indicated word.
*/
proc nonrec _psLookup(int id)*DICTENTRY:
*DICTENTRY d;
d := Dictionary;
while
if d = nil then
_scAbort("psLookup: can't find id.");
fi;
d*.d_id ~= id
do
d := d*.d_next;
od;
d
corp;
/*
* psType - find the type of the word with the given id.
*/
proc nonrec psType(int id)int:
_psLookup(id)*.d_type
corp;
/*
* psGet - return the text of the word with the given id.
*/
proc nonrec psGet(int id)*char:
_psLookup(id)*.d_text
corp;
/*
* _delimChar - say if a character is a delimiter character.
*/
proc nonrec _delimChar(char ch)bool:
not (ch >= 'A' and ch <= 'Z' or ch >= 'a' and ch <= 'z' or
ch >= '0' and ch <= '9')
corp;
/*
* psParse - parse an input sentence.
*/
proc nonrec psParse(*char sentence)int:
**WORDLIST wp;
*FORMLIST f;
*WORDLIST w;
*char wordStart;
int data, position;
char ch;
bool bad;
/* first, free the previous input sentence list: */
while InputSentence ~= nil do
w := InputSentence;
InputSentence := InputSentence*.wl_next;
free(w);
od;
if UnknownWord ~= nil then
Mfree(pretend(UnknownWord, *byte), CharsLen(UnknownWord) + 1);
UnknownWord := nil;
fi;
while PrefixList ~= nil do
w := PrefixList;
PrefixList := PrefixList*.wl_next;
free(w);
od;
/* turn the input sentence into a list of words: */
ScanPos := 0;
wp := &InputSentence;
bad := false;
while
while sentence* = ' ' do
sentence := sentence + 1;
od;
not bad and sentence* ~= '\e'
do
if PrefixEnabled and sentence* = ':' and PrefixList = nil then
/* first part was a prefix: */
wp* := nil;
PrefixList := InputSentence;
wp := &InputSentence;
sentence := sentence + 1;
else
wordStart := sentence;
sentence := sentence + 1;
while not _delimChar(sentence*) do
sentence := sentence + 1;
od;
ch := sentence*;
sentence* := '\e';
w := new(WORDLIST);
w*.wl_id := psFind(wordStart);
if w*.wl_id = 0 then
UnknownWord := pretend(Malloc(CharsLen(wordStart)+1), *char);
CharsCopy(UnknownWord, wordStart);
bad := true;
else
w*.wl_type := psType(w*.wl_id);
fi;
wp* := w;
wp := &w*.wl_next;
sentence* := ch;
fi;
od;
wp* := nil;
/* if an unknown word was found, don't go any further: */
if bad then
-1
else
/* check the forms in the grammar for a matching sentence form: */
MatchedSentence := Grammar;
while
if MatchedSentence = nil then
bad := true;
false
else
f := MatchedSentence*.g_sentence;
w := InputSentence;
bad := false;
position := 1;
while not bad and f ~= nil do
data := f*.f_data;
case f*.f_kind
incase REQID:
if w ~= nil and data = w*.wl_id then
w*.wl_position := position;
f := f*.f_next;
w := w*.wl_next;
else
bad := true;
fi;
incase REQTYPE:
if w ~= nil and data = w*.wl_type then
w*.wl_position := position;
f := f*.f_next;
w := w*.wl_next;
else
bad := true;
fi;
incase OPTID:
if w ~= nil and data = w*.wl_id then
w*.wl_position := position;
w := w*.wl_next;
fi;
f := f*.f_next;
incase OPTTYPE:
if w ~= nil and data = w*.wl_type then
w*.wl_position := position;
w := w*.wl_next;
fi;
f := f*.f_next;
incase MULTIPLE:
while w ~= nil and data = w*.wl_type do
w*.wl_position := position;
w := w*.wl_next;
od;
f := f*.f_next;
esac;
position := position + 1;
od;
if w ~= nil then
bad := true;
fi;
bad
fi
do
MatchedSentence := MatchedSentence*.g_next;
od;
if bad then
0
else
MatchedSentence*.g_id
fi
fi
corp;
/*
* pspBad - return the unknown word (if any).
*/
proc nonrec pspBad()*char:
UnknownWord
corp;
/*
* pspWord - return the (first or any) word which fits the indicated position
* in the matched sentence form.
*/
proc nonrec pspWord(int pos)int:
*WORDLIST w;
ushort i;
if pos ~= ScanPos then
ScanPos := pos;
ScanCount := 0;
fi;
w := InputSentence;
while w ~= nil and w*.wl_position < pos do
w := w*.wl_next;
od;
i := ScanCount;
ScanCount := ScanCount + 1;
while w ~= nil and i ~= 0 do
i := i - 1;
w := w*.wl_next;
od;
if w = nil or w*.wl_position ~= pos then
0
else
w*.wl_id
fi
corp;
/*
* pspPref - return words in the prefix list.
*/
proc nonrec pspPref()int:
*WORDLIST p;
int id;
if PrefixList = nil then
0
else
p := PrefixList;
PrefixList := PrefixList*.wl_next;
id := p*.wl_id;
free(p);
id
fi
corp;