diff options
author | Johannes Schickel | 2010-10-13 03:57:44 +0000 |
---|---|---|
committer | Johannes Schickel | 2010-10-13 03:57:44 +0000 |
commit | 75e8452b6e6a2bf4fb2f588aa00b428a60d873b5 (patch) | |
tree | f29541d55309487a94bd1d38e8b53bb3dde9aec6 /engines/sci/parser/grammar.cpp | |
parent | 48ee83b88957dab86bc763e9ef21a70179fa8679 (diff) | |
parent | e9f50882ea5b6beeefa994040be9d3bab6a1f107 (diff) | |
download | scummvm-rg350-75e8452b6e6a2bf4fb2f588aa00b428a60d873b5.tar.gz scummvm-rg350-75e8452b6e6a2bf4fb2f588aa00b428a60d873b5.tar.bz2 scummvm-rg350-75e8452b6e6a2bf4fb2f588aa00b428a60d873b5.zip |
OPENGL: Merged from trunk, from rev 52105 to 53396.
This includes an rather hacky attempt to merge all the recent gp2x backend
changes into the branch. I suppose the gp2x backend and probably all new
backends, i.e. gph, dingux etc., might not compile anymore.
Since I have no way of testing those it would be nice if porters could look
into getting those up to speed in this branch.
svn-id: r53399
Diffstat (limited to 'engines/sci/parser/grammar.cpp')
-rw-r--r-- | engines/sci/parser/grammar.cpp | 88 |
1 files changed, 69 insertions, 19 deletions
diff --git a/engines/sci/parser/grammar.cpp b/engines/sci/parser/grammar.cpp index 6f37b49919..03e9d29660 100644 --- a/engines/sci/parser/grammar.cpp +++ b/engines/sci/parser/grammar.cpp @@ -38,8 +38,9 @@ namespace Sci { #define TOKEN_CPAREN 0xfe000000 #define TOKEN_TERMINAL_CLASS 0x10000 #define TOKEN_TERMINAL_GROUP 0x20000 -#define TOKEN_STUFFING_WORD 0x40000 -#define TOKEN_NON_NT (TOKEN_OPAREN | TOKEN_TERMINAL_CLASS | TOKEN_TERMINAL_GROUP | TOKEN_STUFFING_WORD) +#define TOKEN_STUFFING_LEAF 0x40000 +#define TOKEN_STUFFING_WORD 0x80000 +#define TOKEN_NON_NT (TOKEN_OPAREN | TOKEN_TERMINAL_CLASS | TOKEN_TERMINAL_GROUP | TOKEN_STUFFING_LEAF | TOKEN_STUFFING_WORD) #define TOKEN_TERMINAL (TOKEN_TERMINAL_CLASS | TOKEN_TERMINAL_GROUP) static int _allocd_rules = 0; // FIXME: Avoid non-const global vars @@ -122,8 +123,10 @@ static void vocab_print_rule(ParseRule *rule) { printf("C(%04x)", token & 0xffff); else if (token & TOKEN_TERMINAL_GROUP) printf("G(%04x)", token & 0xffff); - else if (token & TOKEN_STUFFING_WORD) + else if (token & TOKEN_STUFFING_LEAF) printf("%03x", token & 0xffff); + else if (token & TOKEN_STUFFING_WORD) + printf("{%03x}", token & 0xffff); else printf("[%03x]", token); /* non-terminal */ wspace = 1; @@ -206,8 +209,8 @@ static ParseRule *_vbuild_rule(const parse_tree_branch_t *branch) { rule->_data[tokens++] = value | TOKEN_STUFFING_WORD; else { // normal inductive rule rule->_data[tokens++] = TOKEN_OPAREN; - rule->_data[tokens++] = type | TOKEN_STUFFING_WORD; - rule->_data[tokens++] = value | TOKEN_STUFFING_WORD; + rule->_data[tokens++] = type | TOKEN_STUFFING_LEAF; + rule->_data[tokens++] = value | TOKEN_STUFFING_LEAF; if (i == 0) rule->_firstSpecial = tokens; @@ -220,7 +223,7 @@ static ParseRule *_vbuild_rule(const parse_tree_branch_t *branch) { return rule; } -static ParseRule *_vsatisfy_rule(ParseRule *rule, const ResultWord &input) { +static ParseRule *_vsatisfy_rule(ParseRule *rule, const ResultWordList &input) { int dep; if (!rule->_numSpecials) @@ -228,11 +231,32 @@ static ParseRule *_vsatisfy_rule(ParseRule *rule, const ResultWord &input) { dep = rule->_data[rule->_firstSpecial]; - if (((dep & TOKEN_TERMINAL_CLASS) && ((dep & 0xffff) & input._class)) || - ((dep & TOKEN_TERMINAL_GROUP) && ((dep & 0xffff) & input._group))) { + int count = 0; + int match = 0; + ResultWordList::const_iterator iter; + // TODO: Inserting an array in the middle of another array is slow + Common::Array<int> matches; + matches.reserve(input.size()); + + // We store the first match in 'match', and any subsequent matches in + // 'matches'. 'match' replaces the special in the rule, and 'matches' gets + // inserted after it. + for (iter = input.begin(); iter != input.end(); ++iter) + if (((dep & TOKEN_TERMINAL_CLASS) && ((dep & 0xffff) & iter->_class)) || + ((dep & TOKEN_TERMINAL_GROUP) && ((dep & 0xffff) & iter->_group))) { + if (count == 0) + match = TOKEN_STUFFING_WORD | iter->_group; + else + matches.push_back(TOKEN_STUFFING_WORD | iter->_group); + count++; + } + + if (count) { ParseRule *retval = new ParseRule(*rule); ++_allocd_rules; - retval->_data[rule->_firstSpecial] = TOKEN_STUFFING_WORD | input._group; + retval->_data[rule->_firstSpecial] = match; + if (count > 1) + retval->_data.insert_at(rule->_firstSpecial+1, matches); retval->_numSpecials--; retval->_firstSpecial = 0; @@ -277,10 +301,8 @@ static ParseRuleList *_vocab_add_rule(ParseRuleList *list, ParseRule *rule) { while (seeker->next/* && seeker->next->terminal <= term*/) { if (seeker->next->terminal == term) { if (*(seeker->next->rule) == *rule) { - delete rule; - // FIXME: not sure about this change, fixes pq2 crashing when having opened the cabinet - // and typing "go to bains" - delete rule deletes part of new_elem - //delete new_elem; + delete new_elem; // NB: This also deletes 'rule' + return list; // No duplicate rules } } @@ -445,6 +467,7 @@ static int _vbpt_append(ParseTreeNode *nodes, int *pos, int base, int value) { nodes[base].left = &nodes[++(*pos)]; nodes[*pos].type = kParseTreeLeafNode; nodes[*pos].value = value; + nodes[*pos].right = 0; nodes[base].right = &nodes[++(*pos)]; nodes[*pos].type = kParseTreeBranchNode; nodes[*pos].left = 0; @@ -456,9 +479,29 @@ static int _vbpt_terminate(ParseTreeNode *nodes, int *pos, int base, int value) // Terminates, overwriting a nextwrite forknode nodes[base].type = kParseTreeLeafNode; nodes[base].value = value; + nodes[base].right = 0; + return *pos; +} +static int _vbpt_append_word(ParseTreeNode *nodes, int *pos, int base, int value) { + // writes one value to an existing node and creates a sibling for writing + nodes[base].type = kParseTreeWordNode; + nodes[base].value = value; + nodes[base].right = &nodes[++(*pos)]; + nodes[*pos].type = kParseTreeBranchNode; + nodes[*pos].left = 0; + nodes[*pos].right = 0; + return *pos; +} + +static int _vbpt_terminate_word(ParseTreeNode *nodes, int *pos, int base, int value) { + // Terminates, overwriting a nextwrite forknode + nodes[base].type = kParseTreeWordNode; + nodes[base].value = value; + nodes[base].right = 0; return *pos; } + static int _vbpt_write_subexpression(ParseTreeNode *nodes, int *pos, ParseRule *rule, uint rulepos, int writepos) { uint token; @@ -470,11 +513,16 @@ static int _vbpt_write_subexpression(ParseTreeNode *nodes, int *pos, ParseRule * nexttoken = (rulepos < rule->_data.size()) ? rule->_data[rulepos] : TOKEN_CPAREN; if (nexttoken != TOKEN_CPAREN) writepos = _vbpt_parenc(nodes, pos, writepos); - } else if (token & TOKEN_STUFFING_WORD) { + } else if (token & TOKEN_STUFFING_LEAF) { if (nexttoken == TOKEN_CPAREN) writepos = _vbpt_terminate(nodes, pos, writepos, token & 0xffff); else writepos = _vbpt_append(nodes, pos, writepos, token & 0xffff); + } else if (token & TOKEN_STUFFING_WORD) { + if (nexttoken == TOKEN_CPAREN) + writepos = _vbpt_terminate_word(nodes, pos, writepos, token & 0xffff); + else + writepos = _vbpt_append_word(nodes, pos, writepos, token & 0xffff); } else { printf("\nError in parser (grammar.cpp, _vbpt_write_subexpression()): Rule data broken in rule "); vocab_print_rule(rule); @@ -486,16 +534,16 @@ static int _vbpt_write_subexpression(ParseTreeNode *nodes, int *pos, ParseRule * return rulepos; } -int Vocabulary::parseGNF(const ResultWordList &words, bool verbose) { +int Vocabulary::parseGNF(const ResultWordListList &words, bool verbose) { Console *con = g_sci->getSciDebugger(); // Get the start rules: ParseRuleList *work = _vocab_clone_rule_list_by_id(_parserRules, _parserBranches[0].data[1]); ParseRuleList *results = NULL; uint word = 0; const uint words_nr = words.size(); - ResultWordList::const_iterator word_iter = words.begin(); + ResultWordListList::const_iterator words_iter; - for (word_iter = words.begin(); word_iter != words.end(); ++word_iter, ++word) { + for (words_iter = words.begin(); words_iter != words.end(); ++words_iter, ++word) { ParseRuleList *new_work = NULL; ParseRuleList *reduced_rules = NULL; ParseRuleList *seeker, *subseeker; @@ -505,8 +553,9 @@ int Vocabulary::parseGNF(const ResultWordList &words, bool verbose) { seeker = work; while (seeker) { - if (seeker->rule->_numSpecials <= (words_nr - word)) - reduced_rules = _vocab_add_rule(reduced_rules, _vsatisfy_rule(seeker->rule, *word_iter)); + if (seeker->rule->_numSpecials <= (words_nr - word)) { + reduced_rules = _vocab_add_rule(reduced_rules, _vsatisfy_rule(seeker->rule, *words_iter)); + } seeker = seeker->next; } @@ -570,6 +619,7 @@ int Vocabulary::parseGNF(const ResultWordList &words, bool verbose) { _parserNodes[1].type = kParseTreeLeafNode; _parserNodes[1].value = 0x141; + _parserNodes[1].right = 0; _parserNodes[2].type = kParseTreeBranchNode; _parserNodes[2].left = 0; |