Inform - Support - Source

Back to List

Inventory
Complete

Backward
Forward

Plain
Coloured
Gaudy

This code
in plain text

Browsing parserm.h

ParseToken__ (lines 1601-1999)

1601  [ ParseToken__ given_ttype given_tdata token_n
1602               token l o i j k and_parity single_object desc_wn many_flag
1603               token_allows_multiple;
1604   
1605  !  **** (A) ****
1606   
1607     token_filter = 0;
1608   
1609     switch(given_ttype)
1610     {   ELEMENTARY_TT:
1611             switch(given_tdata)
1612             {   SPECIAL_TOKEN:
1613                     l=TryNumber(wn);
1614                     special_word=NextWord();
1615                     #ifdef DEBUG;
1616                     if (l~=-1000)
1617                         if (parser_trace>=3)
1618                             print "  [Read special as the number ", l, "]^";
1619                     #endif;
1620                     if (l==-1000)
1621                     {   #ifdef DEBUG;
1622                         if (parser_trace>=3)
1623                           print "  [Read special word at word number ", wn, "]^";
1624                         #endif;
1625                         l = special_word;
1626                     }
1627                     parsed_number = l; return GPR_NUMBER;
1628   
1629                 NUMBER_TOKEN:
1630                     l=TryNumber(wn++);
1631                     if (l==-1000) { etype=NUMBER_PE; return GPR_FAIL; }
1632                     #ifdef DEBUG;
1633                     if (parser_trace>=3) print "  [Read number as ", l, "]^";
1634                     #endif;
1635                     parsed_number = l; return GPR_NUMBER;
1636   
1637                 CREATURE_TOKEN:
1638                     if (action_to_be==##Answer or ##Ask or ##AskFor or ##Tell)
1639                         scope_reason = TALKING_REASON;
1640   
1641                 TOPIC_TOKEN:
1642                     consult_from = wn;
1643                     if ((line_ttype-->(token_n+1) ~= PREPOSITION_TT)
1644                         && (line_token-->(token_n+1) ~= ENDIT_TOKEN))
1645                         RunTimeError(13);
1646                     do o=NextWordStopped();
1647                     until (o==-1 || PrepositionChain(o, token_n+1) ~= -1);
1648                     wn--;
1649                     consult_words = wn-consult_from;
1650                     if (consult_words==0) return GPR_FAIL;
1651                     if (action_to_be==##Ask or ##Answer or ##Tell)
1652                     {   o=wn; wn=consult_from; parsed_number=NextWord();
1653                         #IFDEF EnglishNaturalLanguage;
1654                         if (parsed_number=='the' && consult_words>1)
1655                             parsed_number=NextWord();
1656                         #ENDIF;
1657                         wn=o; return 1;
1658                     }
1659                     return GPR_PREPOSITION;
1660             }
1661   
1662         PREPOSITION_TT:
1663             #Iffalse Grammar__Version==1;
1664  !  Is it an unnecessary alternative preposition, when a previous choice
1665  !  has already been matched?
1666             if ((token->0) & $10) return GPR_PREPOSITION;
1667             #Endif;
1668   
1669  !  If we've run out of the player's input, but still have parameters to
1670  !  specify, we go into "infer" mode, remembering where we are and the
1671  !  preposition we are inferring...
1672   
1673             if (wn > num_words)
1674             {   if (inferfrom==0 && parameters<params_wanted)
1675                 {   inferfrom = pcount; inferword = token;
1676                     pattern-->pcount = REPARSE_CODE + Dword__No(given_tdata);
1677                 }
1678   
1679  !  If we are not inferring, then the line is wrong...
1680   
1681                 if (inferfrom==0) return -1;
1682   
1683  !  If not, then the line is right but we mark in the preposition...
1684   
1685                 pattern-->pcount = REPARSE_CODE + Dword__No(given_tdata);
1686                 return GPR_PREPOSITION;
1687             }
1688   
1689             o = NextWord();
1690   
1691             pattern-->pcount = REPARSE_CODE + Dword__No(o);
1692   
1693  !  Whereas, if the player has typed something here, see if it is the
1694  !  required preposition... if it's wrong, the line must be wrong,
1695  !  but if it's right, the token is passed (jump to finish this token).
1696   
1697             if (o == given_tdata) return GPR_PREPOSITION;
1698             #Iffalse Grammar__Version==1;
1699             if (PrepositionChain(o, token_n) ~= -1)
1700                 return GPR_PREPOSITION;
1701             #Endif;
1702             return -1;
1703   
1704         GPR_TT:
1705             l=indirect(given_tdata);
1706             #ifdef DEBUG;
1707             if (parser_trace>=3)
1708                 print "  [Outside parsing routine returned ", l, "]^";
1709             #endif;
1710             return l;
1711   
1712         SCOPE_TT:
1713             scope_token = given_tdata;
1714             scope_stage = 1;
1715             l = indirect(scope_token);
1716             #ifdef DEBUG;
1717             if (parser_trace>=3)
1718                 print "  [Scope routine returned multiple-flag of ", l, "]^";
1719             #endif;
1720             if (l==1) given_tdata = MULTI_TOKEN; else given_tdata = NOUN_TOKEN;
1721   
1722         ATTR_FILTER_TT:
1723             token_filter = 1 + given_tdata;
1724             given_tdata = NOUN_TOKEN;
1725   
1726         ROUTINE_FILTER_TT:
1727             token_filter = given_tdata;
1728             given_tdata = NOUN_TOKEN;
1729     }
1730   
1731     token = given_tdata;
1732   
1733  !  **** (B) ****
1734   
1735  !  There are now three possible ways we can be here:
1736  !      parsing an elementary token other than "special" or "number";
1737  !      parsing a scope token;
1738  !      parsing a noun-filter token (either by routine or attribute).
1739  !
1740  !  In each case, token holds the type of elementary parse to
1741  !  perform in matching one or more objects, and
1742  !  token_filter is 0 (default), an attribute + 1 for an attribute filter
1743  !  or a routine address for a routine filter.
1744   
1745     token_allows_multiple = false;
1746     if (token == MULTI_TOKEN or MULTIHELD_TOKEN or MULTIEXCEPT_TOKEN
1747                  or MULTIINSIDE_TOKEN) token_allows_multiple = true;
1748   
1749     many_flag = false; and_parity = true; dont_infer = false;
1750   
1751  !  **** (C) ****
1752  !  We expect to find a list of objects next in what the player's typed.
1753   
1754    .ObjectList;
1755   
1756     #ifdef DEBUG;
1757     if (parser_trace>=3) print "  [Object list from word ", wn, "]^";
1758     #endif;
1759   
1760  !  Take an advance look at the next word: if it's "it" or "them", and these
1761  !  are unset, set the appropriate error number and give up on the line
1762  !  (if not, these are still parsed in the usual way - it is not assumed
1763  !  that they still refer to something in scope)
1764   
1765      o=NextWord(); wn--;
1766   
1767      pronoun_word = NULL; pronoun_obj = NULL;
1768      l = PronounValue(o);
1769      if (l ~= 0)
1770      {   pronoun_word = o; pronoun_obj = l;
1771          if (l == NULL)
1772          {   !   Don't assume this is a use of an unset pronoun until the
1773              !   descriptors have been checked, because it might be an
1774              !   article (or some such) instead
1775   
1776              for (l=1:l<=LanguageDescriptors-->0:l=l+4)
1777                  if (o == LanguageDescriptors-->l) jump AssumeDescriptor;
1778              pronoun__word=pronoun_word; pronoun__obj=pronoun_obj;
1779              etype=VAGUE_PE; return GPR_FAIL;
1780          }
1781      }
1782   
1783      .AssumeDescriptor;
1784   
1785      if (o==ME1__WD or ME2__WD or ME3__WD)
1786      {   pronoun_word = o; pronoun_obj = player;
1787      }
1788   
1789      allow_plurals = true; desc_wn = wn;
1790   
1791      .TryAgain;
1792  !   First, we parse any descriptive words (like "the", "five" or "every"):
1793      l = Descriptors(token_allows_multiple);
1794      if (l~=0) { etype=l; return GPR_FAIL; }
1795   
1796      .TryAgain2;
1797   
1798  !  **** (D) ****
1799   
1800  !  This is an actual specified object, and is therefore where a typing error
1801  !  is most likely to occur, so we set:
1802   
1803      oops_from = wn;
1804   
1805  !  So, two cases.  Case 1: token not equal to "held" (so, no implicit takes)
1806  !  but we may well be dealing with multiple objects
1807   
1808  !  In either case below we use NounDomain, giving it the token number as
1809  !  context, and two places to look: among the actor's possessions, and in the
1810  !  present location.  (Note that the order depends on which is likeliest.)
1811   
1812      if (token ~= HELD_TOKEN)
1813      {   i=multiple_object-->0;
1814          #ifdef DEBUG;
1815          if (parser_trace>=3)
1816              print "  [Calling NounDomain on location and actor]^";
1817          #endif;
1818          l=NounDomain(actors_location, actor, token);
1819          if (l==REPARSE_CODE) return l;                  ! Reparse after Q&A
1820          if (l==0) {   if (indef_possambig)
1821                        {   ResetDescriptors(); wn = desc_wn; jump TryAgain2; }
1822                        etype=CantSee(); jump FailToken; } ! Choose best error
1823   
1824          #ifdef DEBUG;
1825          if (parser_trace>=3)
1826          {   if (l>1)
1827                  print "  [ND returned ", (the) l, "]^";
1828              else
1829              {   print "  [ND appended to the multiple object list:^";
1830                  k=multiple_object-->0;
1831                  for (j=i+1:j<=k:j++)
1832                      print "  Entry ", j, ": ", (The) multiple_object-->j,
1833                            " (", multiple_object-->j, ")^";
1834                  print "  List now has size ", k, "]^";
1835              }
1836          }
1837          #endif;
1838   
1839          if (l==1)
1840          {   if (~~many_flag)
1841              {   many_flag = true;
1842              }
1843              else                                  ! Merge with earlier ones
1844              {   k=multiple_object-->0;            ! (with either parity)
1845                  multiple_object-->0 = i;
1846                  for (j=i+1:j<=k:j++)
1847                  {   if (and_parity) MultiAdd(multiple_object-->j);
1848                      else MultiSub(multiple_object-->j);
1849                  }
1850                  #ifdef DEBUG;
1851                  if (parser_trace>=3)
1852                      print "  [Merging ", k-i, " new objects to the ",
1853                          i, " old ones]^";
1854                  #endif;
1855              }
1856          }
1857          else
1858          {   ! A single object was indeed found
1859   
1860              if (match_length == 0 && indef_possambig)
1861              {   !   So the answer had to be inferred from no textual data,
1862                  !   and we know that there was an ambiguity in the descriptor
1863                  !   stage (such as a word which could be a pronoun being
1864                  !   parsed as an article or possessive).  It's worth having
1865                  !   another go.
1866   
1867                  ResetDescriptors(); wn = desc_wn; jump TryAgain2;
1868              }
1869          
1870              if (token==CREATURE_TOKEN && CreatureTest(l)==0)
1871              {   etype=ANIMA_PE; jump FailToken; } !  Animation is required
1872   
1873              if (~~many_flag)
1874                  single_object = l;
1875              else
1876              {   if (and_parity) MultiAdd(l); else MultiSub(l);
1877                  #ifdef DEBUG;
1878                  if (parser_trace>=3)
1879                      print "  [Combining ", (the) l, " with list]^";
1880                  #endif;
1881              }
1882          }
1883      }
1884   
1885  !  Case 2: token is "held" (which fortunately can't take multiple objects)
1886  !  and may generate an implicit take
1887   
1888      else
1889   
1890      {   l=NounDomain(actor,actors_location,token);       ! Same as above...
1891          if (l==REPARSE_CODE) return GPR_REPARSE;
1892          if (l==0)
1893          {   if (indef_possambig)
1894              {   ResetDescriptors(); wn = desc_wn; jump TryAgain2; }
1895              etype=CantSee(); return GPR_FAIL;            ! Choose best error
1896          }
1897   
1898  !  ...until it produces something not held by the actor.  Then an implicit
1899  !  take must be tried.  If this is already happening anyway, things are too
1900  !  confused and we have to give up (but saving the oops marker so as to get
1901  !  it on the right word afterwards).
1902  !  The point of this last rule is that a sequence like
1903  !
1904  !      > read newspaper
1905  !      (taking the newspaper first)
1906  !      The dwarf unexpectedly prevents you from taking the newspaper!
1907  !
1908  !  should not be allowed to go into an infinite repeat - read becomes
1909  !  take then read, but take has no effect, so read becomes take then read...
1910  !  Anyway for now all we do is record the number of the object to take.
1911   
1912          o=parent(l);
1913          if (o~=actor)
1914          {   if (notheld_mode==1)
1915              {   saved_oops=oops_from; etype=NOTHELD_PE; jump FailToken;
1916              }
1917              not_holding = l;
1918              #ifdef DEBUG;
1919              if (parser_trace>=3)
1920                  print "  [Allowing object ", (the) l, " for now]^";
1921              #endif;
1922          }
1923          single_object = l;
1924      }
1925   
1926  !  The following moves the word marker to just past the named object...
1927   
1928      wn = oops_from + match_length;
1929   
1930  !  **** (E) ****
1931   
1932  !  Object(s) specified now: is that the end of the list, or have we reached
1933  !  "and", "but" and so on?  If so, create a multiple-object list if we
1934  !  haven't already (and are allowed to).
1935   
1936      .NextInList;
1937   
1938      o=NextWord();
1939   
1940      if (o==AND1__WD or AND2__WD or AND3__WD or BUT1__WD or BUT2__WD or BUT3__WD
1941             or comma_word)
1942      {
1943          #ifdef DEBUG;
1944          if (parser_trace>=3) print "  [Read connective '", (address) o, "']^";
1945          #endif;
1946   
1947          if (~~token_allows_multiple)
1948          {   etype=MULTI_PE; jump FailToken;
1949          }
1950   
1951          if (o==BUT1__WD or BUT2__WD or BUT3__WD) and_parity = 1-and_parity;
1952   
1953          if (~~many_flag)
1954          {   multiple_object-->0 = 1;
1955              multiple_object-->1 = single_object;
1956              many_flag = true;
1957              #ifdef DEBUG;
1958              if (parser_trace>=3)
1959                  print "  [Making new list from ", (the) single_object, "]^";
1960              #endif;
1961          }
1962          dont_infer = true; inferfrom=0;           ! Don't print (inferences)
1963          jump ObjectList;                          ! And back around
1964      }
1965   
1966      wn--;   ! Word marker back to first not-understood word
1967   
1968  !  **** (F) ****
1969   
1970  !  Happy or unhappy endings:
1971   
1972      .PassToken;
1973   
1974      if (many_flag)
1975      {   single_object = GPR_MULTIPLE;
1976          multi_context = token;
1977      }
1978      else
1979      {   if (indef_mode==1 && indef_type & PLURAL_BIT ~= 0)
1980          {   if (indef_wanted<100 && indef_wanted>1)
1981              {   multi_had=1; multi_wanted=indef_wanted;
1982                  etype=TOOFEW_PE;
1983                  jump FailToken;
1984              }
1985          }
1986      }
1987      return single_object;
1988   
1989      .FailToken;
1990   
1991  !  If we were only guessing about it being a plural, try again but only
1992  !  allowing singulars (so that words like "six" are not swallowed up as
1993  !  Descriptors)
1994   
1995      if (allow_plurals && indef_guess_p==1)
1996      {   allow_plurals=false; wn=desc_wn; jump TryAgain;
1997      }
1998      return -1;
1999  ];


Last updated 27 February 2004. This site is no longer supported; information may be out of date.
Maintained as a historical archive by the Interactive Fiction Technology Foundation. Copyright 1993-2018 IFTF, CC-BY-SA unless otherwise noted.
This page was originally managed by Graham Nelson (graham@gnelson.demon.co.uk) assisted by C Knight.