Initial import of the ircii-pana-1.1-final source tree.
git-svn-id: svn://svn.code.sf.net/p/bitchx/code/tags/ircii-pana-1.1-final@1 13b04d17-f746-0410-82c6-800466cd88b0
This commit is contained in:
230
dll/europa/cse476/gnode.cpp
Normal file
230
dll/europa/cse476/gnode.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
// Copyright (c) 1998-99, Ed Schlunder
|
||||
|
||||
#include <string.h>
|
||||
#include "gnode.h"
|
||||
#include "list.h"
|
||||
|
||||
// takes a string and hacks off leading/trailing spaces and *'s.
|
||||
void trim(char *text) {
|
||||
int i, j, len;
|
||||
|
||||
len = strlen(text);
|
||||
|
||||
// empty strings don't need trimming...
|
||||
if(len == 0) return;
|
||||
|
||||
// find beginning of actual text
|
||||
for(i = 0; i < len; i++)
|
||||
if(text[i] != ' ') break;
|
||||
|
||||
// was there any preceeding white space to clear out?
|
||||
if(i > 0)
|
||||
for(j = 0; text[i] != 0; j++, i++)
|
||||
text[j] = text[i];
|
||||
|
||||
// step from the end backwards to see find where we need to chop
|
||||
for(j = strlen(text); j > 1; j--)
|
||||
if(text[j-1] != ' ') {
|
||||
text[j] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Class Implementation: genericNode
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
genericNode::genericNode(char *word, List *features) {
|
||||
if(word) {
|
||||
name = new char[strlen(word)];
|
||||
strcpy(name, word);
|
||||
}
|
||||
else
|
||||
word = NULL;
|
||||
|
||||
featureList = features;
|
||||
}
|
||||
|
||||
// Example Phrasal: ((CAT N) (AGR ?a))
|
||||
// Example Lexical: saw ((CAT N) (ROOT SAW1) (AGR 3s))
|
||||
genericNode::genericNode(char *obj) {
|
||||
unsigned int i, j;
|
||||
|
||||
// first try to read in the name field (in lexical objects)
|
||||
for(i = 0; i < strlen(obj); i++)
|
||||
if(obj[i] != ' ') break;
|
||||
|
||||
// maybe this is a phrasal object -- doesn't have a "name" field
|
||||
if(obj[i] == '(') {
|
||||
name = NULL;
|
||||
j = i;
|
||||
}
|
||||
else {
|
||||
// this is a lexical object, pick up the name:
|
||||
for(j = i; j < strlen(obj); j++)
|
||||
if(obj[j] == ' ') break;
|
||||
|
||||
name = new char[j - i + 1];
|
||||
strncpy(name, obj, j - i);
|
||||
name[j - i] = 0;
|
||||
j++;
|
||||
}
|
||||
|
||||
// pick up the object's feature list
|
||||
char *tmp = obj + j;
|
||||
// cout << "[" << tmp << "]" << endl;
|
||||
featureList = makeFeatureList(tmp);
|
||||
}
|
||||
|
||||
ostream& operator<<(ostream &out_file, genericNode const &n) {
|
||||
if(n.name == NULL)
|
||||
out_file << "(nil";
|
||||
else
|
||||
out_file << '(' << n.name;
|
||||
|
||||
if(n.featureList)
|
||||
out_file << ' ' << *n.featureList;
|
||||
|
||||
out_file << ')';
|
||||
|
||||
return out_file;
|
||||
}
|
||||
|
||||
List *unify(genericNode &s, genericNode &g) {
|
||||
List &sFeatures = *s.featureList, &gFeatures = *g.featureList, *currFeature;
|
||||
List *assignList = new List;
|
||||
char *featureName;
|
||||
List *featureValueA, *featureValueB;
|
||||
|
||||
// if a node has no feature list, then we automatically know it can unify
|
||||
if(!sFeatures.GoTop()) return new List;
|
||||
if(!gFeatures.GoTop()) return new List;
|
||||
|
||||
do {
|
||||
// get the current feature
|
||||
currFeature = sFeatures.currItemList();
|
||||
currFeature->GoTop();
|
||||
|
||||
// pull out the feature name and value
|
||||
featureName = currFeature->currItem();
|
||||
currFeature->GoNext();
|
||||
featureValueA = currFeature->currItemList();
|
||||
featureValueB = g.lookupFeature(featureName);
|
||||
|
||||
/*
|
||||
cout << "unify: [" << featureName << "] = " << *featureValueA << "";
|
||||
cout << " with " << *featureValueB << " --> ";
|
||||
*/
|
||||
|
||||
/*
|
||||
if(featureValueB == NULL)
|
||||
// if feature lookup failed, no corresponding feature exists --
|
||||
// automatically agrees...
|
||||
// cout << "yes" << endl;
|
||||
else {
|
||||
*/
|
||||
// if featureB is nothing, no corresponding featuture exists -- agrees
|
||||
if(featureValueB != NULL) {
|
||||
List *assignment = cmpFeatures(*featureValueA, *featureValueB);
|
||||
if(assignment == NULL) {
|
||||
// cout << "no" << endl;
|
||||
delete assignList;
|
||||
return NULL;
|
||||
}
|
||||
// cout << "yes: " << *assignment << endl;
|
||||
if(!assignment->empty())
|
||||
assignList->InsertAfter(assignment);
|
||||
}
|
||||
} while(sFeatures.GoNext());
|
||||
// cout << "assignment list: " << *assignList << endl;
|
||||
return assignList;
|
||||
}
|
||||
|
||||
List *cmpFeatures(List &a, List &b) {
|
||||
char *valueA, *valueB;
|
||||
a.GoTop();
|
||||
|
||||
do {
|
||||
valueA = a.currItem();
|
||||
|
||||
b.GoTop();
|
||||
do {
|
||||
valueB = b.currItem();
|
||||
|
||||
// do we have a match?
|
||||
if(strcmp(valueA, valueB) == 0)
|
||||
return new List;
|
||||
|
||||
// if one of the values is a variable, then it can match anything
|
||||
if(valueA[0] == '?') {
|
||||
List *assignList = new List;
|
||||
assignList->InsertAfter(valueA);
|
||||
assignList->InsertAfter(&b);
|
||||
|
||||
return assignList;
|
||||
}
|
||||
|
||||
if(valueB[0] == '?') {
|
||||
List *assignList = new List;
|
||||
assignList->InsertAfter(valueB);
|
||||
assignList->InsertAfter(&a);
|
||||
|
||||
return assignList;
|
||||
}
|
||||
} while(b.GoNext());
|
||||
} while(a.GoNext());
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
List *genericNode::lookupFeature(const char *name) const {
|
||||
char *tmp;
|
||||
List *featureSeek;
|
||||
|
||||
// if this node has no features, abort search
|
||||
if(featureList == NULL) return NULL;
|
||||
|
||||
featureList->GoTop();
|
||||
do {
|
||||
// pick up current feature
|
||||
featureSeek = featureList->currItemList();
|
||||
featureSeek->GoTop();
|
||||
|
||||
// pick up current feature's name
|
||||
tmp = featureSeek->currItem();
|
||||
|
||||
// is this the feature we were trying to find?
|
||||
if(strcmp(tmp, name) == 0) {
|
||||
// found our feature, pick up the value
|
||||
featureSeek->GoNext();
|
||||
return featureSeek->currItemList();
|
||||
}
|
||||
} while(featureList->GoNext());
|
||||
|
||||
// exhausted the feature list, this feature doesn't exist in this genericNode
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *genericNode::word(void) {
|
||||
return name;
|
||||
}
|
||||
|
||||
genericNode::~genericNode() {
|
||||
// -----------------------
|
||||
// THIS NEEDS IMPLEMENTING
|
||||
// -----------------------
|
||||
delete name;
|
||||
delete featureList;
|
||||
}
|
||||
|
||||
List *genericNode::features(void) {
|
||||
return featureList;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
genericNode *substitute(genericNode *old, List *assign) {
|
||||
genericNode *subst;
|
||||
|
||||
subst = new genericNode(old->name, substitute(old->featureList, assign));
|
||||
return subst;
|
||||
}
|
||||
Reference in New Issue
Block a user