#include <string.h>
#include "list.h"
List::List() {
rootPtr = NULL;
currPtr = NULL;
}
List::~List() {
listNode *tmpPtr = rootPtr, *nextPtr;
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) {
if(rootPtr == NULL) {
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 {
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) {
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)
return false;
currPtr = rootPtr;
while(n--) {
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] == '(') {
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] != '.') {
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;
l->InsertAfter(MakeList(tmp));
delete tmp;
i = j;
}
return l;
}
List *makeFeatureList(char *text) {
int length, i, j, level, beg, end;
char *tmp, *thisList;
List *l = new List;
length = strlen(text);
for(i = 0; i < length; i++)
if(text[i] == '(') break;
if(i == length) return NULL;
i++;
for(level = 1, j = i+1; j < length; j++) {
if(text[j] == ')') level--;
if(text[j] == '(') level++;
}
j--;
thisList = new char[j - i + 1];
strncpy(thisList, text + i, j - i);
thisList[j - i] = 0;
trim(thisList);
length = strlen(thisList);
end = -1;
while(end < length) {
beg = end + 1;
for(level = 0, end = beg; end < length; end++) {
if((thisList[end] == ' ') && (level == 0))
break;
if(thisList[end] == '(') level++;
if(thisList[end] == ')') level--;
}
tmp = new char[end - beg + 1];
strncpy(tmp, thisList + beg, end - beg);
tmp[end - beg] = 0;
if(tmp[0] == '(')
l->InsertAfter(makeFeatureList(tmp));
else
l->InsertAfter(tmp);
delete tmp;
}
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;
if(tmpPtr == NULL)
out_file << "()";
else {
out_file << "(";
if(tmpPtr->item) out_file << tmpPtr->item;
if(tmpPtr->itemList) out_file << *tmpPtr->itemList;
if(tmpPtr->itemNode) out_file << *tmpPtr->itemNode;
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;
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();
if(strcmp(varSubst->currItem(), var) == 0) {
varSubst->GoNext();
return varSubst->currItemList();
}
} while(assign->GoNext());
return NULL;
}
List *substitute(List *old, List *assign) {
List *subst = new List;
listNode *tmp;
tmp = old->rootPtr;
while(tmp) {
if(tmp->item) {
if(tmp->item[0] == '?') {
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
subst->InsertAfter(tmp->item);
}
if(tmp->itemList) {
subst->InsertAfter(substitute(tmp->itemList, assign));
}
if(tmp->itemNode) {
subst->InsertAfter(new genericNode(NULL, substitute(tmp->itemNode->features(), assign)));
}
tmp = tmp->nextPtr;
}
return subst;
}