home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / hugs101.zip / hugs101sc.zip / hugsdist / src / input.c < prev    next >
C/C++ Source or Header  |  1995-03-02  |  37KB  |  1,264 lines

  1. /* --------------------------------------------------------------------------
  2.  * input.c:     Copyright (c) Mark P Jones 1991-1994.   All rights reserved.
  3.  *              See NOTICE for details and conditions of use etc...
  4.  *              Hugs version 1.0 August 1994, derived from Gofer 2.30a
  5.  *
  6.  * Input functions, lexical analysis parsing etc...
  7.  * ------------------------------------------------------------------------*/
  8.  
  9. #include "prelude.h"
  10. #include "storage.h"
  11. #include "connect.h"
  12. #include "command.h"
  13. #include "errors.h"
  14. #include <ctype.h>
  15.  
  16. /* --------------------------------------------------------------------------
  17.  * Global data:
  18.  * ------------------------------------------------------------------------*/
  19.  
  20. List tyconDefns         = NIL;        /* type constructor definitions       */
  21. List typeInDefns     = NIL;        /* type synonym restrictions        */
  22. List valDefns         = NIL;        /* value definitions in script       */
  23. List opDefns         = NIL;        /* operator defns in script       */
  24. List classDefns      = NIL;        /* class defns in script        */
  25. List instDefns       = NIL;        /* instance defns in script       */
  26. List overDefns         = NIL;        /* overloaded implementation names */
  27. List primDefns         = NIL;        /* primitive definitions       */
  28. List defaultDefns    = NIL;        /* default definitions (if any)       */
  29. Int  defaultLine     = 0;        /* line in which default defs occur*/
  30. List evalDefaults    = NIL;        /* defaults for evaluator       */
  31.  
  32. Cell inputExpr         = NIL;        /* input expression           */
  33. Bool literateScripts = FALSE;        /* TRUE => default to lit scripts  */
  34. Bool literateErrors  = TRUE;        /* TRUE => report errs in lit scrs */
  35.  
  36. String repeatStr     = 0;        /* Repeat last expr           */
  37.  
  38. /* --------------------------------------------------------------------------
  39.  * Local function prototypes:
  40.  * ------------------------------------------------------------------------*/
  41.  
  42. static Void local fileInput      Args((String,Long));
  43. static Bool local literateMode      Args((String));
  44. static Void local skip          Args((Void));
  45. static Void local thisLineIs      Args((Int));
  46. static Void local newlineSkip      Args((Void));
  47. static Void local closeAnyInput   Args((Void));
  48.  
  49.        Int  yyparse        Args((Void)); /* can't stop yacc making this   */
  50.                       /* public, but don't advertise   */
  51.                       /* it in a header file.       */
  52.  
  53. static Void local endToken      Args((Void));
  54. static Text local readOperator      Args((Void));
  55. static Text local readIdent      Args((Void));
  56. static Cell local readNumber      Args((Void));
  57. static Cell local readChar      Args((Void));
  58. static Cell local readString      Args((Void));
  59. static Void local saveStrChr      Args((Char));
  60. static Cell local readAChar      Args((Bool));
  61.  
  62. static Bool local lazyReadMatches Args((String));
  63. static Cell local readEscapeChar  Args((Bool));
  64. static Void local skipGap      Args((Void));
  65. static Cell local readCtrlChar      Args((Void));
  66. static Cell local readOctChar      Args((Void));
  67. static Int  local readOctDigit      Args((Void));
  68. static Cell local readHexChar      Args((Void));
  69. static Int  local readHexDigit      Args((Void));
  70. static Cell local readDecChar      Args((Void));
  71.  
  72. static Void local goOffside      Args((Int));
  73. static Void local unOffside      Args((Void));
  74. static Bool local canUnOffside      Args((Void));
  75.  
  76. static Void local skipWhitespace  Args((Void));
  77. static Int  local yylex       Args((Void));
  78. static Int  local repeatLast      Args((Void));
  79.  
  80. static Void local parseInput      Args((Int));
  81.  
  82. /* --------------------------------------------------------------------------
  83.  * Text values for reserved words and special symbols:
  84.  * ------------------------------------------------------------------------*/
  85.  
  86. static Text textCase,    textOfK,    textData,    textType,   textIf;
  87. static Text textThen,    textElse,   textWhere,    textLet,    textIn;
  88. static Text textInfix,  textInfixl, textInfixr, textPrim;
  89.  
  90. static Text textCoco,    textEq,     textUpto,    textAs,     textLambda;
  91. static Text textBar,    textMinus,  textFrom,    textArrow,  textLazy;
  92.  
  93. static Text textClass,  textImplies,textInstance;
  94.  
  95. static Text textDefault, textDeriving, textHiding, textInterface;
  96. static Text textImport,  textModule,   textTo,     textRenaming;
  97.  
  98. #if    IO_MONAD
  99. static Text textRunST;
  100. #endif
  101.  
  102. static Cell varMinus;            /* (-)                   */
  103. static Cell varNegate;            /* negate               */
  104. static Cell varFlip;            /* flip                   */
  105. static Cell varFrom;            /* [_..]               */
  106. static Cell varFromTo;            /* [_.._]               */
  107. static Cell varFromThen;        /* [_,_..]               */
  108. static Cell varFromThenTo;        /* [_,_.._]               */
  109.  
  110. Text   textPlus;            /* (+)                   */
  111.  
  112. /* --------------------------------------------------------------------------
  113.  * Single character input routines:
  114.  *
  115.  * At the lowest level of input, characters are read one at a time, with the
  116.  * current character held in c0 and the following (lookahead) character in
  117.  * c1.    The corrdinates of c0 within the file are held in (column,row).
  118.  * The input stream is advanced by one character using the skip() function.
  119.  * ------------------------------------------------------------------------*/
  120.  
  121. #define TABSIZE    8               /* spacing between tabstops       */
  122.  
  123. #define NOTHING    0               /* what kind of input is being read?*/
  124. #define KEYBOARD   1               /* - keyboard/console?           */
  125. #define SCRIPTFILE 2               /* - script file            */
  126. #define PROJFILE   3               /* - project file           */
  127.  
  128. static Int    reading    = NOTHING;
  129.  
  130. static Target readSoFar;
  131. static Int    row, column, startColumn;
  132. static int    c0, c1;
  133. static FILE   *inputStream;
  134. static Bool   thisLiterate;
  135.  
  136. #if     USE_READLINE            /* for command line editors       */
  137. static  String currentLine;        /* editline or GNU readline       */
  138. static  String nextChar;
  139. #define nextConsoleChar()   (*nextChar=='\0' ? '\n' : *nextChar++)
  140. extern  Void add_history    Args((String));
  141. extern  String readline        Args((String));
  142.  
  143. #define PROMPTMAX        20        /* max chars in a sensible prompt  */
  144. static  String addSpace(str)        /* add trailing space to prompt       */
  145. String str; {
  146.     static char promptBuf[PROMPTMAX+2];
  147.     if (strlen(str)>PROMPTMAX)
  148.     return str;
  149.     strcpy(promptBuf,str);
  150.     strcat(promptBuf," ");
  151.     return promptBuf;
  152. }
  153. #else
  154. #define nextConsoleChar()   getc(stdin)
  155. #endif
  156.  
  157. static    Int litLines;               /* count defn lines in lit script   */
  158. #define DEFNCHAR  '>'               /* definition lines begin with this */
  159. static    Int lastLine;               /* records type of last line read:  */
  160. #define STARTLINE 0               /* - at start of file, none read    */
  161. #define BLANKLINE 1               /* - blank (may preceed definition) */
  162. #define TEXTLINE  2               /* - text comment           */
  163. #define DEFNLINE  3               /* - line containing definition       */
  164.  
  165. Void consoleInput(prompt)        /* prepare to input characters from*/
  166. String prompt; {            /* standard in (i.e. console/kbd)  */
  167.     reading    = KEYBOARD;        /* keyboard input is Line oriented,*/
  168.     c0        =            /* i.e. input terminated by '\n'   */
  169.     c1        = ' ';
  170.     column    = (-1);
  171.     row     = 0;
  172.  
  173. #if USE_READLINE
  174.     if (currentLine)
  175.     free(currentLine);
  176.     currentLine = readline(addSpace(prompt));
  177.     nextChar    = currentLine;
  178.     if (currentLine) {
  179.     if (*currentLine)
  180.         add_history(currentLine);
  181.     }
  182.     else
  183.     c0 = c1 = EOF;
  184. #else
  185.     printf("%s ",prompt);
  186.     fflush(stdout);
  187. #endif
  188. }
  189.  
  190. Void projInput(nm)               /* prepare to input characters from */
  191. String nm; {                   /* from named project file       */
  192.     if (inputStream = fopen(nm,"r")) {
  193.     reading = PROJFILE;
  194.     c0      = ' ';
  195.         c1      = '\n';
  196.         column  = 1;
  197.         row     = 0;
  198.     }
  199.     else {
  200.     ERROR(0) "Unable to open project file \"%s\"", nm
  201.     EEND;
  202.     }
  203. }
  204.  
  205. static Void local fileInput(nm,len)    /* prepare to input characters from*/
  206. String nm;                /* named file (specified length is */
  207. Long   len; {                /* used to set target for reading) */
  208.     if (inputStream = fopen(nm,"r")) {
  209.     reading      = SCRIPTFILE;
  210.     c0         = ' ';
  211.     c1         = '\n';
  212.     column         = 1;
  213.     row         = 0;
  214.     readSoFar    = 0;
  215.     lastLine     = STARTLINE;
  216.     litLines     = 0;
  217.     thisLiterate = literateMode(nm);
  218.     setGoal("Parsing", (Target)len);
  219.     }
  220.     else {
  221.     ERROR(0) "Unable to open file"
  222.     EEND;
  223.     }
  224. }
  225.  
  226. static Bool local literateMode(nm)    /* selecte literate mode for file  */
  227. String nm; {
  228.     String dot = 0;
  229.  
  230. #if !RISCOS
  231.     for (; *nm; ++nm)            /* look for last dot in file name  */
  232.     if (*nm == '.')
  233.         dot = nm+1;
  234.  
  235.     if (dot) {
  236.     if (strcmp(dot,"hs")==0   ||    /* .hs, .gs, .has, .gof files are  */
  237.         strcmp(dot,"gs")==0   ||    /* never literate scripts       */
  238.         strcmp(dot,"gof")==0  ||
  239.         strcmp(dot,"has")==0  ||
  240.         strcmp(dot,"prelude")==0)    /* special suffix for prelude files*/
  241.         return FALSE;
  242.  
  243.     if (strcmp(dot,"lhs")==0  ||    /* .lhs, .lgs, .verb, .lit scripts */
  244.         strcmp(dot,"lgs")==0  ||    /* are always literate scripts       */
  245.         strcmp(dot,"verb")==0 ||
  246.         strcmp(dot,"lit")==0)
  247.         return TRUE;
  248.     }
  249. #else
  250.     char *start = nm;
  251.     for (; *nm; ++nm)                   /* look for last dot in file name  */
  252.         if (*nm == '.')
  253.             dot = nm+1;
  254.     if (dot) {
  255.     char *prev = dot-1;
  256.     while (prev > start && *--prev != '.')
  257.         ;
  258.     if (*prev == '.')
  259.         ++prev;
  260.     if (namecmp(prev,"hs")      || namecmp(prev,"gs")
  261.          || namecmp(prev,"gof") || namecmp(prev,"has")
  262.          || namecmp(prev,"prelude"))
  263.         return FALSE;
  264.     if (namecmp(prev,"lhs")     || namecmp(prev,"lgs")
  265.          || namecmp(prev,"lit") ||  namecmp(prev,"verb"))
  266.         return TRUE;
  267.     }
  268. #endif
  269.     return literateScripts;        /* otherwise, use the default       */
  270. }
  271.  
  272. static Void local skip() {        /* move forward one char in input  */
  273.     if (c0!=EOF) {            /* stream, updating c0, c1, ...       */
  274.     if (c0=='\n') {            /* Adjusting cursor coords as nec. */
  275.         row++;
  276.         column=1;
  277.         if (reading==SCRIPTFILE)
  278.         soFar(readSoFar);
  279.     }
  280.     else if (c0=='\t')
  281.         column += TABSIZE - ((column-1)%TABSIZE);
  282.     else
  283.         column++;
  284.  
  285.     c0 = c1;
  286.     readSoFar++;
  287.  
  288.     if (c0==EOF) {
  289.         column = 0;
  290.         if (reading==SCRIPTFILE)
  291.         done();
  292.         closeAnyInput();
  293.     }
  294.     else if (reading==KEYBOARD) {
  295.         allowBreak();
  296.         if (c0=='\n')
  297.         c1 = EOF;
  298.         else
  299.         c1 = nextConsoleChar();
  300.     }
  301.     else
  302.         c1 = getc(inputStream);
  303.     }
  304. }
  305.  
  306. static Void local thisLineIs(kind)    /* register kind of current line   */
  307. Int kind; {                /* & check for literate script errs*/
  308.     if (literateErrors && ((kind==DEFNLINE && lastLine==TEXTLINE) ||
  309.                (kind==TEXTLINE && lastLine==DEFNLINE))) {
  310.     ERROR(row) "Program line next to comment"
  311.     EEND;
  312.     }
  313.     lastLine = kind;
  314. }
  315.  
  316. static Void local newlineSkip() {      /* skip `\n' (supports lit scripts) */
  317.     if (reading==SCRIPTFILE && thisLiterate) {
  318.     do {
  319.         skip();
  320.         if (c0==DEFNCHAR) {        /* pass chars on definition lines   */
  321.         thisLineIs(DEFNLINE);  /* to lexer (w/o leading DEFNCHAR)  */
  322.         skip();
  323.         litLines++;
  324.         return;
  325.         }
  326.         while (c0==' ' || c0=='\t')/* maybe line is blank?           */
  327.         skip();
  328.         if (c0=='\n' || c0==EOF)
  329.         thisLineIs(BLANKLINE);
  330.         else {
  331.         thisLineIs(TEXTLINE);  /* otherwise it must be a comment   */
  332.         while (c0!='\n' && c0!=EOF)
  333.             skip();
  334.         }                   /* by now, c0=='\n' or c0==EOF       */
  335.     } while (c0!=EOF);           /* if new line, start again       */
  336.  
  337.     if (litLines==0 && literateErrors) {
  338.         ERROR(row) "Empty script - perhaps you forgot the `%c's?",
  339.                DEFNCHAR
  340.         EEND;
  341.     }
  342.     return;
  343.     }
  344.     skip();
  345. }
  346.  
  347. static Void local closeAnyInput() {    /* close input stream, if open      */
  348.     if (reading==SCRIPTFILE || reading==PROJFILE)
  349.     fclose(inputStream);
  350.     else if (reading==KEYBOARD)        /* or skip to end of console line  */
  351.     while (c0!=EOF)
  352.         skip();
  353.     reading=NOTHING;
  354. }
  355.  
  356. /* --------------------------------------------------------------------------
  357.  * Parser: Uses table driven parser generated from parser.y using yacc
  358.  * ------------------------------------------------------------------------*/
  359.  
  360. #include "parser.c"
  361.  
  362. /* --------------------------------------------------------------------------
  363.  * Single token input routines:
  364.  *
  365.  * The following routines read the values of particular kinds of token given
  366.  * that the first character of the token has already been located in c0 on
  367.  * entry to the routine.
  368.  * ------------------------------------------------------------------------*/
  369.  
  370. #define MAX_TOKEN        250
  371. #define startToken()        tokPos = 0
  372. #define saveTokenChar(c)    if (tokPos<MAX_TOKEN) saveChar(c); else ++tokPos
  373. #define saveChar(c)        tokenStr[tokPos++]=(c)
  374. #define SPECIALS        "(),;[]_{}"
  375. #define SYMBOLS         ":!#$%&*+./<=>?@\\^|-" /* For Haskell 1.1: `-' */
  376. #define PRESYMBOLS         "~"               /* should be a PRESYMBOL*/
  377.                                                    /* but including it here*/
  378.                                                    /* means we loose eg <- */
  379. #define isoneof(c,cs)        (strchr(cs,c)!=(char *)0)
  380. #define overflows(n,b,d,m)  (n > ((m)-(d))/(b))
  381.  
  382. static char tokenStr[MAX_TOKEN+1];    /* token buffer               */
  383. static Int  tokPos;            /* input position in buffer       */
  384. static Int  identType;            /* identifier type: CONID / VARID  */
  385. static Int  opType;            /* operator type  : CONOP / VAROP  */
  386.  
  387. static Void local endToken() {        /* check for token overflow       */
  388.     if (tokPos>MAX_TOKEN) {
  389.     ERROR(row) "Maximum token length (%d) exceeded", MAX_TOKEN
  390.     EEND;
  391.     }
  392.     tokenStr[tokPos] = '\0';
  393. }
  394.  
  395. static Text local readOperator() {    /* read operator symbol           */
  396.     startToken();
  397.     do {
  398.     saveTokenChar(c0);
  399.     skip();
  400.     } while (c0!=EOF && isascii(c0) && isoneof(c0,SYMBOLS));
  401.     opType = (tokenStr[0]==':' ? CONOP : VAROP);
  402.     endToken();
  403.     return findText(tokenStr);
  404. }
  405.  
  406. static Text local readIdent() {        /* read identifier           */
  407.     startToken();
  408.     do {
  409.     saveTokenChar(c0);
  410.     skip();
  411.     } while ((c0!=EOF && isascii(c0) && isalnum(c0)) || c0=='_' || c0=='\'');
  412.     endToken();
  413.     identType = isupper(tokenStr[0]) ? CONID : VARID;
  414.     return findText(tokenStr);
  415. }
  416.  
  417. static Cell local readNumber() {       /* read numeric constant        */
  418.     Int   n           = 0;
  419.     Bool  intTooLarge = FALSE;
  420.  
  421.     startToken();
  422.     do {
  423.     if (overflows(n,10,(c0-'0'),MAXPOSINT))
  424.         intTooLarge = TRUE;
  425.     n  = 10*n  + (c0-'0');
  426.     saveTokenChar(c0);
  427.     skip();
  428.     } while (c0!=EOF && isascii(c0) && isdigit(c0));
  429.  
  430.     if (c0!='.' || !isascii(c1) || !isdigit(c1)) {
  431.     endToken();
  432.     if (!intTooLarge)
  433.         return mkInt(n);
  434. #if BIGNUMS
  435.     if (intTooLarge)
  436.         return bigStr(tokenStr);
  437. #endif
  438.     ERROR(row) "Integer literal out of range"
  439.     EEND;
  440.     }
  441.  
  442.     saveTokenChar(c0);                /* save decimal point           */
  443.     skip();
  444.     do {                /* process fractional part ...       */
  445.     saveTokenChar(c0);
  446.     skip();
  447.     } while (c0!=EOF && isascii(c0) && isdigit(c0));
  448.  
  449.     if (c0=='e' || c0=='E') {        /* look for exponent part...       */
  450.     saveTokenChar('e');
  451.     skip();
  452.     if (c0=='-') {
  453.         saveTokenChar('-');
  454.         skip();
  455.     }
  456.     else if (c0=='+')
  457.         skip();
  458.  
  459.     if (!isascii(c0) || !isdigit(c0)) {
  460.         ERROR(row) "Missing digits in exponent"
  461.         EEND;
  462.     }
  463.     else {
  464.         do {
  465.         saveTokenChar(c0);
  466.         skip();
  467.         } while (c0!=EOF && isascii(c0) && isdigit(c0));
  468.     }
  469.     }
  470.  
  471.     endToken();
  472. #if !HAS_FLOATS
  473.     ERROR(row) "No floating point numbers in this implementation"
  474.     EEND;
  475. #endif
  476.  
  477.     return mkFloat(stringToFloat(tokenStr));
  478. }
  479.  
  480. static Cell local readChar() {           /* read character constant       */
  481.     Cell charRead;
  482.  
  483.     skip(/* '\'' */);
  484.     if (c0=='\'' || c0=='\n' || c0==EOF) {
  485.     ERROR(row) "Illegal character constant"
  486.     EEND;
  487.     }
  488.  
  489.     charRead = readAChar(FALSE);
  490.  
  491.     if (c0=='\'')
  492.     skip(/* '\'' */);
  493.     else {
  494.     ERROR(row) "Improperly terminated character constant"
  495.     EEND;
  496.     }
  497.     return charRead;
  498. }
  499.  
  500. static Cell local readString() {       /* read string literal           */
  501.     Cell c;
  502.  
  503.     startToken();
  504.     skip(/* '\"' */);
  505.     while (c0!='\"' && c0!='\n' && c0!=EOF) {
  506.     c = readAChar(TRUE);
  507.     if (nonNull(c))
  508.         saveStrChr(charOf(c));
  509.     }
  510.  
  511.     if (c0=='\"')
  512.     skip(/* '\"' */);
  513.     else {
  514.     ERROR(row) "improperly terminated string"
  515.     EEND;
  516.     }
  517.     endToken();
  518.     return mkStr(findText(tokenStr));
  519. }
  520.  
  521. static Void local saveStrChr(c)        /* save character in string       */
  522. Char c; {
  523.     if (c!='\0' && c!='\\') {           /* save non null char as single char*/
  524.     saveTokenChar(c);
  525.     }
  526.     else {                   /* save null char as TWO null chars */
  527.     if (tokPos+1<MAX_TOKEN) {
  528.         saveChar('\\');
  529.         if (c=='\\')
  530.         saveChar('\\');
  531.         else
  532.         saveChar('0');
  533.     }
  534.     }
  535. }
  536.  
  537. static Cell local readAChar(allowEmpty)/* read single char constant       */
  538. Bool allowEmpty; {               /* TRUE => enable use of \& and gaps*/
  539.     Cell c = mkChar(c0);
  540.  
  541.     if (c0=='\\')               /* escape character?           */
  542.     return readEscapeChar(allowEmpty);
  543.     if (!isprint(c0)) {
  544.     ERROR(row) "Non printable character '\\%d' in constant", ((int)c0)
  545.     EEND;
  546.     }
  547.     skip();                   /* normal character?           */
  548.     return c;
  549. }
  550.  
  551. /* --------------------------------------------------------------------------
  552.  * Character escape code sequences:
  553.  * ------------------------------------------------------------------------*/
  554.  
  555. static struct {                /* table of special escape codes    */
  556.     char *codename;
  557.     int  codenumber;
  558. } escapes[] = {
  559.    {"a",    7}, {"b",     8}, {"f",   12}, {"n",   10},    /* common escapes  */
  560.    {"r",   13}, {"t",     9}, {"\\",'\\'}, {"\"",'\"'},
  561.    {"\'",'\''}, {"v",    11},
  562.    {"NUL",  0}, {"SOH",  1}, {"STX",  2}, {"ETX",  3},    /* ascii codenames */
  563.    {"EOT",  4}, {"ENQ",  5}, {"ACK",  6}, {"BEL",  7},
  564.    {"BS",   8}, {"HT",     9}, {"LF",  10}, {"VT",  11},
  565.    {"FF",  12}, {"CR",    13}, {"SO",  14}, {"SI",  15},
  566.    {"DLE", 16}, {"DC1", 17}, {"DC2", 18}, {"DC3", 19},
  567.    {"DC4", 20}, {"NAK", 21}, {"SYN", 22}, {"ETB", 23},
  568.    {"CAN", 24}, {"EM",    25}, {"SUB", 26}, {"ESC", 27},
  569.    {"FS",  28}, {"GS",    29}, {"RS",  30}, {"US",  31},
  570.    {"SP",  32}, {"DEL", 127},
  571.    {0,0}
  572. };
  573.  
  574. static Int  alreadyMatched;           /* Record portion of input stream   */
  575. static char alreadyRead[10];           /* that has been read w/o a match   */
  576.  
  577. static Bool local lazyReadMatches(s)   /* compare input stream with string */
  578. String s; {                   /* possibly using characters that   */
  579.     int i;                   /* have already been read       */
  580.  
  581.     for (i=0; i<alreadyMatched; ++i)
  582.     if (alreadyRead[i]!=s[i])
  583.         return FALSE;
  584.  
  585.     while (s[i] && s[i]==c0) {
  586.     alreadyRead[alreadyMatched++]=c0;
  587.     skip();
  588.     i++;
  589.     }
  590.  
  591.     return s[i]=='\0';
  592. }
  593.  
  594. static Cell local readEscapeChar(allowEmpty) /* read escape character       */
  595. Bool allowEmpty; {
  596.     int i=0;
  597.  
  598.     skip(/* '\\' */);
  599.     switch (c0) {
  600.     case '&'  : if (allowEmpty) {
  601.             skip();
  602.             return NIL;
  603.             }
  604.             ERROR(row) "Illegal use of \\& in character constant"
  605.             EEND;
  606.             break;/*NOTREACHED*/
  607.     case ' '  :
  608.     case '\n' :
  609.     case '\t' : if (allowEmpty) {
  610.             skipGap();
  611.             return NIL;
  612.             }
  613.             ERROR(row) "Illegal use of gap in character constant"
  614.             EEND;
  615.             break;
  616.     case '^'  : return readCtrlChar();
  617.     case 'o'  : return readOctChar();
  618.     case 'x'  : return readHexChar();
  619.     default   : if (isdigit(c0))
  620.             return readDecChar();
  621.     }
  622.  
  623.     for (alreadyMatched=0; escapes[i].codename; i++)
  624.     if (lazyReadMatches(escapes[i].codename))
  625.         return mkChar(escapes[i].codenumber);
  626.  
  627.     alreadyRead[alreadyMatched++] = c0;
  628.     alreadyRead[alreadyMatched++] = '\0';
  629.     ERROR(row) "Illegal character escape sequence \"\\%s\"",
  630.            alreadyRead
  631.     EEND;
  632.     return NIL;/*NOTREACHED*/
  633. }
  634.  
  635. static Void local skipGap() {        /* skip over gap in string literal */
  636.     do                    /* (simplified in Haskell 1.1)       */
  637.     if (c0=='\n')
  638.         newlineSkip();
  639.     else
  640.         skip();
  641.     while (c0==' ' || c0=='\t' || c0=='\n');
  642.     if (c0!='\\') {
  643.     ERROR(row) "Missing `\\' terminating string literal gap"
  644.     EEND;
  645.     }
  646.     skip(/* '\\' */);
  647. }
  648.  
  649. static Cell local readCtrlChar() {     /* read escape sequence \^x       */
  650.     static String controls = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
  651.     String which;
  652.  
  653.     skip(/* '^' */);
  654.     if ((which = strchr(controls,c0))==NULL) {
  655.     ERROR(row) "Unrecognised escape sequence `\\^%c'", c0
  656.     EEND;
  657.     }
  658.     skip();
  659.     return mkChar(which-controls);
  660. }
  661.  
  662. static Cell local readOctChar() {      /* read octal character constant    */
  663.     Int n = 0;
  664.     Int d;
  665.  
  666.     skip(/* 'o' */);
  667.     if ((d = readOctDigit())<0) {
  668.     ERROR(row) "Empty octal character escape"
  669.     EEND;
  670.     }
  671.     do {
  672.     if (overflows(n,8,d,MAXCHARVAL)) {
  673.         ERROR(row) "Octal character escape out of range"
  674.         EEND;
  675.     }
  676.     n = 8*n + d;
  677.     skip();
  678.     } while ((d = readOctDigit())>=0);
  679.  
  680.     return mkChar(n);
  681. }
  682.  
  683. static Int local readOctDigit() {      /* read single octal digit       */
  684.     if ('0'<=c0 && c0<='7')
  685.     return c0-'0';
  686.     return -1;
  687. }
  688.  
  689. static Cell local readHexChar() {      /* read hex character constant       */
  690.     Int n = 0;
  691.     Int d;
  692.  
  693.     skip(/* 'x' */);
  694.     if ((d = readHexDigit())<0) {
  695.     ERROR(row) "Empty hexadecimal character escape"
  696.     EEND;
  697.     }
  698.     do {
  699.     if (overflows(n,16,d,MAXCHARVAL)) {
  700.         ERROR(row) "Hexadecimal character escape out of range"
  701.         EEND;
  702.     }
  703.     n = 16*n + d;
  704.     skip();
  705.     } while ((d = readHexDigit())>=0);
  706.  
  707.     return mkChar(n);
  708. }
  709.  
  710. static Int local readHexDigit() {      /* read single hex digit        */
  711.     if ('0'<=c0 && c0<='9')
  712.     return c0-'0';
  713.     if ('A'<=c0 && c0<='F')
  714.     return 10 + (c0-'A');
  715.     if ('a'<=c0 && c0<='f')
  716.     return 10 + (c0-'a');
  717.     return -1;
  718. }
  719.  
  720. static Cell local readDecChar() {      /* read decimal character constant  */
  721.     Int n = 0;
  722.  
  723.     do {
  724.     if (overflows(n,10,(c0-'0'),MAXCHARVAL)) {
  725.         ERROR(row) "Decimal character escape out of range"
  726.         EEND;
  727.     }
  728.     n = 10*n + (c0-'0');
  729.     skip();
  730.     } while (c0!=EOF && isascii(c0) && isdigit(c0));
  731.  
  732.     return mkChar(n);
  733. }
  734.  
  735. /* --------------------------------------------------------------------------
  736.  * Produce printable representation of character:
  737.  * ------------------------------------------------------------------------*/
  738.  
  739. String unlexChar(c,quote)        /* return string representation of */
  740. Char c;                    /* character...               */
  741. Char quote; {                /* protect quote character       */
  742.     static char buffer[12];
  743.  
  744.     if (c<0)                /* deal with sign extended chars.. */
  745.     c += NUM_CHARS;
  746.  
  747.     if (isascii(c) && isprint(c)) {    /* normal printable character       */
  748.     if (c==quote) {            /* look for quote of approp. kind  */
  749.         buffer[0] = '\\';        
  750.         buffer[1] = c;
  751.         buffer[2] = '\0';
  752.     }
  753.     else {
  754.             buffer[0] = c;
  755.             buffer[1] = '\0';
  756.     }
  757.     }
  758.     else {                /* look for escape code           */
  759.         Int escs;
  760.         for (escs=0; escapes[escs].codename; escs++)
  761.         if (escapes[escs].codenumber==c) {
  762.         sprintf(buffer,"\\%s",escapes[escs].codename);
  763.         return buffer;
  764.         }
  765.         sprintf(buffer,"\\%d",c);    /* otherwise use numeric escape       */
  766.     }
  767.     return buffer;
  768. }
  769.  
  770. /* --------------------------------------------------------------------------
  771.  * Handle special types of input for use in interpreter:
  772.  * ------------------------------------------------------------------------*/
  773.  
  774. Command readCommand(cmds,start,sys)    /* read command at start of input  */
  775. struct cmd *cmds;            /* line in interpreter           */
  776. Char   start;                /* characters introducing a cmd    */
  777. Char   sys; {                /* character for shell escape       */
  778.     while (c0==' ' || c0 =='\t')
  779.     skip();
  780.  
  781.     if (c0=='\n')            /* look for blank command lines    */
  782.     return NOCMD;
  783.     if (c0==EOF)            /* look for end of input stream       */
  784.     return QUIT;
  785.     if (c0==sys) {            /* single character system escape  */
  786.     skip();
  787.     return SYSTEM;
  788.     }
  789.     if (c0==start && c1==sys) {        /* two character system escape       */
  790.     skip();
  791.     skip();
  792.     return SYSTEM;
  793.     }
  794.  
  795.     startToken();            /* All cmds start with start       */
  796.     if (c0==start)            /* except default (usually EVAL)   */
  797.     do {                /* which is empty           */
  798.         saveTokenChar(c0);
  799.         skip();
  800.     } while (c0!=' ' && c0!='\t' && c0!='\n' && c0!=EOF);
  801.     endToken();
  802.  
  803.     for (; cmds->cmdString; ++cmds)
  804.     if (strcmp((cmds->cmdString),tokenStr)==0 ||
  805.             (tokenStr[0]==start &&
  806.              tokenStr[1]==(cmds->cmdString)[1] &&
  807.              tokenStr[2]=='\0'))
  808.         return (cmds->cmdCode);
  809.     return BADCMD;
  810. }
  811.  
  812. String readFilename() {            /* Read filename from input (if any)*/
  813.     if (reading==PROJFILE)
  814.     skipWhitespace();
  815.     else
  816.     while (c0==' ' || c0=='\t')
  817.         skip();
  818.  
  819.     if (c0=='\n' || c0==EOF)           /* return null string at end of line*/
  820.     return 0;
  821.  
  822.     startToken();
  823.     while (c0!=' ' && c0!='\t' && c0!='\n' && c0!='\r' && c0!=EOF) {
  824.     saveTokenChar(c0);
  825.     skip();
  826.     }
  827.     endToken();
  828.  
  829.     return tokenStr;
  830. }
  831.  
  832. String readLine() {            /* Read command line from input       */
  833.     while (c0==' ' || c0=='\t')        /* skip leading whitespace       */
  834.     skip();
  835.  
  836.     startToken();
  837.     while (c0!='\n' && c0!=EOF) {
  838.     saveTokenChar(c0);
  839.     skip();
  840.     }
  841.     endToken();
  842.  
  843.     return tokenStr;
  844. }
  845.  
  846. /* --------------------------------------------------------------------------
  847.  * This lexer supports the Haskell layout rule:
  848.  *
  849.  * - Layout area bounded by { ... }, with `;'s in between.
  850.  * - A `{' is a HARD indentation and can only be matched by a corresponding
  851.  *   HARD '}'
  852.  * - Otherwise, if no `{' follows the keywords WHERE/LET or OF, a SOFT `{'
  853.  *   is inserted with the column number of the first token after the
  854.  *   WHERE/LET/OF keyword.
  855.  * - When a soft indentation is uppermost on the indetation stack with
  856.  *   column col' we insert:
  857.  *    `}'  in front of token with column<col' and pop indentation off stack,
  858.  *    `;'  in front of token with column==col'.
  859.  * ------------------------------------------------------------------------*/
  860.  
  861. #define MAXINDENT  100               /* maximum nesting of layout rule   */
  862. static    Int       layout[MAXINDENT+1];/* indentation stack           */
  863. #define HARD       (-1)            /* indicates hard indentation       */
  864. static    Int       indentDepth = (-1); /* current indentation nesting       */
  865.  
  866. static Void local goOffside(col)       /* insert offside marker        */
  867. Int col; {                   /* for specified column           */
  868.     if (indentDepth>=MAXINDENT) {
  869.     ERROR(row) "Too many levels of program nesting"
  870.     EEND;
  871.     }
  872.     layout[++indentDepth] = col;
  873. }
  874.  
  875. static Void local unOffside() {        /* leave layout rule area       */
  876.     indentDepth--;
  877. }
  878.  
  879. static Bool local canUnOffside() {     /* Decide if unoffside permitted    */
  880.     return indentDepth>=0 && layout[indentDepth]!=HARD;
  881. }
  882.  
  883. /* --------------------------------------------------------------------------
  884.  * Main tokeniser:
  885.  * ------------------------------------------------------------------------*/
  886.  
  887. static Void local skipWhitespace() {   /* skip over whitespace/comments    */
  888.  
  889. ws: while (c0==' ' || c0=='\t' || c0=='\r' || c0=='\f')
  890.     skip();
  891.  
  892.     if (c0=='\n') {               /* skip newline characters       */
  893.     newlineSkip();
  894.     goto ws;
  895.     }
  896.  
  897.     if (c0=='{' && c1=='-') {           /* (potentially) nested comment       */
  898.     Int nesting = 1;
  899.     Int origRow = row;           /* save original row number       */
  900.  
  901.         skip();
  902.         skip();
  903.     while (nesting>0 && c0!=EOF) {
  904.         if (c0=='{' && c1=='-') {
  905.         skip();
  906.         nesting++;
  907.         }
  908.         else if (c0=='-' && c1=='}') {
  909.         skip();
  910.         nesting--;
  911.         }
  912.  
  913.         if (c0=='\n')
  914.         newlineSkip();
  915.         else
  916.         skip();
  917.     }
  918.     if (nesting>0) {
  919.         ERROR(origRow) "Unterminated nested comment {- ..."
  920.         EEND;
  921.     }
  922.     goto ws;
  923.     }
  924.  
  925.     if (c0=='-' && c1=='-') {           /* one line comment           */
  926.     do
  927.         skip();
  928.     while (c0!='\n' && c0!=EOF)
  929.         ;
  930.     if (c0=='\n')
  931.         newlineSkip();
  932.     goto ws;
  933.     }
  934. }
  935.  
  936. static Bool firstToken;            /* Set to TRUE for first token       */
  937. static Int  firstTokenIs;           /* ... with token value stored here */
  938.  
  939. static Int local yylex() {           /* Read next input token ...       */
  940.     static Bool insertOpen    = FALSE;
  941.     static Bool insertedToken = FALSE;
  942.     static Text textRepeat;
  943.  
  944. #define lookAhead(t) {skipWhitespace(); insertOpen = (c0!='{'); return t;}
  945.  
  946.     if (firstToken) {               /* Special case for first token       */
  947.     indentDepth   = (-1);
  948.     firstToken    = FALSE;
  949.     insertOpen    = FALSE;
  950.     insertedToken = FALSE;
  951.     if (reading==KEYBOARD)
  952.         textRepeat = findText(repeatStr);
  953.     return firstTokenIs;
  954.     }
  955.  
  956.     if (insertOpen) {               /* insert `soft' opening brace       */
  957.     insertOpen    = FALSE;
  958.     insertedToken = TRUE;
  959.     goOffside(column);
  960.     push(yylval = mkInt(row));
  961.     return '{';
  962.     }
  963.  
  964.     /* ----------------------------------------------------------------------
  965.      * Skip white space, and insert tokens to support layout rules as reqd.
  966.      * --------------------------------------------------------------------*/
  967.  
  968.     skipWhitespace();
  969.     startColumn = column;
  970.     push(yylval = mkInt(row));           /* default token value is line no.  */
  971.     /* subsequent changes to yylval must also set top() to the same value  */
  972.  
  973.     if (indentDepth>=0)            /* layout rule(s) active ?       */
  974.         if (insertedToken)           /* avoid inserting multiple `;'s    */
  975.         insertedToken = FALSE;     /* or putting `;' after `{'       */
  976.         else if (layout[indentDepth]!=HARD)
  977.         if (column<layout[indentDepth]) {
  978.         unOffside();
  979.         return '}';
  980.             }
  981.             else if (column==layout[indentDepth] && c0!=EOF) {
  982.                 insertedToken = TRUE;
  983.                 return ';';
  984.             }
  985.  
  986.     /* ----------------------------------------------------------------------
  987.      * Now try to identify token type as one of:
  988.      * - end of file character
  989.      * - Special character:  ( ) , ; [ ] _ { } `
  990.      * - Character constant
  991.      * - String Constant
  992.      * - Integer literal
  993.      * - Alphanum: reservedid, VARID or CONID
  994.      * - operator: reservedop, VAROP or CONOP
  995.      * --------------------------------------------------------------------*/
  996.  
  997.     switch (c0) {
  998.     case EOF  : return 0;
  999.  
  1000.     case '('  : skip();
  1001.             return '(';
  1002.  
  1003.     case ')'  : skip();
  1004.             return ')';
  1005.  
  1006.     case ','  : skip();
  1007.             return ',';
  1008.  
  1009.     case ';'  : skip();
  1010.             return ';';
  1011.  
  1012.     case '['  : skip();
  1013.             return '[';
  1014.  
  1015.     case ']'  : skip();
  1016.             return ']';
  1017.  
  1018.     case '_'  : skip();
  1019.             return '_';
  1020.  
  1021.     case '{'  : goOffside(HARD);
  1022.             skip();
  1023.             return '{';
  1024.  
  1025.     case '}'  : if (indentDepth<0) {
  1026.             ERROR(row) "Misplaced `}'"
  1027.             EEND;
  1028.             }
  1029.             if (layout[indentDepth]==HARD)    /* skip over hard } */
  1030.             skip();
  1031.             unOffside();    /* otherwise, we have to insert a } */
  1032.             return '}';        /* to (try to) avoid an error...    */
  1033.  
  1034.     case '\'' : top() = yylval = readChar();
  1035.             return CHARLIT;
  1036.  
  1037.     case '\"' : top() = yylval = readString();
  1038.             return STRINGLIT;
  1039.  
  1040.     case '`'  : skip();
  1041.             return '`';
  1042.     }
  1043.  
  1044.     if (!(isascii(c0) && isprint(c0))) {
  1045.     ERROR(row) "Unrecognised character '\\%d' in column %d",
  1046.            ((int)c0), column
  1047.     EEND;
  1048.     }
  1049.  
  1050.     if (isalpha(c0)) {
  1051.     Text it = readIdent();
  1052.  
  1053.     if (it==textCase)              return CASEXP;
  1054.     if (it==textOfK)               lookAhead(OF);
  1055.     if (it==textData)           return DATA;
  1056.     if (it==textType)           return TYPE;
  1057.     if (it==textIf)            return IF;
  1058.     if (it==textThen)           return THEN;
  1059.     if (it==textElse)           return ELSE;
  1060.     if (it==textWhere)             lookAhead(WHERE);
  1061.         if (it==textLet)               lookAhead(LET);
  1062.         if (it==textIn)                return IN;
  1063.     if (it==textInfix)           return INFIX;
  1064.     if (it==textInfixl)           return INFIXL;
  1065.     if (it==textInfixr)           return INFIXR;
  1066.     if (it==textPrim)              return PRIMITIVE;
  1067.     if (it==textClass)           return TCLASS;
  1068.     if (it==textInstance)           return TINSTANCE;
  1069.     if (it==textDeriving)           return DERIVING;
  1070.     if (it==textDefault)           return DEFAULT;
  1071.     if (it==textHiding)           return HIDING;
  1072.     if (it==textImport)           return IMPORT;
  1073.     if (it==textInterface)           return INTERFACE;
  1074.     if (it==textModule)           return MODULE;
  1075.     if (it==textTo)               return TO;
  1076.     if (it==textRenaming)           return RENAMING;
  1077.     if (it==textRepeat && reading==KEYBOARD)
  1078.         return repeatLast();
  1079. #if IO_MONAD
  1080.     if (it==textRunST)           return TRUNST;
  1081. #endif
  1082.     top() = yylval = ap((identType==CONID ? CONIDCELL : VARIDCELL),it);
  1083.     return identType;
  1084.     }
  1085.  
  1086.     if (isoneof(c0,SYMBOLS) || isoneof(c0,PRESYMBOLS)) {
  1087.     Text it = readOperator();
  1088.  
  1089.     if (it==textCoco)    return COCO;
  1090.     if (it==textEq)      return '=';
  1091.     if (it==textUpto)    return UPTO;
  1092.     if (it==textAs)      return '@';
  1093.     if (it==textLambda)  return '\\';
  1094.     if (it==textBar)     return '|';
  1095.     if (it==textFrom)    return FROM;/*relies on notElem '-' PRESYMBOLS*/
  1096.     if (it==textMinus)   return '-';
  1097.     if (it==textArrow)   return FUNARROW;
  1098.     if (it==textLazy)    return '~';
  1099.     if (it==textImplies) return IMPLIES;
  1100.     if (it==textRepeat && reading==KEYBOARD)
  1101.         return repeatLast();
  1102.  
  1103.     top() = yylval = ap((opType==CONOP ? CONOPCELL : VAROPCELL),it);
  1104.     return opType;
  1105.     }
  1106.  
  1107.     if (isdigit(c0)) {
  1108.     top() = yylval = readNumber();
  1109.     return NUMLIT;
  1110.     }
  1111.  
  1112.     ERROR(row) "Unrecognised character '\\%d' in column %d", ((int)c0), column
  1113.     EEND;
  1114.     return 0; /*NOTREACHED*/
  1115. }
  1116.  
  1117. static Int local repeatLast() {        /* obtain last expression entered  */
  1118.     if (isNull(yylval=getLastExpr())) {
  1119.     ERROR(row) "Cannot use %s without any previous input", repeatStr
  1120.     EEND;
  1121.     }
  1122.     return REPEAT;
  1123. }
  1124.  
  1125. Syntax defaultSyntax(t)            /* find default syntax of var named */
  1126. Text t; {                   /* by t ...               */
  1127.     String s = textToStr(t);
  1128.     if ((isascii(s[0]) && isalpha(s[0])) || s[0]=='_' || strcmp(s,"[]")==0)
  1129.     return APPLIC;
  1130.     else
  1131.     return DEF_OPSYNTAX;
  1132. }
  1133.  
  1134. /* --------------------------------------------------------------------------
  1135.  * main entry points to parser/lexer:
  1136.  * ------------------------------------------------------------------------*/
  1137.  
  1138. static Void local parseInput(startWith)/* parse input with given first tok,*/
  1139. Int startWith; {               /* determining whether to read a    */
  1140.     firstToken     = TRUE;           /* script or an expression       */
  1141.     firstTokenIs = startWith;
  1142.  
  1143.     clearStack();
  1144.     if (yyparse()) {               /* This can only be parser overflow */
  1145.     ERROR(row) "Parser overflow"   /* as all syntax errors are caught  */
  1146.     EEND;                   /* in the parser...           */
  1147.     }
  1148.     drop();
  1149.     if (!stackEmpty())               /* stack should now be empty       */
  1150.     internal("parseInput");
  1151. }
  1152.  
  1153. Void parseScript(nm,len)           /* Read a script: sets valDefns and */
  1154. String nm;                   /*                tyconDefns       */
  1155. Long   len; {                   /* used to set a target for reading)*/
  1156.     input(RESET);
  1157.     fileInput(nm,len);
  1158.     parseInput(SCRIPT);
  1159. }
  1160.  
  1161. Void parseExp() {               /* read an expression to evaluate   */
  1162.     parseInput(EVALEX);
  1163.     setLastExpr(inputExpr);
  1164. }
  1165.  
  1166. /* --------------------------------------------------------------------------
  1167.  * Input control:
  1168.  * ------------------------------------------------------------------------*/
  1169.  
  1170. Void input(what)
  1171. Int what; {
  1172.     switch (what) {
  1173.     case RESET   : tyconDefns   = NIL;
  1174.                typeInDefns  = NIL;
  1175.                valDefns     = NIL;
  1176.                opDefns        = NIL;
  1177.                classDefns   = NIL;
  1178.                        instDefns    = NIL;
  1179.                overDefns    = NIL;
  1180.                primDefns    = NIL;
  1181.                defaultDefns = stdDefaults;
  1182.                defaultLine  = 0;
  1183.                inputExpr    = NIL;
  1184.                closeAnyInput();
  1185.                break;
  1186.  
  1187.     case BREAK   : if (reading==KEYBOARD)
  1188.                c0 = EOF;
  1189.                break;
  1190.  
  1191.     case MARK    : mark(tyconDefns);
  1192.                mark(typeInDefns);
  1193.                mark(valDefns);
  1194.                mark(opDefns);
  1195.                mark(classDefns);
  1196.                        mark(instDefns);
  1197.                mark(overDefns);
  1198.                mark(primDefns);
  1199.                mark(defaultDefns);
  1200.                mark(evalDefaults);
  1201.                mark(inputExpr);
  1202.                mark(varNegate);
  1203.                mark(varFlip);
  1204.                mark(varMinus);
  1205.                mark(varFrom);
  1206.                mark(varFromTo);
  1207.                mark(varFromThen);
  1208.                mark(varFromThenTo);
  1209.                break;
  1210.  
  1211.     case INSTALL : input(RESET);
  1212.                textCase       = findText("case");
  1213.                textOfK          = findText("of");
  1214.                textData       = findText("data");
  1215.                textType       = findText("type");
  1216.                textIf          = findText("if");
  1217.                textThen       = findText("then");
  1218.                textElse       = findText("else");
  1219.                textWhere      = findText("where");
  1220.                        textLet        = findText("let");
  1221.                        textIn         = findText("in");
  1222.                textInfix      = findText("infix");
  1223.                textInfixl     = findText("infixl");
  1224.                textInfixr     = findText("infixr");
  1225.                textPrim       = findText("primitive");
  1226.                textCoco       = findText("::");
  1227.                textEq          = findText("=");
  1228.                textUpto       = findText("..");
  1229.                textAs          = findText("@");
  1230.                textLambda     = findText("\\");
  1231.                textBar          = findText("|");
  1232.                textMinus      = findText("-");
  1233.                textFrom       = findText("<-");
  1234.                textArrow      = findText("->");
  1235.                textLazy       = findText("~");
  1236.                textClass      = findText("class");
  1237.                textInstance   = findText("instance");
  1238.                textImplies    = findText("=>");
  1239.                textPlus          = findText("+");
  1240.                textDefault    = findText("default");
  1241.                textDeriving   = findText("deriving");
  1242.                textHiding     = findText("hiding");
  1243.                textInterface  = findText("interface");
  1244.                textImport     = findText("import");
  1245.                textModule     = findText("module");
  1246.                textTo         = findText("to");
  1247.                textRenaming   = findText("renaming");
  1248. #if IO_MONAD
  1249.                textRunST      = findText("runST");
  1250. #endif
  1251.                varMinus          = mkVar(findText("-"));
  1252.                varNegate      = mkVar(findText("negate"));
  1253.                varFlip          = mkVar(findText("flip"));
  1254.                varFrom          = mkVar(findText("enumFrom"));
  1255.                varFromTo      = mkVar(findText("enumFromTo"));
  1256.                varFromThen    = mkVar(findText("enumFromThen"));
  1257.                varFromThenTo  = mkVar(findText("enumFromThenTo"));
  1258.                evalDefaults   = NIL;
  1259.                break;
  1260.     }
  1261. }
  1262.  
  1263. /*-------------------------------------------------------------------------*/
  1264.