Inform - Support - Source

Back to List

Inventory
Complete

Backward
Forward

Plain
Coloured
Gaudy

This code
in plain text

Browsing parserm.h

ParseToken__ (lines 2244-2687)

2244  [ ParseToken__ given_ttype given_tdata token_n
2245               token l o i j k and_parity single_object desc_wn many_flag
2246               token_allows_multiple prev_indef_wanted;
2247   
2248      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2249      !
2250      ! A: Analyse token; handle all not involving object lists, break down others
2251      !
2252      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2253   
2254      token_filter = 0;
2255   
2256      switch (given_ttype) {
2257        ELEMENTARY_TT:
2258          switch (given_tdata) {
2259            SPECIAL_TOKEN:
2260              l = TryNumber(wn);
2261              special_word = NextWord();
2262              #Ifdef DEBUG;
2263              if (l ~= -1000)
2264                  if (parser_trace >= 3) print "  [Read special as the number ", l, "]^";
2265              #Endif; ! DEBUG
2266              if (l == -1000) {
2267                  #Ifdef DEBUG;
2268                  if (parser_trace >= 3) print "  [Read special word at word number ", wn, "]^";
2269                  #Endif; ! DEBUG
2270                  l = special_word;
2271              }
2272              parsed_number = l; return GPR_NUMBER;
2273   
2274            NUMBER_TOKEN:
2275              l=TryNumber(wn++);
2276              if (l == -1000) { etype = NUMBER_PE; return GPR_FAIL; }
2277              #Ifdef DEBUG;
2278              if (parser_trace>=3) print "  [Read number as ", l, "]^";
2279              #Endif; ! DEBUG
2280              parsed_number = l; return GPR_NUMBER;
2281   
2282            CREATURE_TOKEN:
2283              if (action_to_be == ##Answer or ##Ask or ##AskFor or ##Tell)
2284                  scope_reason = TALKING_REASON;
2285   
2286            TOPIC_TOKEN:
2287              consult_from = wn;
2288              if ((line_ttype-->(token_n+1) ~= PREPOSITION_TT) &&
2289                 (line_token-->(token_n+1) ~= ENDIT_TOKEN))
2290                  RunTimeError(13);
2291              do o = NextWordStopped();
2292              until (o == -1 || PrepositionChain(o, token_n+1) ~= -1);
2293              wn--;
2294              consult_words = wn-consult_from;
2295              if (consult_words == 0) return GPR_FAIL;
2296              if (action_to_be == ##Ask or ##Answer or ##Tell) {
2297                  o = wn; wn = consult_from; parsed_number = NextWord();
2298                  #Ifdef EnglishNaturalLanguage;
2299                  if (parsed_number == 'the' && consult_words > 1) parsed_number=NextWord();
2300                  #Endif; ! EnglishNaturalLanguage
2301                  wn = o; return 1;
2302              }
2303              if (o==-1 && (line_ttype-->(token_n+1) == PREPOSITION_TT))
2304                  return GPR_FAIL;    ! don't infer if required preposition is absent
2305              return GPR_PREPOSITION;
2306          }
2307   
2308        PREPOSITION_TT:
2309          #Iffalse (Grammar__Version == 1);
2310          ! Is it an unnecessary alternative preposition, when a previous choice
2311          ! has already been matched?
2312          if ((token->0) & $10) return GPR_PREPOSITION;
2313          #Endif; ! Grammar__Version
2314   
2315          ! If we've run out of the player's input, but still have parameters to
2316          ! specify, we go into "infer" mode, remembering where we are and the
2317          ! preposition we are inferring...
2318   
2319          if (wn > num_words) {
2320              if (inferfrom==0 && parameters<params_wanted) {
2321                  inferfrom = pcount; inferword = token;
2322                  pattern-->pcount = REPARSE_CODE + Dword__No(given_tdata);
2323              }
2324   
2325              ! If we are not inferring, then the line is wrong...
2326   
2327              if (inferfrom == 0) return -1;
2328   
2329              ! If not, then the line is right but we mark in the preposition...
2330   
2331              pattern-->pcount = REPARSE_CODE + Dword__No(given_tdata);
2332              return GPR_PREPOSITION;
2333          }
2334   
2335          o = NextWord();
2336   
2337          pattern-->pcount = REPARSE_CODE + Dword__No(o);
2338   
2339          ! Whereas, if the player has typed something here, see if it is the
2340          ! required preposition... if it's wrong, the line must be wrong,
2341          ! but if it's right, the token is passed (jump to finish this token).
2342   
2343          if (o == given_tdata) return GPR_PREPOSITION;
2344          #Iffalse (Grammar__Version == 1);
2345          if (PrepositionChain(o, token_n) ~= -1) return GPR_PREPOSITION;
2346          #Endif; ! Grammar__Version
2347          return -1;
2348   
2349        GPR_TT:
2350          l = indirect(given_tdata);
2351          #Ifdef DEBUG;
2352          if (parser_trace >= 3) print "  [Outside parsing routine returned ", l, "]^";
2353          #Endif; ! DEBUG
2354          return l;
2355   
2356        SCOPE_TT:
2357          scope_token = given_tdata;
2358          scope_stage = 1;
2359          l = indirect(scope_token);
2360          #Ifdef DEBUG;
2361          if (parser_trace >= 3) print "  [Scope routine returned multiple-flag of ", l, "]^";
2362          #Endif; ! DEBUG
2363          if (l == 1) given_tdata = MULTI_TOKEN; else given_tdata = NOUN_TOKEN;
2364   
2365        ATTR_FILTER_TT:
2366          token_filter = 1 + given_tdata;
2367          given_tdata = NOUN_TOKEN;
2368   
2369        ROUTINE_FILTER_TT:
2370          token_filter = given_tdata;
2371          given_tdata = NOUN_TOKEN;
2372   
2373      } ! end of switch(given_ttype)
2374   
2375      token = given_tdata;
2376   
2377      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2378      !
2379      ! B: Begin parsing an object list
2380      !
2381      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2382   
2383      ! There are now three possible ways we can be here:
2384      !     parsing an elementary token other than "special" or "number";
2385      !     parsing a scope token;
2386      !     parsing a noun-filter token (either by routine or attribute).
2387      !
2388      ! In each case, token holds the type of elementary parse to
2389      ! perform in matching one or more objects, and
2390      ! token_filter is 0 (default), an attribute + 1 for an attribute filter
2391      ! or a routine address for a routine filter.
2392   
2393      token_allows_multiple = false;
2394      if (token == MULTI_TOKEN or MULTIHELD_TOKEN or MULTIEXCEPT_TOKEN or MULTIINSIDE_TOKEN)
2395          token_allows_multiple = true;
2396   
2397      many_flag = false; and_parity = true; dont_infer = false;
2398   
2399      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2400      !
2401      ! C: Parse descriptors (articles, pronouns, etc.) in the list
2402      !
2403      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2404   
2405      ! We expect to find a list of objects next in what the player's typed.
2406   
2407    .ObjectList;
2408   
2409      #Ifdef DEBUG;
2410      if (parser_trace >= 3) print "  [Object list from word ", wn, "]^";
2411      #Endif; ! DEBUG
2412   
2413      ! Take an advance look at the next word: if it's "it" or "them", and these
2414      ! are unset, set the appropriate error number and give up on the line
2415      ! (if not, these are still parsed in the usual way - it is not assumed
2416      ! that they still refer to something in scope)
2417   
2418      o = NextWord(); wn--;
2419   
2420      pronoun_word = NULL; pronoun_obj = NULL;
2421      l = PronounValue(o);
2422      if (l ~= 0) {
2423          pronoun_word = o; pronoun_obj = l;
2424          if (l == NULL) {
2425              ! Don't assume this is a use of an unset pronoun until the
2426              ! descriptors have been checked, because it might be an
2427              ! article (or some such) instead
2428   
2429              for (l=1 : l<=LanguageDescriptors-->0 : l=l+4)
2430                  if (o == LanguageDescriptors-->l) jump AssumeDescriptor;
2431              pronoun__word = pronoun_word; pronoun__obj = pronoun_obj;
2432              etype = VAGUE_PE; return GPR_FAIL;
2433          }
2434      }
2435   
2436    .AssumeDescriptor;
2437   
2438      if (o == ME1__WD or ME2__WD or ME3__WD) { pronoun_word = o; pronoun_obj = player; }
2439   
2440      allow_plurals = true; desc_wn = wn;
2441   
2442    .TryAgain;
2443   
2444      ! First, we parse any descriptive words (like "the", "five" or "every"):
2445      l = Descriptors();
2446      if (l ~= 0) { etype = l; return GPR_FAIL; }
2447   
2448    .TryAgain2;
2449   
2450      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2451      !
2452      ! D: Parse an object name
2453      !
2454      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2455   
2456      ! This is an actual specified object, and is therefore where a typing error
2457      ! is most likely to occur, so we set:
2458   
2459      oops_from = wn;
2460   
2461      ! So, two cases.  Case 1: token not equal to "held" (so, no implicit takes)
2462      ! but we may well be dealing with multiple objects
2463   
2464      ! In either case below we use NounDomain, giving it the token number as
2465      ! context, and two places to look: among the actor's possessions, and in the
2466      ! present location.  (Note that the order depends on which is likeliest.)
2467   
2468      if (token ~= HELD_TOKEN) {
2469          i = multiple_object-->0;
2470          #Ifdef DEBUG;
2471          if (parser_trace >= 3) print "  [Calling NounDomain on location and actor]^";
2472          #Endif; ! DEBUG
2473          l = NounDomain(actors_location, actor, token);
2474          if (l == REPARSE_CODE) return l;                  ! Reparse after Q&A
2475          if (indef_wanted == 100 && l == 0 && number_matched == 0)
2476              l = 1;  ! ReviseMulti if TAKE ALL FROM empty container
2477   
2478          if (token_allows_multiple && ~~multiflag) {
2479              if (best_etype==MULTI_PE) best_etype=STUCK_PE;
2480              multiflag = true;
2481          }
2482          if (l == 0) {
2483              if (indef_possambig) {
2484                  ResetDescriptors();
2485                  wn = desc_wn;
2486                  jump TryAgain2;
2487              }
2488              if (etype == MULTI_PE or TOOFEW_PE && multiflag) etype = STUCK_PE;
2489              etype=CantSee();
2490              jump FailToken;
2491          } ! Choose best error
2492   
2493          #Ifdef DEBUG;
2494          if (parser_trace >= 3) {
2495              if (l > 1) print "  [ND returned ", (the) l, "]^";
2496              else {
2497                  print "  [ND appended to the multiple object list:^";
2498                  k = multiple_object-->0;
2499                  for (j=i+1 : j<=k : j++)
2500                      print "  Entry ", j, ": ", (The) multiple_object-->j,
2501                            " (", multiple_object-->j, ")^";
2502                  print "  List now has size ", k, "]^";
2503              }
2504          }
2505          #Endif; ! DEBUG
2506   
2507          if (l == 1) {
2508              if (~~many_flag) many_flag = true;
2509              else {                                ! Merge with earlier ones
2510                  k = multiple_object-->0;            ! (with either parity)
2511                  multiple_object-->0 = i;
2512                  for (j=i+1 : j<=k : j++) {
2513                      if (and_parity) MultiAdd(multiple_object-->j);
2514                      else            MultiSub(multiple_object-->j);
2515                  }
2516                  #Ifdef DEBUG;
2517                  if (parser_trace >= 3) print "  [Merging ", k-i, " new objects to the ", i, " old ones]^";
2518                  #Endif; ! DEBUG
2519              }
2520          }
2521          else {
2522              ! A single object was indeed found
2523   
2524              if (match_length == 0 && indef_possambig) {
2525                  ! So the answer had to be inferred from no textual data,
2526                  ! and we know that there was an ambiguity in the descriptor
2527                  ! stage (such as a word which could be a pronoun being
2528                  ! parsed as an article or possessive).  It's worth having
2529                  ! another go.
2530   
2531                  ResetDescriptors();
2532                  wn = desc_wn;
2533                  jump TryAgain2;
2534              }
2535   
2536              if (token == CREATURE_TOKEN && CreatureTest(l) == 0) {
2537                  etype = ANIMA_PE;
2538                  jump FailToken;
2539              } !  Animation is required
2540   
2541              if (~~many_flag) single_object = l;
2542              else {
2543                  if (and_parity) MultiAdd(l); else MultiSub(l);
2544                  #Ifdef DEBUG;
2545                  if (parser_trace >= 3) print "  [Combining ", (the) l, " with list]^";
2546                  #Endif; ! DEBUG
2547              }
2548          }
2549      }
2550   
2551      else {
2552   
2553      ! Case 2: token is "held" (which fortunately can't take multiple objects)
2554      ! and may generate an implicit take
2555   
2556          l = NounDomain(actor,actors_location,token);       ! Same as above...
2557          if (l == REPARSE_CODE) return GPR_REPARSE;
2558          if (l == 0) {
2559              if (indef_possambig) {
2560                  ResetDescriptors();
2561                  wn = desc_wn;
2562                  jump TryAgain2;
2563              }
2564              etype = CantSee(); jump FailToken;            ! Choose best error
2565          }
2566   
2567          ! ...until it produces something not held by the actor.  Then an implicit
2568          ! take must be tried.  If this is already happening anyway, things are too
2569          ! confused and we have to give up (but saving the oops marker so as to get
2570          ! it on the right word afterwards).
2571          ! The point of this last rule is that a sequence like
2572          !
2573          !     > read newspaper
2574          !     (taking the newspaper first)
2575          !     The dwarf unexpectedly prevents you from taking the newspaper!
2576          !
2577          ! should not be allowed to go into an infinite repeat - read becomes
2578          ! take then read, but take has no effect, so read becomes take then read...
2579          ! Anyway for now all we do is record the number of the object to take.
2580   
2581          o = parent(l);
2582          if (o ~= actor) {
2583              if (notheld_mode == 1) {
2584                  saved_oops = oops_from;
2585                  etype = NOTHELD_PE;
2586                  jump FailToken;
2587              }
2588              not_holding = l;
2589              #Ifdef DEBUG;
2590              if (parser_trace >= 3) print "  [Allowing object ", (the) l, " for now]^";
2591              #Endif; ! DEBUG
2592          }
2593          single_object = l;
2594      } ! end of if (token ~= HELD_TOKEN) else
2595   
2596      ! The following moves the word marker to just past the named object...
2597   
2598      wn = oops_from + match_length;
2599   
2600      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2601      !
2602      ! E: Parse connectives ("and", "but", etc.) and go back to (C)
2603      !
2604      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2605   
2606      ! Object(s) specified now: is that the end of the list, or have we reached
2607      ! "and", "but" and so on?  If so, create a multiple-object list if we
2608      ! haven't already (and are allowed to).
2609   
2610    .NextInList;
2611   
2612      o = NextWord();
2613   
2614      if (o == AND1__WD or AND2__WD or AND3__WD or BUT1__WD or BUT2__WD or BUT3__WD or comma_word) {
2615   
2616          #Ifdef DEBUG;
2617          if (parser_trace >= 3) print "  [Read connective '", (address) o, "']^";
2618          #Endif; ! DEBUG
2619   
2620          if (~~token_allows_multiple) {
2621              if (multiflag) jump PassToken; ! give UPTO_PE error
2622              etype=MULTI_PE;
2623              jump FailToken;
2624          }
2625   
2626          if (o == BUT1__WD or BUT2__WD or BUT3__WD) and_parity = 1-and_parity;
2627   
2628          if (~~many_flag) {
2629              multiple_object-->0 = 1;
2630              multiple_object-->1 = single_object;
2631              many_flag = true;
2632              #Ifdef DEBUG;
2633              if (parser_trace >= 3) print "  [Making new list from ", (the) single_object, "]^";
2634              #Endif; ! DEBUG
2635          }
2636          dont_infer = true; inferfrom=0;           ! Don't print (inferences)
2637          jump ObjectList;                          ! And back around
2638      }
2639   
2640      wn--;   ! Word marker back to first not-understood word
2641   
2642      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2643      !
2644      ! F: Return the conclusion of parsing an object list
2645      !
2646      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2647   
2648      ! Happy or unhappy endings:
2649   
2650    .PassToken;
2651   
2652      if (many_flag) {
2653          single_object = GPR_MULTIPLE;
2654          multi_context = token;
2655      }
2656      else {
2657          if (indef_mode == 1 && indef_type & PLURAL_BIT ~= 0) {
2658              if (indef_wanted < 100 && indef_wanted > 1) {
2659                  multi_had = 1; multi_wanted = indef_wanted;
2660                  etype = TOOFEW_PE;
2661                  jump FailToken;
2662              }
2663          }
2664      }
2665      return single_object;
2666   
2667    .FailToken;
2668   
2669      ! If we were only guessing about it being a plural, try again but only
2670      ! allowing singulars (so that words like "six" are not swallowed up as
2671      ! Descriptors)
2672   
2673      if (allow_plurals && indef_guess_p == 1) {
2674          #Ifdef DEBUG;
2675          if (parser_trace >= 4) print "   [Retrying singulars after failure ", etype, "]^";
2676          #Endif;
2677          prev_indef_wanted = indef_wanted;
2678          allow_plurals = false;
2679          wn = desc_wn;
2680          jump TryAgain;
2681      }
2682   
2683      if ((indef_wanted > 0 || prev_indef_wanted > 0) && (~~multiflag)) etype = MULTI_PE;
2684   
2685      return GPR_FAIL;
2686   
2687  ]; ! end of ParseToken__


Last updated 27 February 2004. The librarian in charge of this page is Graham Nelson (graham@gnelson.demon.co.uk) assisted by C Knight. Please email any comments, suggestions or corrections to cedenqs@inform-fiction.org.