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:
569
dll/europa/cse476/list.cpp
Normal file
569
dll/europa/cse476/list.cpp
Normal file
@@ -0,0 +1,569 @@
|
||||
// Copyright (c) 1998-99, Ed Schlunder
|
||||
|
||||
#include <string.h>
|
||||
#include "list.h"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Class Implementation: List
|
||||
// ---------------------------------------------------------------------------
|
||||
List::List() {
|
||||
rootPtr = NULL;
|
||||
currPtr = NULL;
|
||||
}
|
||||
|
||||
List::~List() {
|
||||
listNode *tmpPtr = rootPtr, *nextPtr;
|
||||
|
||||
// go through the list and delete each node
|
||||
while(tmpPtr) {
|
||||
nextPtr = tmpPtr->nextPtr;
|
||||
if(tmpPtr->item)
|
||||
delete tmpPtr->item;
|
||||
if(tmpPtr->itemList)
|
||||
delete tmpPtr->itemList;
|
||||
if(tmpPtr->itemNode)
|
||||
delete tmpPtr->itemNode;
|
||||
|
||||
delete tmpPtr;
|
||||
tmpPtr = nextPtr;
|
||||
}
|
||||
};
|
||||
|
||||
void List::InsertBefore(char *item) {
|
||||
// this version does char strings
|
||||
|
||||
if(rootPtr == NULL) {
|
||||
// creating the first node in a previously empty list.
|
||||
rootPtr = new listNode;
|
||||
|
||||
rootPtr->item = new char[strlen(item) + 1];
|
||||
strcpy(rootPtr->item, item);
|
||||
rootPtr->itemList = NULL;
|
||||
rootPtr->itemNode = NULL;
|
||||
|
||||
rootPtr->nextPtr = NULL;
|
||||
rootPtr->prevPtr = NULL;
|
||||
|
||||
currPtr = rootPtr;
|
||||
}
|
||||
else {
|
||||
// create a new node and insert it before currPtr's node
|
||||
listNode *newPtr = new listNode;
|
||||
|
||||
newPtr->nextPtr = currPtr;
|
||||
newPtr->prevPtr = currPtr->prevPtr;
|
||||
newPtr->item = new char[strlen(item) + 1];
|
||||
strcpy(newPtr->item, item);
|
||||
newPtr->itemList = NULL;
|
||||
newPtr->itemNode = NULL;
|
||||
|
||||
currPtr->prevPtr = newPtr;
|
||||
if(newPtr->prevPtr)
|
||||
newPtr->prevPtr->nextPtr = newPtr;
|
||||
|
||||
currPtr = newPtr;
|
||||
}
|
||||
}
|
||||
|
||||
void List::InsertBefore(List *item) {
|
||||
// this version does Lists
|
||||
|
||||
if(rootPtr == NULL) {
|
||||
rootPtr = new listNode;
|
||||
|
||||
rootPtr->item = NULL;
|
||||
rootPtr->itemList = item;
|
||||
rootPtr->itemNode = NULL;
|
||||
|
||||
rootPtr->nextPtr = NULL;
|
||||
rootPtr->prevPtr = NULL;
|
||||
|
||||
currPtr = rootPtr;
|
||||
}
|
||||
else {
|
||||
listNode *newPtr = new listNode;
|
||||
|
||||
newPtr->item = NULL;
|
||||
newPtr->itemList = item;
|
||||
newPtr->itemNode = NULL;
|
||||
newPtr->nextPtr = currPtr;
|
||||
newPtr->prevPtr = currPtr->prevPtr;
|
||||
|
||||
currPtr->prevPtr = newPtr;
|
||||
if(newPtr->prevPtr)
|
||||
newPtr->prevPtr->nextPtr = newPtr;
|
||||
|
||||
currPtr = newPtr;
|
||||
}
|
||||
}
|
||||
|
||||
void List::InsertBefore(genericNode *item) {
|
||||
if(rootPtr == NULL) {
|
||||
rootPtr = new listNode;
|
||||
|
||||
rootPtr->item = NULL;
|
||||
rootPtr->itemList = NULL;
|
||||
rootPtr->itemNode = item;
|
||||
|
||||
rootPtr->nextPtr = NULL;
|
||||
rootPtr->prevPtr = NULL;
|
||||
|
||||
currPtr = rootPtr;
|
||||
}
|
||||
else {
|
||||
listNode *newPtr = new listNode;
|
||||
|
||||
newPtr->item = NULL;
|
||||
newPtr->itemList = NULL;
|
||||
newPtr->itemNode = item;
|
||||
newPtr->nextPtr = currPtr;
|
||||
newPtr->prevPtr = currPtr->prevPtr;
|
||||
|
||||
currPtr->prevPtr = newPtr;
|
||||
if(newPtr->prevPtr)
|
||||
newPtr->prevPtr->nextPtr = newPtr;
|
||||
|
||||
currPtr = newPtr;
|
||||
}
|
||||
}
|
||||
|
||||
void List::InsertAfter(char *item) {
|
||||
if(rootPtr == NULL) {
|
||||
rootPtr = new listNode;
|
||||
rootPtr->prevPtr = NULL;
|
||||
rootPtr->nextPtr = NULL;
|
||||
rootPtr->itemList = NULL;
|
||||
rootPtr->itemNode = NULL;
|
||||
rootPtr->item = new char[strlen(item) + 1];
|
||||
strcpy(rootPtr->item, item);
|
||||
|
||||
currPtr = rootPtr;
|
||||
}
|
||||
else {
|
||||
listNode *newPtr = new listNode;
|
||||
|
||||
newPtr->nextPtr = currPtr->nextPtr;
|
||||
newPtr->prevPtr = currPtr;
|
||||
newPtr->itemList = NULL;
|
||||
newPtr->itemNode = NULL;
|
||||
newPtr->item = new char[strlen(item) + 1];
|
||||
strcpy(newPtr->item, item);
|
||||
|
||||
if(newPtr->nextPtr)
|
||||
newPtr->nextPtr->prevPtr = newPtr;
|
||||
newPtr->prevPtr->nextPtr = newPtr;
|
||||
|
||||
currPtr = newPtr;
|
||||
}
|
||||
}
|
||||
|
||||
void List::InsertAfter(List *item) {
|
||||
if(rootPtr == NULL) {
|
||||
rootPtr = new listNode;
|
||||
rootPtr->prevPtr = NULL;
|
||||
rootPtr->nextPtr = NULL;
|
||||
rootPtr->item = NULL;
|
||||
rootPtr->itemList = item;
|
||||
rootPtr->itemNode = NULL;
|
||||
|
||||
currPtr = rootPtr;
|
||||
}
|
||||
else {
|
||||
listNode *newPtr = new listNode;
|
||||
|
||||
newPtr->nextPtr = currPtr->nextPtr;
|
||||
newPtr->prevPtr = currPtr;
|
||||
newPtr->item = NULL;
|
||||
newPtr->itemList = item;
|
||||
newPtr->itemNode = NULL;
|
||||
|
||||
if(newPtr->nextPtr)
|
||||
newPtr->nextPtr->prevPtr = newPtr;
|
||||
newPtr->prevPtr->nextPtr = newPtr;
|
||||
|
||||
currPtr = newPtr;
|
||||
}
|
||||
}
|
||||
|
||||
void List::InsertAfter(genericNode *item) {
|
||||
if(rootPtr == NULL) {
|
||||
rootPtr = new listNode;
|
||||
rootPtr->prevPtr = NULL;
|
||||
rootPtr->nextPtr = NULL;
|
||||
rootPtr->item = NULL;
|
||||
rootPtr->itemList = NULL;
|
||||
rootPtr->itemNode = item;
|
||||
|
||||
currPtr = rootPtr;
|
||||
}
|
||||
else {
|
||||
listNode *newPtr = new listNode;
|
||||
|
||||
newPtr->nextPtr = currPtr->nextPtr;
|
||||
newPtr->prevPtr = currPtr;
|
||||
newPtr->item = NULL;
|
||||
newPtr->itemList = NULL;
|
||||
newPtr->itemNode = item;
|
||||
|
||||
if(newPtr->nextPtr)
|
||||
newPtr->nextPtr->prevPtr = newPtr;
|
||||
newPtr->prevPtr->nextPtr = newPtr;
|
||||
|
||||
currPtr = newPtr;
|
||||
}
|
||||
}
|
||||
|
||||
bool List::GoTop(void) {
|
||||
currPtr = rootPtr;
|
||||
|
||||
if(currPtr == NULL)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool List::GoNext(void) {
|
||||
if(!currPtr)
|
||||
return false;
|
||||
|
||||
currPtr = currPtr->nextPtr;
|
||||
if(currPtr == NULL)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool List::GoPrev(void) {
|
||||
if(!currPtr)
|
||||
return false;
|
||||
|
||||
currPtr = currPtr->prevPtr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool List::GoItem(int n) {
|
||||
if(!rootPtr) // if empty list, abort
|
||||
return false;
|
||||
|
||||
currPtr = rootPtr;
|
||||
|
||||
while(n--) { // visit each node from the root up to n nodes deep
|
||||
if(!currPtr->nextPtr)
|
||||
break;
|
||||
|
||||
currPtr = currPtr->nextPtr;
|
||||
}
|
||||
|
||||
if(currPtr == NULL)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
char *List::currItem(void) {
|
||||
if(currPtr)
|
||||
return currPtr->item;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
List *List::currItemList(void) {
|
||||
if(currPtr)
|
||||
return currPtr->itemList;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
genericNode *List::currItemNode(void) {
|
||||
if(currPtr)
|
||||
return currPtr->itemNode;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void List::Print(void) {
|
||||
listNode *tmpPtr = rootPtr;
|
||||
|
||||
cout << "(";
|
||||
while(tmpPtr) {
|
||||
if(tmpPtr->item)
|
||||
cout << tmpPtr->item << " ";
|
||||
|
||||
if(tmpPtr->itemList)
|
||||
tmpPtr->itemList->Print();
|
||||
|
||||
if(tmpPtr->itemNode)
|
||||
cout << tmpPtr->itemNode;
|
||||
|
||||
tmpPtr = tmpPtr->nextPtr;
|
||||
}
|
||||
cout << "\b) ";
|
||||
}
|
||||
|
||||
|
||||
List *MakeList(char *text) {
|
||||
int length, i, j;
|
||||
char *tmp = text;
|
||||
List *l = new List;
|
||||
|
||||
length = strlen(text);
|
||||
for(i = 0; i < length; i++) {
|
||||
if(text[i] == '{' || text[i] == '(') {
|
||||
// sub-list found
|
||||
for(j = i + 1; j < length; j++)
|
||||
if(text[j] == '}' || text[j] == ')')
|
||||
break;
|
||||
|
||||
tmp = new char[j - i];
|
||||
strncpy(tmp, text + i + 1, j - i - 1);
|
||||
tmp[j - i - 1] = 0;
|
||||
|
||||
l->InsertAfter(MakeList(tmp));
|
||||
delete tmp;
|
||||
i = j + 1;
|
||||
}
|
||||
else if(text[i] != ' ' && text[i] != '\t' && text[i] != '.') {
|
||||
// item found
|
||||
for(j = i + 1; j < length; j++)
|
||||
if(text[j] == ' ' || text[j] == '\t' || text[j] == '.')
|
||||
break;
|
||||
tmp = new char[j - i + 1];
|
||||
strncpy(tmp, text + i, j - i);
|
||||
tmp[j-i] = 0;
|
||||
|
||||
l->InsertAfter(tmp);
|
||||
if(text[j] == '.')
|
||||
l->InsertAfter(".");
|
||||
delete tmp;
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
List *MakeFeatList(char *text) {
|
||||
int length, i, j;
|
||||
char *tmp;
|
||||
List *l = new List;
|
||||
|
||||
length = strlen(text);
|
||||
for(i = 0; i < length; i++) {
|
||||
for(j = i; j < length; j++)
|
||||
if(text[j] == ' ')
|
||||
break;
|
||||
|
||||
for(j++; j < length; j++)
|
||||
if(text[j] == ' ' || text[j] == '}')
|
||||
break;
|
||||
|
||||
if(text[j+1] == '{')
|
||||
for(j++; j < length; j++)
|
||||
if(text[j] == '}') {
|
||||
j++;
|
||||
break;
|
||||
}
|
||||
|
||||
tmp = new char[j - i + 1];
|
||||
strncpy(tmp, text + i, j - i);
|
||||
tmp[j - i] = 0;
|
||||
// cout << "Mklist: [" << tmp << "]" << endl;
|
||||
l->InsertAfter(MakeList(tmp));
|
||||
delete tmp;
|
||||
|
||||
i = j;
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Creates a list of features from a string. Example string:
|
||||
// ((CAT NP) (AGR ?a))
|
||||
List *makeFeatureList(char *text) {
|
||||
int length, i, j, level, beg, end;
|
||||
char *tmp, *thisList;
|
||||
List *l = new List;
|
||||
|
||||
length = strlen(text);
|
||||
|
||||
// locate opening parenthesis
|
||||
for(i = 0; i < length; i++)
|
||||
if(text[i] == '(') break;
|
||||
|
||||
// no list given if no opening parenthesis found -- abort
|
||||
if(i == length) return NULL;
|
||||
|
||||
// get -past- the (
|
||||
i++;
|
||||
|
||||
// find end of this list
|
||||
for(level = 1, j = i+1; j < length; j++) {
|
||||
if(text[j] == ')') level--;
|
||||
if(text[j] == '(') level++;
|
||||
}
|
||||
|
||||
j--;
|
||||
|
||||
// make a new string containing a copy of the list text we want to work
|
||||
// with only...
|
||||
thisList = new char[j - i + 1];
|
||||
strncpy(thisList, text + i, j - i);
|
||||
thisList[j - i] = 0;
|
||||
trim(thisList);
|
||||
|
||||
// cout << "thisList: [" << thisList << "]" << endl;
|
||||
|
||||
// step through the list text and take out each item (*tmp)
|
||||
length = strlen(thisList);
|
||||
end = -1;
|
||||
while(end < length) {
|
||||
beg = end + 1;
|
||||
|
||||
// find the end of this item
|
||||
for(level = 0, end = beg; end < length; end++) {
|
||||
if((thisList[end] == ' ') && (level == 0))
|
||||
break;
|
||||
|
||||
// make sure that items encased within ( ) are kept as one piece
|
||||
if(thisList[end] == '(') level++;
|
||||
if(thisList[end] == ')') level--;
|
||||
}
|
||||
|
||||
// make a copy of the text just for this item
|
||||
tmp = new char[end - beg + 1];
|
||||
strncpy(tmp, thisList + beg, end - beg);
|
||||
tmp[end - beg] = 0;
|
||||
|
||||
// is this item a sub list?
|
||||
if(tmp[0] == '(')
|
||||
l->InsertAfter(makeFeatureList(tmp));
|
||||
else
|
||||
l->InsertAfter(tmp);
|
||||
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
// free up memory for temporary list string
|
||||
delete thisList;
|
||||
return l;
|
||||
}
|
||||
|
||||
ostream &operator<<(ostream &out_file, const List &l) {
|
||||
if(&l == NULL) {
|
||||
out_file << "nil";
|
||||
return out_file;
|
||||
}
|
||||
|
||||
listNode *tmpPtr = l.rootPtr;
|
||||
|
||||
// is this an empty list?
|
||||
if(tmpPtr == NULL)
|
||||
out_file << "()";
|
||||
else {
|
||||
out_file << "(";
|
||||
|
||||
// print out first item without a separating space for it
|
||||
if(tmpPtr->item) out_file << tmpPtr->item;
|
||||
if(tmpPtr->itemList) out_file << *tmpPtr->itemList;
|
||||
if(tmpPtr->itemNode) out_file << *tmpPtr->itemNode;
|
||||
|
||||
// step through the linked list of List items and print each one...
|
||||
while((tmpPtr = tmpPtr->nextPtr)) {
|
||||
if(tmpPtr->item) out_file << ' ' << tmpPtr->item;
|
||||
if(tmpPtr->itemList) out_file << ' ' << *tmpPtr->itemList;
|
||||
if(tmpPtr->itemNode) out_file << ' ' << *tmpPtr->itemNode;
|
||||
}
|
||||
out_file << ')';
|
||||
}
|
||||
|
||||
return out_file;
|
||||
}
|
||||
|
||||
bool List::empty(void) {
|
||||
if(rootPtr == NULL)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
int List::length(void) {
|
||||
listNode *tmp;
|
||||
int num;
|
||||
|
||||
// count each node in the list and return the count
|
||||
tmp = rootPtr;
|
||||
num = 0;
|
||||
while(tmp) {
|
||||
num++;
|
||||
tmp = tmp->nextPtr;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
List *findSubst(char *var, List *assign) {
|
||||
if(assign->GoTop() == false)
|
||||
return NULL;
|
||||
|
||||
do {
|
||||
List *varSubst = assign->currItemList();
|
||||
varSubst->GoTop();
|
||||
|
||||
// is this the variable that we are trying to find?
|
||||
if(strcmp(varSubst->currItem(), var) == 0) {
|
||||
varSubst->GoNext();
|
||||
return varSubst->currItemList();
|
||||
}
|
||||
} while(assign->GoNext());
|
||||
|
||||
// couldn't find var in the variable substitution list
|
||||
return NULL;
|
||||
}
|
||||
|
||||
List *substitute(List *old, List *assign) {
|
||||
List *subst = new List;
|
||||
listNode *tmp;
|
||||
|
||||
tmp = old->rootPtr;
|
||||
while(tmp) {
|
||||
if(tmp->item) {
|
||||
// cout << "recreating item: " << tmp->item << endl;
|
||||
if(tmp->item[0] == '?') {
|
||||
// variable may need to be substituted
|
||||
List *newItem = findSubst(tmp->item, assign);
|
||||
if(newItem == NULL)
|
||||
subst->InsertAfter(tmp->item);
|
||||
else {
|
||||
newItem->GoTop();
|
||||
do {
|
||||
if(newItem->currItem())
|
||||
subst->InsertAfter(newItem->currItem());
|
||||
if(newItem->currItemList())
|
||||
subst->InsertAfter(newItem->currItemList());
|
||||
if(newItem->currItemNode())
|
||||
subst->InsertAfter(newItem->currItemNode());
|
||||
} while(newItem->GoNext());
|
||||
}
|
||||
}
|
||||
else
|
||||
// constants just stay
|
||||
subst->InsertAfter(tmp->item);
|
||||
}
|
||||
|
||||
// just call ourselves recursively for sublists
|
||||
if(tmp->itemList) {
|
||||
// cout << "recreating list: " << *tmp->itemList << endl;
|
||||
subst->InsertAfter(substitute(tmp->itemList, assign));
|
||||
}
|
||||
|
||||
if(tmp->itemNode) {
|
||||
// cout << "recreating genericNode: " << *tmp->itemNode << endl;
|
||||
subst->InsertAfter(new genericNode(NULL, substitute(tmp->itemNode->features(), assign)));
|
||||
}
|
||||
|
||||
tmp = tmp->nextPtr;
|
||||
}
|
||||
|
||||
return subst;
|
||||
}
|
||||
Reference in New Issue
Block a user