Computer Literacy -- Appendix B

void flagger(WORD *sentence, int n_words, WORD *dict, int n_dict)
{
	int i, j, k;
	/* Search for each word in dictionary. When found, copy information */
	/* If it can't be found, set first code to -1 (unknown) */
	for(i = 0; i < n_words; i++)
	{
		for(j = 0; j < n_dict; j++)
		{
			if(!strcmp(sentence[i].word, dict[j].word))
			{
				for(k = 0; k < 11; k++)
				{
					sentence[i].p_code[k] =
					  dict[j].p_code[k];
				}
				break;
			}
		}
		if(j == n_dict) /* Did not find word */
		{
			/* Ask user for type + add to dict */
			printf("Word \"%s\" not found.\n", sentence[i].word);
			printf("Please enter part of speech list (11 items): ");
			for(k = 0; k < 11; k++)
			{
				scanf("%d", &sentence[i].p_code[k]);
			}
		}
	}
}

void pdetect(WORD *sentence, int n_words, int pattern[4])
{
	int i, j; /* Counters */
	/* For a pattern to be in use, the words must be able to fit into   *
	 * it. Thus, we use a dictionary of sentence positions and parts of *  
	 * speech allowed in those positions to determine whether each      *
	 * pattern will work. When one is found, it will fill out pattern[] *
	 * and return. If none is found, -1 will be returned in pattern[0]  */
	for(i = 0; i < 9; i++) /* Loop through patterns */
	{
		if(fitsPattern(sentence, n_words, valid_patterns[i]))
		{
			for(j = 0; j < 4; j++)
				pattern[j] = valid_patterns[i][j];
			return; /* We really really found it! */
		}
	}
	/* We didn't find it--return all -1's. */
	for(i = 0; i < 4; i++) pattern[i] = -1;
}

int fitsPattern(WORD *sentence, int n_words, int pattern[4])
{
	int i, j, p = 0, op;
	int allowed_parts[4];
	/* Game plan: scan ahead to determine whether next part is part of  *
	 * the next part of the sentence. If not, then determine whether it *
	 * fits in the current part and whether it marks the end of the     *
	 * current part (which may depend on the next word's type--for      *
	 * example, two nouns in a row are probably two different parts of  *
	 * the sentence (unless seperated by commas).                       */
	for(i = 0; i < n_words; i++) /* Scan through words in sentence */
	{
		op = p; /* Backup p--still need to process */
		if((i < n_words - 1) & (p < 3)) /*not last word or last part*/
		{
			getAllowedParts(sentence[i+1], allowed_parts);
			for(j = 0; j < 4; j++)
			{
				if((pattern[p+1] == allowed_parts[j]) &&
				  pattern[p+1] != -1)
				{
					p++; /* Next part of sentence */
					break;
				}
			}
		}
		getAllowedParts(sentence[i], allowed_parts);
		for(j = 0; j < 4; j++)
		{
			if(pattern[op] == allowed_parts[j])
			{
				break; /* Exits for loop */
			}
			if(j == 3) /* There's no hope of matching */
			{
				return 0; /* Does not fit pattern */
			}
		} /* We fit--continue searching! */
		/* Warning--scanning for end of part not implemented! */
	}
	return 1; /* We made it--it matches! */

}

void getAllowedParts(WORD word, int parts[4])
{
	int i;
	/* Loop through each allowed part of speech--find parts of sentence *
	 * which it may lie and, if not already in the parts list, add it.  */
	for(i = 0; i < 4; i++) parts[i] = -1; /* Blank all parts fields */
	for(i = 0; i < 11; i++) /* Loop through valid types field */
	{
		switch(word.p_code[i])
		{
			case NOUN: /* May be in S, DO, or IO */
			case PRONOUN:
			addPartsToList(parts, SUBJECT, DO, IO, -1);
			break;
			case VERB: /* Duh!!! */
			case AVERB:
			addPartsToList(parts, VERB, -1, -1, -1);
			break;
			case ADJECTIVE: /* S, DO, or IO */
			addPartsToList(parts, SUBJECT, DO, IO, -1);
			break;
			case ADVERB: /* S, V, DO, or IO */
			addPartsToList(parts, SUBJECT, VERB, DO, IO);
		}
	}
}

