Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
BitchX
GitHub Repository: BitchX/BitchX1.3
Path: blob/master/dll/europa/cse476/gnode.cpp
1074 views
1
// Copyright (c) 1998-99, Ed Schlunder
2
3
#include <string.h>
4
#include "gnode.h"
5
#include "list.h"
6
7
// takes a string and hacks off leading/trailing spaces and *'s.
8
void trim(char *text) {
9
int i, j, len;
10
11
len = strlen(text);
12
13
// empty strings don't need trimming...
14
if(len == 0) return;
15
16
// find beginning of actual text
17
for(i = 0; i < len; i++)
18
if(text[i] != ' ') break;
19
20
// was there any preceeding white space to clear out?
21
if(i > 0)
22
for(j = 0; text[i] != 0; j++, i++)
23
text[j] = text[i];
24
25
// step from the end backwards to see find where we need to chop
26
for(j = strlen(text); j > 1; j--)
27
if(text[j-1] != ' ') {
28
text[j] = 0;
29
break;
30
}
31
}
32
33
34
// ---------------------------------------------------------------------------
35
// Class Implementation: genericNode
36
// ---------------------------------------------------------------------------
37
38
genericNode::genericNode(char *word, List *features) {
39
if(word) {
40
name = new char[strlen(word)];
41
strcpy(name, word);
42
}
43
else
44
word = NULL;
45
46
featureList = features;
47
}
48
49
// Example Phrasal: ((CAT N) (AGR ?a))
50
// Example Lexical: saw ((CAT N) (ROOT SAW1) (AGR 3s))
51
genericNode::genericNode(char *obj) {
52
unsigned int i, j;
53
54
// first try to read in the name field (in lexical objects)
55
for(i = 0; i < strlen(obj); i++)
56
if(obj[i] != ' ') break;
57
58
// maybe this is a phrasal object -- doesn't have a "name" field
59
if(obj[i] == '(') {
60
name = NULL;
61
j = i;
62
}
63
else {
64
// this is a lexical object, pick up the name:
65
for(j = i; j < strlen(obj); j++)
66
if(obj[j] == ' ') break;
67
68
name = new char[j - i + 1];
69
strncpy(name, obj, j - i);
70
name[j - i] = 0;
71
j++;
72
}
73
74
// pick up the object's feature list
75
char *tmp = obj + j;
76
// cout << "[" << tmp << "]" << endl;
77
featureList = makeFeatureList(tmp);
78
}
79
80
ostream& operator<<(ostream &out_file, genericNode const &n) {
81
if(n.name == NULL)
82
out_file << "(nil";
83
else
84
out_file << '(' << n.name;
85
86
if(n.featureList)
87
out_file << ' ' << *n.featureList;
88
89
out_file << ')';
90
91
return out_file;
92
}
93
94
List *unify(genericNode &s, genericNode &g) {
95
List &sFeatures = *s.featureList, &gFeatures = *g.featureList, *currFeature;
96
List *assignList = new List;
97
char *featureName;
98
List *featureValueA, *featureValueB;
99
100
// if a node has no feature list, then we automatically know it can unify
101
if(!sFeatures.GoTop()) return new List;
102
if(!gFeatures.GoTop()) return new List;
103
104
do {
105
// get the current feature
106
currFeature = sFeatures.currItemList();
107
currFeature->GoTop();
108
109
// pull out the feature name and value
110
featureName = currFeature->currItem();
111
currFeature->GoNext();
112
featureValueA = currFeature->currItemList();
113
featureValueB = g.lookupFeature(featureName);
114
115
/*
116
cout << "unify: [" << featureName << "] = " << *featureValueA << "";
117
cout << " with " << *featureValueB << " --> ";
118
*/
119
120
/*
121
if(featureValueB == NULL)
122
// if feature lookup failed, no corresponding feature exists --
123
// automatically agrees...
124
// cout << "yes" << endl;
125
else {
126
*/
127
// if featureB is nothing, no corresponding featuture exists -- agrees
128
if(featureValueB != NULL) {
129
List *assignment = cmpFeatures(*featureValueA, *featureValueB);
130
if(assignment == NULL) {
131
// cout << "no" << endl;
132
delete assignList;
133
return NULL;
134
}
135
// cout << "yes: " << *assignment << endl;
136
if(!assignment->empty())
137
assignList->InsertAfter(assignment);
138
}
139
} while(sFeatures.GoNext());
140
// cout << "assignment list: " << *assignList << endl;
141
return assignList;
142
}
143
144
List *cmpFeatures(List &a, List &b) {
145
char *valueA, *valueB;
146
a.GoTop();
147
148
do {
149
valueA = a.currItem();
150
151
b.GoTop();
152
do {
153
valueB = b.currItem();
154
155
// do we have a match?
156
if(strcmp(valueA, valueB) == 0)
157
return new List;
158
159
// if one of the values is a variable, then it can match anything
160
if(valueA[0] == '?') {
161
List *assignList = new List;
162
assignList->InsertAfter(valueA);
163
assignList->InsertAfter(&b);
164
165
return assignList;
166
}
167
168
if(valueB[0] == '?') {
169
List *assignList = new List;
170
assignList->InsertAfter(valueB);
171
assignList->InsertAfter(&a);
172
173
return assignList;
174
}
175
} while(b.GoNext());
176
} while(a.GoNext());
177
178
return NULL;
179
}
180
181
List *genericNode::lookupFeature(const char *name) const {
182
char *tmp;
183
List *featureSeek;
184
185
// if this node has no features, abort search
186
if(featureList == NULL) return NULL;
187
188
featureList->GoTop();
189
do {
190
// pick up current feature
191
featureSeek = featureList->currItemList();
192
featureSeek->GoTop();
193
194
// pick up current feature's name
195
tmp = featureSeek->currItem();
196
197
// is this the feature we were trying to find?
198
if(strcmp(tmp, name) == 0) {
199
// found our feature, pick up the value
200
featureSeek->GoNext();
201
return featureSeek->currItemList();
202
}
203
} while(featureList->GoNext());
204
205
// exhausted the feature list, this feature doesn't exist in this genericNode
206
return NULL;
207
}
208
209
char *genericNode::word(void) {
210
return name;
211
}
212
213
genericNode::~genericNode() {
214
// -----------------------
215
// THIS NEEDS IMPLEMENTING
216
// -----------------------
217
delete name;
218
delete featureList;
219
}
220
221
List *genericNode::features(void) {
222
return featureList;
223
}
224
// ---------------------------------------------------------------------------
225
genericNode *substitute(genericNode *old, List *assign) {
226
genericNode *subst;
227
228
subst = new genericNode(old->name, substitute(old->featureList, assign));
229
return subst;
230
}
231
232