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 web site has not been fully supported since April 2008. Information may be out of date. This page was originally managed by Graham Nelson (graham@gnelson.demon.co.uk) assisted by C Knight.