[Scummvm-cvs-logs] SF.net SVN: scummvm:[38471] tools/trunk/sci/engine/said.y

thebluegr at users.sourceforge.net thebluegr at users.sourceforge.net
Wed Feb 18 12:37:20 CET 2009


Revision: 38471
          http://scummvm.svn.sourceforge.net/scummvm/?rev=38471&view=rev
Author:   thebluegr
Date:     2009-02-18 11:37:19 +0000 (Wed, 18 Feb 2009)

Log Message:
-----------
Added said.y which I forgot...

Added Paths:
-----------
    tools/trunk/sci/engine/said.y

Added: tools/trunk/sci/engine/said.y
===================================================================
--- tools/trunk/sci/engine/said.y	                        (rev 0)
+++ tools/trunk/sci/engine/said.y	2009-02-18 11:37:19 UTC (rev 38471)
@@ -0,0 +1,950 @@
+/***************************************************************************
+ said.y Copyright (C) 1999 Christoph Reichenbach
+
+
+ This program may be modified and copied freely according to the terms of
+ the GNU general public license (GPL), as long as the above copyright
+ notice and the licensing information contained herein are preserved.
+
+ Please refer to www.gnu.org for licensing details.
+
+ This work is provided AS IS, without warranty of any kind, expressed or
+ implied, including but not limited to the warranties of merchantibility,
+ noninfringement, and fitness for a specific purpose. The author will not
+ be held liable for any damage caused by this work or derivatives of it.
+
+ By using this source code, you agree to the licensing terms as stated
+ above.
+
+
+ Please contact the maintainer for bug reports or inquiries.
+
+ Current Maintainer:
+
+    Christoph Reichenbach (CJR) [jameson at linuxgames.com]
+
+***************************************************************************/
+
+%{
+
+#include <engine.h>
+
+#define SAID_BRANCH_NULL 0
+
+#define MAX_SAID_TOKENS 128
+
+/* Maximum number of words to be expected in a parsed sentence */
+#define AUGMENT_MAX_WORDS 64
+
+
+#define ANYWORD 0xfff
+
+#define WORD_TYPE_BASE 0x141
+#define WORD_TYPE_REF 0x144
+#define WORD_TYPE_SYNTACTIC_SUGAR 0x145
+
+#define AUGMENT_SENTENCE_PART_BRACKETS 0x152
+
+/* Minor numbers */
+#define AUGMENT_SENTENCE_MINOR_MATCH_PHRASE 0x14c
+#define AUGMENT_SENTENCE_MINOR_MATCH_WORD 0x153
+#define AUGMENT_SENTENCE_MINOR_RECURSE 0x144
+#define AUGMENT_SENTENCE_MINOR_PARENTHESES 0x14f
+
+
+#undef YYDEBUG /*1*/
+/*#define SAID_DEBUG*/
+/*#define SCI_DEBUG_PARSE_TREE_AUGMENTATION*/ /* uncomment to debug parse tree augmentation*/
+
+
+#ifdef SCI_DEBUG_PARSE_TREE_AUGMENTATION
+#define scidprintf sciprintf
+#else
+#define scidprintf if (0) sciprintf
+#endif
+
+
+static char *said_parse_error;
+
+static int said_token;
+static int said_tokens_nr;
+static int said_tokens[MAX_SAID_TOKENS];
+
+static int said_blessed;  /* increminated by said_top_branch */
+
+static int said_tree_pos; /* Set to 0 if we're out of space */
+#define SAID_TREE_START 4; /* Reserve space for the 4 top nodes */
+
+#define VALUE_IGNORE -424242
+
+static parse_tree_node_t said_tree[VOCAB_TREE_NODES];
+
+typedef int wgroup_t;
+typedef int tree_t;
+typedef int said_spec_t;
+
+static tree_t
+said_aug_branch(int, int, tree_t, tree_t);
+
+static tree_t
+said_attach_branch(tree_t, tree_t);
+/*
+static tree_t
+said_wgroup_branch(wgroup_t);
+*/
+static said_spec_t
+said_top_branch(tree_t);
+
+static tree_t
+said_paren(tree_t, tree_t);
+
+static tree_t
+said_value(int, tree_t);
+
+static tree_t
+said_terminal(int);
+
+
+static int
+yylex(void);
+
+static int
+yyerror(char *s)
+{
+	said_parse_error = sci_strdup(s);
+	return 1; /* Abort */
+}
+
+%}
+
+%token WGROUP /* Word group */
+%token YY_COMMA     /* 0xf0 */
+%token YY_AMP       /* 0xf1 */
+%token YY_SLASH     /* 0xf2 */
+%token YY_PARENO    /* 0xf3 */
+%token YY_PARENC    /* 0xf4 */
+%token YY_BRACKETSO /* 0xf5 */
+%token YY_BRACKETSC /* 0xf6 */
+%token YY_HASH      /* 0xf7 */
+%token YY_LT        /* 0xf8 */
+%token YY_GT        /* 0xf9 */
+%token YY_BRACKETSO_LT /* special token used to imitate LR(2) behaviour */
+%token YY_BRACKETSO_SLASH /* special token used to imitate LR(2) behaviour */
+%token YY_LT_BRACKETSO /* special token used to imitate LR(2) behaviour */
+%token YY_LT_PARENO /* special token used to imitate LR(2) behaviour */
+
+%%
+
+saidspec :	  leftspec optcont 
+			{ $$ = said_top_branch(said_attach_branch($1, $2)); } 
+		| leftspec midspec optcont
+			{ $$ = said_top_branch(said_attach_branch($1, said_attach_branch($2, $3))); }
+		| leftspec midspec rightspec optcont
+			{ $$ = said_top_branch(said_attach_branch($1, said_attach_branch($2, said_attach_branch($3, $4)))); }
+		;
+
+
+optcont :	 /* empty */
+			{ $$ = SAID_BRANCH_NULL; }
+		| YY_GT
+			{ $$ = said_paren(said_value(0x14b, said_value(0xf900, said_terminal(0xf900))), SAID_BRANCH_NULL); }
+		;
+
+
+
+leftspec :	/* empty */
+			{ $$ = SAID_BRANCH_NULL; }
+		| expr
+			{ $$ = said_paren(said_value(0x141, said_value(0x149, $1)), SAID_BRANCH_NULL); }
+		;
+
+
+
+midspec :	 YY_SLASH expr
+			{ $$ = said_aug_branch(0x142, 0x14a, $2, SAID_BRANCH_NULL); }
+		| YY_BRACKETSO_SLASH YY_SLASH expr YY_BRACKETSC
+			{ $$ = said_aug_branch(0x152, 0x142, said_aug_branch(0x142, 0x14a, $3, SAID_BRANCH_NULL), SAID_BRANCH_NULL); }
+		| YY_SLASH
+			{ $$ = SAID_BRANCH_NULL; }
+		;
+
+
+
+rightspec :	 YY_SLASH expr
+			{ $$ = said_aug_branch(0x143, 0x14a, $2, SAID_BRANCH_NULL); }
+		| YY_BRACKETSO_SLASH YY_SLASH expr YY_BRACKETSC
+			{ $$ = said_aug_branch(0x152, 0x143, said_aug_branch(0x143, 0x14a, $3, SAID_BRANCH_NULL), SAID_BRANCH_NULL); }
+		| YY_SLASH
+			{ $$ = SAID_BRANCH_NULL; }
+		;
+
+
+
+word :		 WGROUP
+			{ $$ = said_paren(said_value(0x141, said_value(0x153, said_terminal($1))), SAID_BRANCH_NULL); }
+		;
+
+
+cwordset :	wordset
+			{ $$ = said_aug_branch(0x141, 0x14f, $1, SAID_BRANCH_NULL); }
+		| YY_BRACKETSO wordset YY_BRACKETSC
+			{ $$ = said_aug_branch(0x141, 0x14f, said_aug_branch(0x152, 0x14c, said_aug_branch(0x141, 0x14f, $2, SAID_BRANCH_NULL), SAID_BRANCH_NULL), SAID_BRANCH_NULL); }
+		;
+
+
+wordset :	 word
+			{ $$ = $1; }
+		| YY_PARENO expr YY_PARENC
+			{ $$ = $1; }
+		| wordset YY_COMMA wordset
+			{ $$ = said_attach_branch($1, $3); }
+                | wordset YY_BRACKETSO_LT wordrefset YY_BRACKETSC
+			{ $$ = said_attach_branch($1, $3); }
+		| wordset YY_COMMA YY_BRACKETSO wordset YY_BRACKETSC
+			{ $$ = said_attach_branch($1, $3); }
+		;
+
+
+
+expr :		 cwordset cwordrefset
+			{ $$ = said_attach_branch($1, $2); }
+		| cwordset
+			{ $$ = $1; }
+		| cwordrefset
+			{ $$ = $1; }
+		;
+
+
+
+cwordrefset :	 wordrefset
+			{ $$ = $1; }
+		| YY_BRACKETSO_LT wordrefset YY_BRACKETSC
+			{ $$ = said_aug_branch(0x152, 0x144, $2, SAID_BRANCH_NULL); }
+		| wordrefset YY_BRACKETSO_LT wordrefset YY_BRACKETSC
+			{ $$ = said_attach_branch($1, said_aug_branch(0x152, 0x144, $3, SAID_BRANCH_NULL)); }
+		;
+
+
+
+wordrefset :	YY_LT word recref
+			{ $$ = said_aug_branch(0x144, 0x14f, $2, $3); }
+		| YY_LT_PARENO YY_PARENO expr YY_PARENC
+		{ $$ = said_aug_branch(0x144, 0x14f, said_aug_branch(0x141, 0x144, $2, SAID_BRANCH_NULL), SAID_BRANCH_NULL); }
+		| YY_LT wordset
+			{ $$ = said_aug_branch(0x144, 0x14f, $2, SAID_BRANCH_NULL); }
+		| YY_LT_BRACKETSO YY_BRACKETSO wordset YY_BRACKETSC
+			{ $$ = said_aug_branch(0x152, 0x144, said_aug_branch(0x144, 0x14f, $3, SAID_BRANCH_NULL), SAID_BRANCH_NULL); }
+		;
+
+
+
+recref :	YY_LT wordset recref
+			{ $$ = said_aug_branch(0x141, 0x144, said_aug_branch(0x144, 0x14f, $2, SAID_BRANCH_NULL), $3); }
+		| YY_LT wordset
+			{ $$ = said_aug_branch(0x141, 0x144, said_aug_branch(0x144, 0x14f, $2, SAID_BRANCH_NULL), SAID_BRANCH_NULL); }
+		| YY_LT_PARENO YY_PARENO expr YY_PARENC
+		{ $$ = said_aug_branch(0x141, 0x14c, $2, SAID_BRANCH_NULL); }
+		;
+
+
+
+%%
+
+
+int
+parse_yy_token_lookup[] = {YY_COMMA, YY_AMP, YY_SLASH, YY_PARENO, YY_PARENC, YY_BRACKETSO, YY_BRACKETSC,
+			   YY_HASH, YY_LT, YY_GT};
+
+static int
+yylex(void)
+{
+	int retval = said_tokens[said_token++];
+
+	if (retval < SAID_LONG(SAID_FIRST)) {
+		yylval = retval;
+		retval = WGROUP;
+	} else {
+		retval >>= 8;
+
+		if (retval == SAID_TERM)
+			retval = 0;
+		else {
+			assert(retval >= SAID_FIRST);
+			retval = parse_yy_token_lookup[retval - SAID_FIRST];
+			if (retval == YY_BRACKETSO) {
+				if ((said_tokens[said_token] >> 8) == SAID_LT)
+					retval = YY_BRACKETSO_LT;
+				else
+					if ((said_tokens[said_token] >> 8) == SAID_SLASH)
+						retval = YY_BRACKETSO_SLASH;
+			} else if (retval == YY_LT && (said_tokens[said_token] >> 8) == SAID_BRACKO) {
+				retval = YY_LT_BRACKETSO;
+			} else if (retval == YY_LT && (said_tokens[said_token] >> 8) == SAID_PARENO) {
+				retval = YY_LT_PARENO;
+			}
+		}
+	}
+
+	return retval;
+}
+
+#define SAID_NEXT_NODE ((said_tree_pos == 0) || (said_tree_pos >= VOCAB_TREE_NODES))? said_tree_pos = 0 : said_tree_pos++
+
+static inline int
+said_leaf_node(tree_t pos, int value)
+{
+	said_tree[pos].type = PARSE_TREE_NODE_LEAF;
+
+	if (value != VALUE_IGNORE)
+		said_tree[pos].content.value = value;
+
+	return pos;
+}
+
+static inline int
+said_branch_node(tree_t pos, int left, int right)
+{
+	said_tree[pos].type = PARSE_TREE_NODE_BRANCH;
+
+	if (left != VALUE_IGNORE)
+		said_tree[pos].content.branches[0] = left;
+
+	if (right != VALUE_IGNORE)
+		said_tree[pos].content.branches[1] = right;
+
+	return pos;
+}
+
+
+static tree_t
+said_paren(tree_t t1, tree_t t2)
+{
+	if (t1)
+		return said_branch_node(SAID_NEXT_NODE,
+					t1,
+					t2
+					);
+	else
+		return t2;
+}
+
+static tree_t
+said_value(int val, tree_t t)
+{
+	return said_branch_node(SAID_NEXT_NODE,
+				said_leaf_node(SAID_NEXT_NODE, val),
+				t
+				);
+			  
+}
+
+static tree_t
+said_terminal(int val)
+{
+	return said_leaf_node(SAID_NEXT_NODE, val);
+}
+
+
+static tree_t
+said_aug_branch(int n1, int n2, tree_t t1, tree_t t2)
+{
+	int retval;
+
+	retval = said_branch_node(SAID_NEXT_NODE,
+				  said_branch_node(SAID_NEXT_NODE,
+						   said_leaf_node(SAID_NEXT_NODE, n1),
+						   said_branch_node(SAID_NEXT_NODE,
+								    said_leaf_node(SAID_NEXT_NODE, n2),
+								    t1
+								    )
+						   ),
+				  t2
+				  );
+
+#ifdef SAID_DEBUG
+	fprintf(stderr,"AUG(0x%x, 0x%x, [%04x], [%04x]) = [%04x]\n", n1, n2, t1, t2, retval);
+#endif
+
+	return retval;
+}
+
+static tree_t
+said_attach_branch(tree_t base, tree_t attacheant)
+{
+#ifdef SAID_DEBUG
+	fprintf(stderr,"ATT2([%04x], [%04x]) = [%04x]\n", base, attacheant, base);
+#endif
+
+	if (!attacheant)
+		return base;
+	if (!base)
+		return attacheant;
+
+	if (!base)
+		return 0; /* Happens if we're out of space */
+
+	said_branch_node(base, VALUE_IGNORE, attacheant);
+
+	return base;
+}
+
+static said_spec_t
+said_top_branch(tree_t first)
+{
+#ifdef SAID_DEBUG
+	fprintf(stderr, "TOP([%04x])\n", first);
+#endif
+	said_branch_node(0, 1, 2);
+	said_leaf_node(1, 0x141); /* Magic number #1 */
+	said_branch_node(2, 3, first);
+	said_leaf_node(3, 0x13f); /* Magic number #2 */
+
+	++said_blessed;
+
+	return 0;
+}
+
+
+int
+said_parse_spec(state_t *s, byte *spec)
+{
+	int nextitem;
+
+	said_parse_error = NULL;
+	said_token = 0;
+	said_tokens_nr = 0;
+	said_blessed = 0;
+
+	said_tree_pos = SAID_TREE_START;
+
+	do {
+		nextitem = *spec++;
+		if (nextitem < SAID_FIRST)
+			said_tokens[said_tokens_nr++] = nextitem << 8 | *spec++;
+		else
+			said_tokens[said_tokens_nr++] = SAID_LONG(nextitem);
+
+	} while ((nextitem != SAID_TERM) && (said_tokens_nr < MAX_SAID_TOKENS));
+
+	if (nextitem == SAID_TERM)
+		yyparse();
+	else {
+		sciprintf("Error: SAID spec is too long\n");
+		return 1;
+	}
+
+	if (said_parse_error) {
+		sciprintf("Error while parsing SAID spec: %s\n", said_parse_error);
+		free(said_parse_error);
+		return 1;
+	}
+
+	if (said_tree_pos == 0) {
+		sciprintf("Error: Out of tree space while parsing SAID spec\n");
+		return 1;
+	}
+
+	if (said_blessed != 1) {
+		sciprintf("Error: Found %d top branches\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+/**********************/
+/**** Augmentation ****/
+/**********************/
+
+
+/** primitive functions **/
+
+#define AUG_READ_BRANCH(a, br, p) \
+  if (tree[p].type != PARSE_TREE_NODE_BRANCH) \
+    return 0; \
+  a = tree[p].content.branches[br];
+
+#define AUG_READ_VALUE(a, p) \
+  if (tree[p].type != PARSE_TREE_NODE_LEAF) \
+    return 0; \
+  a = tree[p].content.value;
+
+#define AUG_ASSERT(i) \
+  if (!i) return 0;
+
+static int
+aug_get_next_sibling(parse_tree_node_t *tree, int pos, int *first, int *second)
+     /* Returns the next sibling relative to the specified position in 'tree',
+     ** sets *first and *second to its augment node values, returns the new position
+     ** or 0 if there was no next sibling
+     */
+{
+	int seek, valpos;
+
+	AUG_READ_BRANCH(pos, 1, pos);
+	AUG_ASSERT(pos);
+	AUG_READ_BRANCH(seek, 0, pos);
+	AUG_ASSERT(seek);
+
+	/* Now retreive first value */
+	AUG_READ_BRANCH(valpos, 0, seek);
+	AUG_ASSERT(valpos);
+	AUG_READ_VALUE(*first, valpos);
+
+	/* Get second value */
+	AUG_READ_BRANCH(seek, 1, seek);
+	AUG_ASSERT(seek);
+	AUG_READ_BRANCH(valpos, 0, seek);
+	AUG_ASSERT(valpos);
+	AUG_READ_VALUE(*second, valpos);
+
+	return pos;
+}
+
+
+static int
+aug_get_wgroup(parse_tree_node_t *tree, int pos)
+     /* Returns 0 if pos in tree is not the root of a 3-element list, otherwise
+     ** it returns the last element (which, in practice, is the word group
+     */
+{
+	int val;
+
+	AUG_READ_BRANCH(pos, 0, pos);
+	AUG_ASSERT(pos);
+	AUG_READ_BRANCH(pos, 1, pos);
+	AUG_ASSERT(pos);
+	AUG_READ_BRANCH(pos, 1, pos);
+	AUG_ASSERT(pos);
+	AUG_READ_VALUE(val, pos);
+
+	return val;
+}
+
+
+static int
+aug_get_base_node(parse_tree_node_t *tree)
+{
+	int startpos = 0;
+	AUG_READ_BRANCH(startpos, 1, startpos);
+	return startpos;
+}
+
+
+/** semi-primitive functions **/
+
+
+static int
+aug_get_first_child(parse_tree_node_t *tree, int pos, int *first, int *second)
+     /* like aug_get_next_sibling, except that it recurses into the tree and
+     ** finds the first child (usually *not* Ayanami Rei) of the current branch
+     ** rather than its next sibling.
+     */
+{
+	AUG_READ_BRANCH(pos, 0, pos);
+	AUG_ASSERT(pos);
+	AUG_READ_BRANCH(pos, 1, pos);
+	AUG_ASSERT(pos);
+
+	return aug_get_next_sibling(tree, pos, first, second);
+}
+
+static void
+aug_find_words_recursively(parse_tree_node_t *tree, int startpos,
+			   int *base_words, int *base_words_nr,
+			   int *ref_words, int *ref_words_nr,
+			   int maxwords, int refbranch)
+     /* Finds and lists all base (141) and reference (144) words */
+{
+	int major, minor;
+	int word;
+	int pos = aug_get_first_child(tree, startpos, &major, &minor);
+
+	/*	if (major == WORD_TYPE_REF)
+		refbranch = 1;*/
+
+	while (pos) {
+		if ((word = aug_get_wgroup(tree, pos))) { /* found a word */
+
+			if (!refbranch && major == WORD_TYPE_BASE) {	
+				if ((*base_words_nr) == maxwords) {
+					sciprintf("Out of regular words\n");
+					return; /* return gracefully */
+				}
+
+				base_words[*base_words_nr] = word; /* register word */
+				++(*base_words_nr);
+
+			}
+			if (major == WORD_TYPE_REF || refbranch) {
+				if ((*ref_words_nr) == maxwords) {
+					sciprintf("Out of reference words\n");
+					return; /* return gracefully */
+				}
+
+				ref_words[*ref_words_nr] = word; /* register word */
+				++(*ref_words_nr);
+
+			}
+			if (major != WORD_TYPE_SYNTACTIC_SUGAR && major != WORD_TYPE_BASE && major != WORD_TYPE_REF)
+				sciprintf("aug_find_words_recursively(): Unknown word type %03x\n", major);
+    
+		} else /* Did NOT find a word group: Attempt to recurse */
+			aug_find_words_recursively(tree, pos, base_words, base_words_nr,
+						   ref_words, ref_words_nr, maxwords, refbranch || major == WORD_TYPE_REF);
+
+		pos = aug_get_next_sibling(tree, pos, &major, &minor);
+	}
+}
+
+
+static void
+aug_find_words(parse_tree_node_t *tree, int startpos,
+	       int *base_words, int *base_words_nr,
+	       int *ref_words, int *ref_words_nr,
+	       int maxwords)
+     /* initializing wrapper for aug_find_words_recursively() */
+{
+	*base_words_nr = 0;
+	*ref_words_nr = 0;
+
+	aug_find_words_recursively(tree, startpos, base_words, base_words_nr, ref_words, ref_words_nr, maxwords, 0);
+}
+
+
+static inline int
+aug_contains_word(int *list, int length, int word)
+{
+	int i;
+	if (word == ANYWORD)
+		return (length);
+
+	for (i = 0; i < length; i++)
+		if (list[i] == word)
+			return 1;
+
+	return 0;
+}
+
+
+static int
+augment_sentence_expression(parse_tree_node_t *saidt, int augment_pos,
+			    parse_tree_node_t *parset, int parse_branch,
+			    int major, int minor,
+			    int *base_words, int base_words_nr,
+			    int *ref_words, int ref_words_nr);
+
+static int
+augment_match_expression_p(parse_tree_node_t *saidt, int augment_pos,
+			   parse_tree_node_t *parset, int parse_basepos,
+			   int major, int minor,
+			   int *base_words, int base_words_nr,
+			   int *ref_words, int ref_words_nr)
+{
+	int cmajor, cminor, cpos;
+	cpos = aug_get_first_child(saidt, augment_pos, &cmajor, &cminor);
+	if (!cpos) {
+		sciprintf("augment_match_expression_p(): Empty condition\n");
+		return 1;
+	}
+
+	scidprintf("Attempting to match (%03x %03x (%03x %03x\n", major, minor, cmajor, cminor);
+
+	if ((major == WORD_TYPE_BASE) && (minor == AUGMENT_SENTENCE_MINOR_RECURSE))
+		return augment_match_expression_p(saidt, cpos,
+						  parset, parse_basepos,
+						  cmajor, cminor,
+						  base_words, base_words_nr,
+						  ref_words, ref_words_nr);
+
+
+	switch (major) {
+
+	case WORD_TYPE_BASE:
+		while (cpos) {
+			if (cminor == AUGMENT_SENTENCE_MINOR_MATCH_WORD) {
+				int word = aug_get_wgroup(saidt, cpos);
+				scidprintf("Looking for word %03x\n", word);
+
+				if (aug_contains_word(base_words, base_words_nr, word))
+					return 1;
+			} else if (cminor == AUGMENT_SENTENCE_MINOR_MATCH_PHRASE) {
+				if (augment_sentence_expression(saidt, cpos,
+								parset, parse_basepos,
+								cmajor, cminor,
+								base_words, base_words_nr,
+								ref_words, ref_words_nr))
+					return 1;
+			} else if (cminor == AUGMENT_SENTENCE_MINOR_PARENTHESES) {
+				int gc_major, gc_minor;
+				int gchild = aug_get_first_child(saidt, cpos, &gc_major, &gc_minor);
+
+				while (gchild) {
+					if (augment_match_expression_p(saidt, cpos,
+								       parset, parse_basepos,
+								       major, minor,
+								       base_words, base_words_nr,
+								       ref_words, ref_words_nr))
+						return 1;
+					gchild = aug_get_next_sibling(saidt, gchild, &gc_major, &gc_minor);
+				}
+			} else
+				sciprintf("augment_match_expression_p(): Unknown type 141 minor number %3x\n", cminor);
+
+			cpos = aug_get_next_sibling(saidt, cpos, &cmajor, &cminor);
+
+		}
+		break;
+
+	case WORD_TYPE_REF:
+		while (cpos) {
+			if (cminor == AUGMENT_SENTENCE_MINOR_MATCH_WORD) {
+				int word = aug_get_wgroup(saidt, cpos);
+				scidprintf("Looking for refword %03x\n", word);
+
+				if (aug_contains_word(ref_words, ref_words_nr, word))
+					return 1;
+			} else if (cminor == AUGMENT_SENTENCE_MINOR_MATCH_PHRASE) {
+				if (augment_match_expression_p(saidt, cpos,
+							       parset, parse_basepos,
+							       cmajor, cminor,
+							       base_words, base_words_nr,
+							       ref_words, ref_words_nr))
+					return 1;
+			} else if (cminor == AUGMENT_SENTENCE_MINOR_PARENTHESES) {
+				int gc_major, gc_minor;
+				int gchild = aug_get_first_child(saidt, cpos, &gc_major, &gc_minor);
+
+				while (gchild) {
+					if (augment_match_expression_p(saidt, cpos,
+								       parset, parse_basepos,
+								       major, minor,
+								       base_words, base_words_nr,
+								       ref_words, ref_words_nr))
+						return 1;
+					gchild = aug_get_next_sibling(saidt, gchild, &gc_major, &gc_minor);
+				}
+			} else
+				sciprintf("augment_match_expression_p(): Unknown type 144 minor number %3x\n", cminor);
+
+			cpos = aug_get_next_sibling(saidt, cpos, &cmajor, &cminor);
+
+		}
+		break;
+
+	case AUGMENT_SENTENCE_PART_BRACKETS:
+		if (augment_match_expression_p(saidt, cpos,
+					       parset, parse_basepos,
+					       cmajor, cminor,
+					       base_words, base_words_nr,
+					       ref_words, ref_words_nr))
+			return 1;
+
+		scidprintf("Didn't match subexpression; checking sub-bracked predicate %03x\n", cmajor);
+
+		switch (cmajor) {
+		case WORD_TYPE_BASE:
+			if (!base_words_nr)
+				return 1;
+			break;
+
+		case WORD_TYPE_REF:
+			if (!ref_words_nr)
+				return 1;
+			break;
+
+		default:
+			sciprintf("augment_match_expression_p(): (subp1) Unkonwn sub-bracket predicate %03x\n", cmajor);
+		}
+
+		break;
+
+	default:
+		sciprintf("augment_match_expression_p(): Unknown predicate %03x\n", major);
+
+	}
+
+	scidprintf("Generic failure\n");
+	return 0;
+}
+
+static int
+augment_sentence_expression(parse_tree_node_t *saidt, int augment_pos,
+			    parse_tree_node_t *parset, int parse_branch,
+			    int major, int minor,
+			    int *base_words, int base_words_nr,
+			    int *ref_words, int ref_words_nr)
+{
+	int check_major, check_minor;
+	int check_pos = aug_get_first_child(saidt, augment_pos, &check_major, &check_minor);
+	do {
+		if (!(augment_match_expression_p(saidt, check_pos, parset, parse_branch,
+						 check_major, check_minor, base_words, base_words_nr,
+						 ref_words, ref_words_nr)))
+			return 0;
+	} while ((check_pos = aug_get_next_sibling(saidt, check_pos, &check_major, &check_minor)));
+	return 1;
+}
+
+
+
+static int
+augment_sentence_part(parse_tree_node_t *saidt, int augment_pos,
+		      parse_tree_node_t *parset, int parse_basepos,
+		      int major, int minor)
+{
+	int pmajor, pminor;
+	int parse_branch = parse_basepos;
+	int optional = 0;
+	int foundwords = 0;
+
+	scidprintf("Augmenting (%03x %03x\n", major, minor);
+
+	if (major == AUGMENT_SENTENCE_PART_BRACKETS) { /* '[/ foo]' is true if '/foo' or if there
+						       ** exists no x for which '/x' is true
+						       */
+		if ((augment_pos = aug_get_first_child(saidt, augment_pos, &major, &minor))) {
+			scidprintf("Optional part: Now augmenting (%03x %03x\n", major, minor);
+			optional = 1;
+		} else {
+			scidprintf("Matched empty optional expression\n");
+			return 1;
+		}
+	}
+
+	if ((major < 0x141)
+	    || (major > 0x143)) {
+		scidprintf("augment_sentence_part(): Unexpected sentence part major number %03x\n", major);
+		return 0;
+	}
+
+	while ((parse_branch = aug_get_next_sibling(parset, parse_branch, &pmajor, &pminor)))
+		if (pmajor == major) { /* found matching sentence part */
+			int success;
+			int base_words_nr;
+			int ref_words_nr;
+			int base_words[AUGMENT_MAX_WORDS];
+			int ref_words[AUGMENT_MAX_WORDS];
+#ifdef SCI_DEBUG_PARSE_TREE_AUGMENTATION
+			int i;
+#endif
+
+			scidprintf("Found match with pminor = %03x\n", pminor);
+			aug_find_words(parset, parse_branch, base_words, &base_words_nr,
+				       ref_words, &ref_words_nr, AUGMENT_MAX_WORDS);
+			foundwords |= (ref_words_nr | base_words_nr);
+#ifdef SCI_DEBUG_PARSE_TREE_AUGMENTATION
+			sciprintf("%d base words:", base_words_nr);
+			for (i = 0; i < base_words_nr; i++)
+				sciprintf(" %03x", base_words[i]);
+			sciprintf("\n%d reference words:", ref_words_nr);
+			for (i = 0; i < ref_words_nr; i++)
+				sciprintf(" %03x", ref_words[i]);
+			sciprintf("\n");
+#endif
+
+			success = augment_sentence_expression(saidt, augment_pos,
+							      parset, parse_basepos, major, minor,
+							      base_words, base_words_nr,
+							      ref_words, ref_words_nr);
+
+			if (success) {
+				scidprintf("SUCCESS on augmenting (%03x %03x\n", major, minor);
+				return 1;
+			}
+		}
+
+	if (optional && (foundwords == 0)) {
+		scidprintf("Found no words and optional branch => SUCCESS on augmenting (%03x %03x\n", major, minor);
+		return 1;
+	}
+	scidprintf("FAILURE on augmenting (%03x %03x\n", major, minor);
+	return 0;
+}
+
+static int
+augment_parse_nodes(parse_tree_node_t *parset, parse_tree_node_t *saidt)
+{
+	int augment_basepos = 0;
+	int parse_basepos;
+	int major, minor;
+	int dontclaim = 0;
+
+	parse_basepos = aug_get_base_node(parset);
+	if (!parse_basepos) {
+		sciprintf("augment_parse_nodes(): Parse tree is corrupt\n");
+		return 0;
+	}
+  
+	augment_basepos = aug_get_base_node(saidt);
+	if (!augment_basepos) {
+		sciprintf("augment_parse_nodes(): Said tree is corrupt\n");
+		return 0;
+	}
+	while ((augment_basepos = aug_get_next_sibling(saidt, augment_basepos, &major, &minor))) {
+
+		if ((major == 0x14b)
+		    && (minor == SAID_LONG(SAID_GT)))
+			dontclaim = 1; /* special case */
+		else /* normal sentence part */
+			if (!(augment_sentence_part(saidt, augment_basepos, parset, parse_basepos, major, minor))) {
+				scidprintf("Returning failure\n");
+				return 0; /* fail */
+			}
+	}
+
+	scidprintf("Returning success with dontclaim=%d\n", dontclaim);
+
+	if (dontclaim)
+		return SAID_PARTIAL_MATCH;
+	else return 1; /* full match */
+}
+
+
+/*******************/
+/**** Main code ****/
+/*******************/
+
+int
+said(state_t *s, byte *spec, int verbose)
+{
+	int retval;
+
+	parse_tree_node_t *parse_tree_ptr = s->parser_nodes;
+
+	if (s->parser_valid) {
+
+		if (said_parse_spec(s, spec)) {
+			sciprintf("Offending spec was: ");
+			vocab_decypher_said_block(s, spec);
+			return SAID_NO_MATCH;
+		}
+
+		if (verbose)
+			vocab_dump_parse_tree("Said-tree", said_tree); /* Nothing better to do yet */
+		retval = augment_parse_nodes(parse_tree_ptr, &(said_tree[0]));
+
+		if (!retval)
+			return SAID_NO_MATCH;
+		else if (retval != SAID_PARTIAL_MATCH)
+			return SAID_FULL_MATCH;
+		else return SAID_PARTIAL_MATCH;
+	}
+
+	return SAID_NO_MATCH;
+}
+
+
+
+#ifdef SAID_DEBUG_PROGRAM
+int
+main (int argc, char *argv)
+{
+	byte block[] = {0x01, 0x00, 0xf8, 0xf5, 0x02, 0x01, 0xf6, 0xf2, 0x02, 0x01, 0xf2, 0x01, 0x03, 0xff};
+	state_t s;
+	con_passthrough = 1;
+
+	s.parser_valid = 1;
+	said(&s, block);
+}
+#endif


Property changes on: tools/trunk/sci/engine/said.y
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list