Back to List Inventory Complete Backward Forward Plain Coloured Gaudy This code in plain text |
Browsing parserm.h
NounDomain (lines 2002-2302)
2002 ! NounDomain does the most substantial part of parsing an object name.
2003 !
2004 ! It is given two "domains" - usually a location and then the actor who is
2005 ! looking - and a context (i.e. token type), and returns:
2006 !
2007 ! 0 if no match at all could be made,
2008 ! 1 if a multiple object was made,
2009 ! k if object k was the one decided upon,
2010 ! REPARSE_CODE if it asked a question of the player and consequently rewrote
2011 ! the player's input, so that the whole parser should start again
2012 ! on the rewritten input.
2013 !
2014 ! In the case when it returns 1
2015 ! length_of_noun to the number of words in the input text matched to the
2016 ! noun.
2017 ! In the case k=1, the multiple objects are added to multiple_object by
2018 ! hand (not by MultiAdd, because we want to allow duplicates).
2019 ! ----------------------------------------------------------------------------
2020
2021 [ NounDomain domain1 domain2 context first_word i j k l
2022 answer_words marker;
2023
2024 #ifdef DEBUG;
2025 if (parser_trace>=4)
2026 { print " [NounDomain called at word ", wn, "^";
2027 print " ";
2028 if (indef_mode)
2029 { print "seeking indefinite object: ";
2030 if (indef_type & OTHER_BIT) print "other ";
2031 if (indef_type & MY_BIT) print "my ";
2032 if (indef_type & THAT_BIT) print "that ";
2033 if (indef_type & PLURAL_BIT) print "plural ";
2034 if (indef_type & LIT_BIT) print "lit ";
2035 if (indef_type & UNLIT_BIT) print "unlit ";
2036 if (indef_owner ~= 0) print "owner:", (name) indef_owner;
2037 new_line;
2038 print " number wanted: ";
2039 if (indef_wanted == 100) print "all"; else print indef_wanted;
2040 new_line;
2041 print " most likely GNAs of names: ", indef_cases, "^";
2042 }
2043 else print "seeking definite object^";
2044 }
2045 #endif;
2046
2047 match_length=0; number_matched=0; match_from=wn; placed_in_flag=0;
2048
2049 SearchScope(domain1, domain2, context);
2050
2051 #ifdef DEBUG;
2052 if (parser_trace>=4) print " [ND made ", number_matched, " matches]^";
2053 #endif;
2054
2055 wn=match_from+match_length;
2056
2057 ! If nothing worked at all, leave with the word marker skipped past the
2058 ! first unmatched word...
2059
2060 if (number_matched==0) { wn++; rfalse; }
2061
2062 ! Suppose that there really were some words being parsed (i.e., we did
2063 ! not just infer). If so, and if there was only one match, it must be
2064 ! right and we return it...
2065
2066 if (match_from <= num_words)
2067 { if (number_matched==1) { i=match_list-->0; return i; }
2068
2069 ! ...now suppose that there was more typing to come, i.e. suppose that
2070 ! the user entered something beyond this noun. If nothing ought to follow,
2071 ! then there must be a mistake, (unless what does follow is just a full
2072 ! stop, and or comma)
2073
2074 if (wn<=num_words)
2075 { i=NextWord(); wn--;
2076 if (i ~= AND1__WD or AND2__WD or AND3__WD or comma_word
2077 or THEN1__WD or THEN2__WD or THEN3__WD
2078 or BUT1__WD or BUT2__WD or BUT3__WD)
2079 { if (lookahead==ENDIT_TOKEN) rfalse;
2080 }
2081 }
2082 }
2083
2084 ! Now look for a good choice, if there's more than one choice...
2085
2086 number_of_classes=0;
2087
2088 if (number_matched==1) i=match_list-->0;
2089 if (number_matched>1)
2090 { i=Adjudicate(context);
2091 if (i==-1) rfalse;
2092 if (i==1) rtrue; ! Adjudicate has made a multiple
2093 ! object, and we pass it on
2094 }
2095
2096 ! If i is non-zero here, one of two things is happening: either
2097 ! (a) an inference has been successfully made that object i is
2098 ! the intended one from the user's specification, or
2099 ! (b) the user finished typing some time ago, but we've decided
2100 ! on i because it's the only possible choice.
2101 ! In either case we have to keep the pattern up to date,
2102 ! note that an inference has been made and return.
2103 ! (Except, we don't note which of a pile of identical objects.)
2104
2105 if (i~=0)
2106 { if (dont_infer) return i;
2107 if (inferfrom==0) inferfrom=pcount;
2108 pattern-->pcount = i;
2109 return i;
2110 }
2111
2112 ! If we get here, there was no obvious choice of object to make. If in
2113 ! fact we've already gone past the end of the player's typing (which
2114 ! means the match list must contain every object in scope, regardless
2115 ! of its name), then it's foolish to give an enormous list to choose
2116 ! from - instead we go and ask a more suitable question...
2117
2118 if (match_from > num_words) jump Incomplete;
2119
2120 ! Now we print up the question, using the equivalence classes as worked
2121 ! out by Adjudicate() so as not to repeat ourselves on plural objects...
2122
2123 if (context==CREATURE_TOKEN)
2124 L__M(##Miscellany, 45); else L__M(##Miscellany, 46);
2125
2126 j=number_of_classes; marker=0;
2127 for (i=1:i<=number_of_classes:i++)
2128 {
2129 while (((match_classes-->marker) ~= i)
2130 && ((match_classes-->marker) ~= -i)) marker++;
2131 k=match_list-->marker;
2132
2133 if (match_classes-->marker > 0) print (the) k; else print (a) k;
2134
2135 if (i<j-1) print ", ";
2136 if (i==j-1) print (string) OR__TX;
2137 }
2138 print "?^";
2139
2140 ! ...and get an answer:
2141
2142 .WhichOne;
2143 for (i=2:i<120:i++) buffer2->i=' ';
2144 answer_words=Keyboard(buffer2, parse2);
2145
2146 first_word=(parse2-->1);
2147
2148 ! Take care of "all", because that does something too clever here to do
2149 ! later on:
2150
2151 if (first_word == ALL1__WD or ALL2__WD or ALL3__WD or ALL4__WD or ALL5__WD)
2152 {
2153 if (context == MULTI_TOKEN or MULTIHELD_TOKEN or MULTIEXCEPT_TOKEN
2154 or MULTIINSIDE_TOKEN)
2155 { l=multiple_object-->0;
2156 for (i=0:i<number_matched && l+i<63:i++)
2157 { k=match_list-->i;
2158 multiple_object-->(i+1+l) = k;
2159 }
2160 multiple_object-->0 = i+l;
2161 rtrue;
2162 }
2163 L__M(##Miscellany, 47);
2164 jump WhichOne;
2165 }
2166
2167 ! If the first word of the reply can be interpreted as a verb, then
2168 ! assume that the player has ignored the question and given a new
2169 ! command altogether.
2170 ! (This is one time when it's convenient that the directions are
2171 ! not themselves verbs - thus, "north" as a reply to "Which, the north
2172 ! or south door" is not treated as a fresh command but as an answer.)
2173
2174 #ifdef LanguageIsVerb;
2175 if (first_word==0)
2176 { j = wn; first_word=LanguageIsVerb(buffer2, parse2, 1); wn = j;
2177 }
2178 #endif;
2179 if (first_word ~= 0)
2180 { j=first_word->#dict_par1;
2181 if ((0~=j&1) && (first_word ~= 'long' or 'short' or 'normal'
2182 or 'brief' or 'full' or 'verbose'))
2183 { CopyBuffer(buffer, buffer2);
2184 return REPARSE_CODE;
2185 }
2186 }
2187
2188 ! Now we insert the answer into the original typed command, as
2189 ! words additionally describing the same object
2190 ! (eg, > take red button
2191 ! Which one, ...
2192 ! > music
2193 ! becomes "take music red button". The parser will thus have three
2194 ! words to work from next time, not two.)
2195
2196 k = WordAddress(match_from) - buffer; l=buffer2->1+1;
2197 for (j=buffer + buffer->0 - 1: j>= buffer+k+l: j--)
2198 j->0 = 0->(j-l);
2199 for (i=0:i<l:i++) buffer->(k+i) = buffer2->(2+i);
2200 buffer->(k+l-1) = ' ';
2201 buffer->1 = buffer->1 + l;
2202 if (buffer->1 >= (buffer->0 - 1)) buffer->1 = buffer->0;
2203
2204 ! Having reconstructed the input, we warn the parser accordingly
2205 ! and get out.
2206
2207 return REPARSE_CODE;
2208
2209 ! Now we come to the question asked when the input has run out
2210 ! and can't easily be guessed (eg, the player typed "take" and there
2211 ! were plenty of things which might have been meant).
2212
2213 .Incomplete;
2214
2215 if (context==CREATURE_TOKEN)
2216 L__M(##Miscellany, 48); else L__M(##Miscellany, 49);
2217
2218 for (i=2:i<120:i++) buffer2->i=' ';
2219 answer_words=Keyboard(buffer2, parse2);
2220
2221 first_word=(parse2-->1);
2222 #ifdef LanguageIsVerb;
2223 if (first_word==0)
2224 { j = wn; first_word=LanguageIsVerb(buffer2, parse2, 1); wn = j;
2225 }
2226 #endif;
2227
2228 ! Once again, if the reply looks like a command, give it to the
2229 ! parser to get on with and forget about the question...
2230
2231 if (first_word ~= 0)
2232 { j=first_word->#dict_par1;
2233 if (0~=j&1)
2234 { CopyBuffer(buffer, buffer2);
2235 return REPARSE_CODE;
2236 }
2237 }
2238
2239 ! ...but if we have a genuine answer, then:
2240 !
2241 ! (1) we must glue in text suitable for anything that's been inferred.
2242
2243 if (inferfrom ~= 0)
2244 { for (j = inferfrom: j<pcount: j++)
2245 { if (pattern-->j == PATTERN_NULL) continue;
2246 i=2+buffer->1; (buffer->1)++; buffer->(i++) = ' ';
2247
2248 if (parser_trace >= 5)
2249 print "[Gluing in inference with pattern code ", pattern-->j, "]^";
2250
2251 parse2-->1 = 0;
2252
2253 ! An inferred object. Best we can do is glue in a pronoun.
2254 ! (This is imperfect, but it's very seldom needed anyway.)
2255
2256 if (pattern-->j >= 2 && pattern-->j < REPARSE_CODE)
2257 { PronounNotice(pattern-->j);
2258 for (k=1: k<=LanguagePronouns-->0: k=k+3)
2259 if (pattern-->j == LanguagePronouns-->(k+2))
2260 { parse2-->1 = LanguagePronouns-->k;
2261 if (parser_trace >= 5)
2262 print "[Using pronoun '", (address) parse2-->1, "']^";
2263 break;
2264 }
2265 }
2266 else
2267 { ! An inferred preposition.
2268 parse2-->1 = No__Dword(pattern-->j - REPARSE_CODE);
2269 if (parser_trace >= 5)
2270 print "[Using preposition '", (address) parse2-->1, "']^";
2271 }
2272
2273 ! parse2-->1 now holds the dictionary address of the word to glue in.
2274
2275 if (parse2-->1 ~= 0)
2276 { k = buffer + i;
2277 @output_stream 3 k;
2278 print (address) parse2-->1;
2279 @output_stream -3;
2280 k = k-->0;
2281 for (l=i:l<i+k:l++) buffer->l = buffer->(l+2);
2282 i = i + k; buffer->1 = i-2;
2283 }
2284 }
2285 }
2286
2287 ! (2) we must glue the newly-typed text onto the end.
2288
2289 i=2+buffer->1; (buffer->1)++; buffer->(i++) = ' ';
2290 for (j=0: j<buffer2->1: i++, j++)
2291 { buffer->i = buffer2->(j+2);
2292 (buffer->1)++;
2293 if (buffer->1 == 120) break;
2294 }
2295
2296 ! (3) we fill up the buffer with spaces, which is unnecessary, but may
2297 ! help incorrectly-written interpreters to cope.
2298
2299 for (:i<120:i++) buffer->i = ' ';
2300
2301 return REPARSE_CODE;
2302 ];
|