void addPartsToList(int parts[4], int p1, int p2, int p3, int p4)
{
	int i;
	/* Simply loop through parts list for each part, recording the part *
	 * if it's not already in the list.                                 */
	for(i = 0; i < 4; i++)
	{
		if(parts[i] == p1)
		{
			break; /* Part already in list--no sense adding it */
		}
		else if(parts[i] == -1)
		{
			parts[i] = p1;
			break; /* Don't add it again!!! */
		}
	}
	for(i = 0; i < 4; i++)
	{
		if(parts[i] == p2)
		{
			break; /* Part already in list--no sense adding it */
		}
		else if(parts[i] == -1)
		{
			parts[i] = p2;
			break; /* Don't add it again!!! */
		}
	}
	for(i = 0; i < 4; i++)
	{
		if(parts[i] == p3)
		{
			break; /* Part already in list--no sense adding it */
		}
		else if(parts[i] == -1)
		{
			parts[i] = p3;
			break; /* Don't add it again!!! */
		}
	}
	for(i = 0; i < 4; i++)
	{
		if(parts[i] == p4)
		{
			break; /* Part already in list--no sense adding it */
		}
		else if(parts[i] == -1)
		{
			parts[i] = p4;
			break; /* Don't add it again!!! */
		}
	}
}

void parseSentence(WORD *sentence, int n_words, int pattern[4])
{
	int i, index;
	/* For each part, look at the pattern and the words and see which   *
	 * words fit in which part of the sentence. Then, using the process *
	 * of elimination, determine which words are what type. This needs  *
	 * to consider rules not set by the pattern--for example, a series  *
	 * of adjectives that are not predicate adjectives must eventually  *
	 * be followed by a noun, and conjunctions connect parallel         *
	 * structures.                                                      */
	index = 0;
	for(i = 0; i < 4; i++) /* Loop through parts of sentence */
	{
		index = flagPart(sentence, n_words, pattern[i], index);
	}
}

int flagPart(WORD *sentence, int n_words, int part, int index)
{
	int i, j, p_part, p_punc, c, adj_chain;
	int p_parts[4];
	p_part = p_punc = -1;
	adj_chain = 0;
	switch(part)
	{
	case VERB:
		for(i = index; i < n_words; i++)
		{
			c = 0;
			getAllowedParts(sentence[i], p_parts);
			for(j = 0; j < 4; j++)
			{
				if(p_parts[j] == part)
				{
					c = -1;
				}        
			}
			if(!c)
				return i;
			for(j = 0; j < 11; j++)
			{
				if(sentence[i].p_code[j] == VERB ||
				  sentence[i].p_code[j] == ADVERB ||
				  sentence[i].p_code[j] == AVERB)
				{
					sentence[i].code = sentence[i].p_code[j];
					break;
				}
			}
			p_punc = sentence[i].post_punct;
			p_part = sentence[i].code;
		}
		/* Since we're here, we've finished parsing */
		break;
	default:
		for(i = index; i < n_words; i++) /* Returns on end of part */
		{
			c = 0;
			if((p_part == NOUN || p_part == PRONOUN) && !adj_chain)
			{
				if(p_punc != ',')
					return i; /* End of part */
			}
			getAllowedParts(sentence[i], p_parts);
			for(j = 0; j < 4; j++)
			{
				if(p_parts[j] == part)
				{
					/* Write part in word structure here */
					c = -1; /* Continue looping */
				}
			}
			if(!c)
				return i;
			/* Still needs to be done: update p_punc and p_part */
			for(j = 0; j < 11; j++)
			{
				if(sentence[i].p_code[j] == ADJECTIVE &&
				  p_part == ADJECTIVE)
				{
					adj_chain = -1;
				}
			}
			for(j = 0; j < 11; j++)
			{
				if(sentence[i].p_code[j] == NOUN ||
				  sentence[i].p_code[j] == PRONOUN ||
				  sentence[i].p_code[j] == ADJECTIVE)
				{
					sentence[i].code =
					  sentence[i].p_code[j];
					break; /* exit inner loop */
				}
			}
			p_punc = sentence[i].post_punct;
			if(p_part == NOUN && adj_chain)
			{
				sentence[i-1].code = ADJECTIVE;
			}
			p_part = sentence[i].code;
		}
	}
	/* If we're here, then we've finished parsing */
	return n_words;
}