diff options
Diffstat (limited to 'engines/sci/engine/said.y')
-rw-r--r-- | engines/sci/engine/said.y | 950 |
1 files changed, 950 insertions, 0 deletions
diff --git a/engines/sci/engine/said.y b/engines/sci/engine/said.y new file mode 100644 index 0000000000..fdef2360ae --- /dev/null +++ b/engines/sci/engine/said.y @@ -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@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 |