summaryrefslogtreecommitdiff
path: root/ghc/interpreter/input.c
diff options
context:
space:
mode:
authorsimonm <unknown>1998-12-02 13:32:30 +0000
committersimonm <unknown>1998-12-02 13:32:30 +0000
commit438596897ebbe25a07e1c82085cfbc5bdb00f09e (patch)
treeda7a441396aed2e13f6e0cc55282bf041b0cf72c /ghc/interpreter/input.c
parent967cc47f37cb93a5e2b6df7822c9a646f0428247 (diff)
downloadhaskell-438596897ebbe25a07e1c82085cfbc5bdb00f09e.tar.gz
[project @ 1998-12-02 13:17:09 by simonm]
Move 4.01 onto the main trunk.
Diffstat (limited to 'ghc/interpreter/input.c')
-rw-r--r--ghc/interpreter/input.c1567
1 files changed, 1567 insertions, 0 deletions
diff --git a/ghc/interpreter/input.c b/ghc/interpreter/input.c
new file mode 100644
index 0000000000..94e8542f01
--- /dev/null
+++ b/ghc/interpreter/input.c
@@ -0,0 +1,1567 @@
+/* -*- mode: hugs-c; -*- */
+/* --------------------------------------------------------------------------
+ * Input functions, lexical analysis parsing etc...
+ *
+ * Copyright (c) The University of Nottingham and Yale University, 1994-1997.
+ * All rights reserved. See NOTICE for details and conditions of use etc...
+ * Hugs version 1.4, December 1997
+ *
+ * $RCSfile: input.c,v $
+ * $Revision: 1.2 $
+ * $Date: 1998/12/02 13:22:12 $
+ * ------------------------------------------------------------------------*/
+
+#include "prelude.h"
+#include "storage.h"
+#include "connect.h"
+#include "charset.h"
+#include "input.h"
+#include "static.h"
+#include "interface.h"
+#include "command.h"
+#include "errors.h"
+#include "link.h"
+#include "hugs.h" /* for target */
+#include <ctype.h>
+#if HAVE_GETDELIM_H
+#include "getdelim.h"
+#endif
+
+#include "machdep.h" /* for findPathname */
+
+#if HUGS_FOR_WINDOWS
+#undef IN
+#endif
+
+/* --------------------------------------------------------------------------
+ * Global data:
+ * ------------------------------------------------------------------------*/
+
+List tyconDefns = NIL; /* type constructor definitions */
+List typeInDefns = NIL; /* type synonym restrictions */
+List valDefns = NIL; /* value definitions in script */
+List opDefns = NIL; /* operator defns in script */
+List classDefns = NIL; /* class defns in script */
+List instDefns = NIL; /* instance defns in script */
+List selDefns = NIL; /* list of selector lists */
+List genDefns = NIL; /* list of generated names */
+List unqualImports = NIL; /* unqualified import list */
+List foreignImports = NIL; /* foreign imports */
+List foreignExports = NIL; /* foreign exportsd */
+List defaultDefns = NIL; /* default definitions (if any) */
+Int defaultLine = 0; /* line in which default defs occur*/
+List evalDefaults = NIL; /* defaults for evaluator */
+
+Cell inputExpr = NIL; /* input expression */
+Bool literateScripts = FALSE; /* TRUE => default to lit scripts */
+Bool literateErrors = TRUE; /* TRUE => report errs in lit scrs */
+
+String repeatStr = 0; /* Repeat last expr */
+
+#if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
+String preprocessor = 0;
+#endif
+
+/* --------------------------------------------------------------------------
+ * Local function prototypes:
+ * ------------------------------------------------------------------------*/
+
+static Void local fileInput Args((String,Long));
+static Bool local literateMode Args((String));
+static Bool local linecmp Args((String,String));
+static Int local nextLine Args((Void));
+static Void local skip Args((Void));
+static Void local thisLineIs Args((Int));
+static Void local newlineSkip Args((Void));
+static Void local closeAnyInput Args((Void));
+
+ Int yyparse Args((Void)); /* can't stop yacc making this */
+ /* public, but don't advertise */
+ /* it in a header file. */
+
+static Void local endToken Args((Void));
+static Text local readOperator Args((Void));
+static Text local readIdent Args((Void));
+static Cell local readRadixNumber Args((Int));
+static Cell local readNumber Args((Void));
+static Cell local readChar Args((Void));
+static Cell local readString Args((Void));
+static Void local saveStrChr Args((Char));
+static Cell local readAChar Args((Bool));
+
+static Bool local lazyReadMatches Args((String));
+static Cell local readEscapeChar Args((Bool));
+static Void local skipGap Args((Void));
+static Cell local readCtrlChar Args((Void));
+static Cell local readOctChar Args((Void));
+static Cell local readHexChar Args((Void));
+static Int local readHexDigit Args((Char));
+static Cell local readDecChar Args((Void));
+
+static Void local goOffside Args((Int));
+static Void local unOffside Args((Void));
+static Bool local canUnOffside Args((Void));
+
+static Void local skipWhitespace Args((Void));
+static Int local yylex Args((Void));
+static Int local repeatLast Args((Void));
+
+static Void local parseInput Args((Int));
+
+/* --------------------------------------------------------------------------
+ * Text values for reserved words and special symbols:
+ * ------------------------------------------------------------------------*/
+
+static Text textCase, textOfK, textData, textType, textIf;
+static Text textThen, textElse, textWhere, textLet, textIn;
+static Text textInfix, textInfixl, textInfixr, textForeign, textNewtype;
+static Text textDefault, textDeriving, textDo, textClass, textInstance;
+
+static Text textCoco, textEq, textUpto, textAs, textLambda;
+static Text textBar, textMinus, textFrom, textArrow, textLazy;
+static Text textBang, textDot, textAll, textImplies;
+static Text textWildcard;
+
+static Text textModule, textImport, textPrelude, textPreludeHugs;
+static Text textHiding, textQualified, textAsMod;
+static Text textExport, textInterface, textRequires, textUnsafe;
+
+#if NPLUSK
+Text textPlus; /* (+) */
+#endif
+Cell conPrelude; /* Prelude */
+
+static Cell conMain; /* Main */
+static Cell varMain; /* main */
+
+static Cell conUnit; /* () */
+static Cell conList; /* [] */
+static Cell conNil; /* [] */
+static Cell conPreludeUnit; /* Prelude.() */
+static Cell conPreludeList; /* Prelude.[] */
+static Cell conPreludeNil; /* Prelude.[] */
+
+static Cell varMinus; /* (-) */
+static Cell varBang; /* (!) */
+static Cell varDot; /* (.) */
+static Cell varHiding; /* hiding */
+static Cell varQualified; /* qualified */
+static Cell varAsMod; /* as */
+
+static Cell varNegate;
+static Cell varFlip;
+static Cell varEnumFrom;
+static Cell varEnumFromThen;
+static Cell varEnumFromTo;
+static Cell varEnumFromThenTo;
+
+static List imps; /* List of imports to be chased */
+
+/* --------------------------------------------------------------------------
+ * Single character input routines:
+ *
+ * At the lowest level of input, characters are read one at a time, with the
+ * current character held in c0 and the following (lookahead) character in
+ * c1. The corrdinates of c0 within the file are held in (column,row).
+ * The input stream is advanced by one character using the skip() function.
+ * ------------------------------------------------------------------------*/
+
+#define TABSIZE 8 /* spacing between tabstops */
+
+#define NOTHING 0 /* what kind of input is being read?*/
+#define KEYBOARD 1 /* - keyboard/console? */
+#define SCRIPTFILE 2 /* - script file */
+#define PROJFILE 3 /* - project file */
+#define STRING 4 /* - string buffer? */
+
+static Int reading = NOTHING;
+
+static Target readSoFar;
+static Int row, column, startColumn;
+static int c0, c1;
+static FILE *inputStream = 0;
+static Bool thisLiterate;
+static String nextStringChar; /* next char in string buffer */
+
+#if USE_READLINE /* for command line editors */
+static String currentLine; /* editline or GNU readline */
+static String nextChar;
+#define nextConsoleChar() (unsigned char)(*nextChar=='\0' ? '\n' : *nextChar++)
+extern Void add_history Args((String));
+extern String readline Args((String));
+#else
+#define nextConsoleChar() getc(stdin)
+#endif
+
+static Int litLines; /* count defn lines in lit script */
+#define DEFNCHAR '>' /* definition lines begin with this */
+static Int lastLine; /* records type of last line read: */
+#define STARTLINE 0 /* - at start of file, none read */
+#define BLANKLINE 1 /* - blank (may preceed definition) */
+#define TEXTLINE 2 /* - text comment */
+#define DEFNLINE 3 /* - line containing definition */
+#define CODELINE 4 /* - line inside code block */
+
+#define BEGINCODE "\\begin{code}"
+#define ENDCODE "\\end{code}"
+
+#if HAVE_GETDELIM_H
+static char *lineBuffer = NULL; /* getline() does the initial allocation */
+#else
+#define LINEBUFFER_SIZE 1000
+static char lineBuffer[LINEBUFFER_SIZE];
+#endif
+static int lineLength = 0;
+static int inCodeBlock = FALSE; /* Inside \begin{code}..\end{code} */
+static int linePtr = 0;
+
+Void consoleInput(prompt) /* prepare to input characters from */
+String prompt; { /* standard in (i.e. console/kbd) */
+ reading = KEYBOARD; /* keyboard input is Line oriented, */
+ c0 = /* i.e. input terminated by '\n' */
+ c1 = ' ';
+ column = (-1);
+ row = 0;
+
+#if USE_READLINE
+ /* Paranoid freeing code supplied by Sverker Nilsson (sverker@opq.se)
+ * avoids accidentally freeing currentLine twice.
+ */
+ if (currentLine) {
+ String oldCurrentLine = currentLine;
+ currentLine = 0; /* We may lose the space of currentLine */
+ free(oldCurrentLine); /* if interrupted here - unlikely */
+ }
+ currentLine = readline(prompt);
+ nextChar = currentLine;
+ if (currentLine) {
+ if (*currentLine)
+ add_history(currentLine);
+ }
+ else
+ c0 = c1 = EOF;
+#else
+ Printf("%s",prompt);
+ FlushStdout();
+#endif
+}
+
+Void projInput(nm) /* prepare to input characters from */
+String nm; { /* from named project file */
+ if ((inputStream = fopen(nm,"r"))!=0) {
+ reading = PROJFILE;
+ c0 = ' ';
+ c1 = '\n';
+ column = 1;
+ row = 0;
+ }
+ else {
+ ERRMSG(0) "Unable to open project file \"%s\"", nm
+ EEND;
+ }
+}
+
+static Void local fileInput(nm,len) /* prepare to input characters from*/
+String nm; /* named file (specified length is */
+Long len; { /* used to set target for reading) */
+#if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
+ if (preprocessor) {
+ char cmd[100];
+ strncpy(cmd,preprocessor,100);
+ strncat(cmd," ",100);
+ strncat(cmd,nm,100);
+ cmd[99] = '\0'; /* paranoia */
+ inputStream = popen(cmd,"r");
+ } else {
+ inputStream = fopen(nm,"r");
+ }
+#else
+ inputStream = fopen(nm,"r");
+#endif
+ if (inputStream) {
+ reading = SCRIPTFILE;
+ c0 = ' ';
+ c1 = '\n';
+ column = 1;
+ row = 0;
+
+ lastLine = STARTLINE; /* literate file processing */
+ litLines = 0;
+ linePtr = 0;
+ lineLength = 0;
+ thisLiterate = literateMode(nm);
+ inCodeBlock = FALSE;
+
+ readSoFar = 0;
+ setGoal("Parsing", (Target)len);
+ }
+ else {
+ ERRMSG(0) "Unable to open file \"%s\"", nm
+ EEND;
+ }
+}
+
+Void stringInput(s) /* prepare to input characters from string */
+String s; {
+ reading = STRING;
+ c0 = EOF;
+ c1 = EOF;
+ if (*s) c0 = *s++;
+ if (*s) c1 = *s++;
+ column = 1;
+ row = 1;
+
+ nextStringChar = s;
+}
+
+static Bool local literateMode(nm) /* select literate mode for file */
+String nm; {
+ char *dot = strrchr(nm,'.'); /* look for last dot in file name */
+ if (dot) {
+ if (filenamecmp(dot+1,"hs")==0) /* .hs files are never literate */
+ return FALSE;
+ if (filenamecmp(dot+1,"lhs") ==0 || /* .lhs, .verb files are always*/
+ filenamecmp(dot+1,"verb")==0) /* literate scripts */
+ return TRUE;
+ }
+ return literateScripts; /* otherwise, use the default */
+}
+
+Bool isInterfaceFile(nm) /* is nm an interface file? */
+String nm; {
+ char *dot = strrchr(nm,'.'); /* look for last dot in file name */
+ return (dot && filenamecmp(dot+1,"myhi")==0);
+}
+
+
+/* This code originally came from Sigbjorn Finne (sof@dcs.gla.ac.uk).
+ * I've removed the loop (since newLineSkip contains a loop too) and
+ * replaced the warnings with errors. ADR
+ */
+/*
+ * To deal with literate \begin{code}...\end{code} blocks,
+ * add a line buffer that rooms the current line. The old c0 and c1
+ * stream pointers are used as before within that buffer -- sof
+ *
+ * Upon reading a new line into the line buffer, we check to see if
+ * we're reading in a line containing \begin{code} or \end{code} and
+ * take appropriate action.
+ */
+
+static Bool local linecmp(s,line) /* compare string with line */
+String s; /* line may end in whitespace */
+String line; {
+ Int i=0;
+ while (s[i] != '\0' && s[i] == line[i]) {
+ ++i;
+ }
+ /* s[0..i-1] == line[0..i-1] */
+ if (s[i] != '\0') { /* check s `isPrefixOf` line */
+ return FALSE;
+ }
+ while (isIn(line[i], SPACE)) { /* allow whitespace at end of line */
+ ++i;
+ }
+ return (line[i] == '\0');
+}
+
+/* Returns line length (including \n) or 0 upon EOF. */
+static Int local nextLine()
+{
+#if HAVE_GETDELIM_H
+ /*
+ Forget about fgets(), it is utterly braindead.
+ (Assumes \NUL free streams and does not gracefully deal
+ with overflow.) Instead, use GNU libc's getline().
+ */
+ lineLength = getline(&lineBuffer, &lineLength, inputStream);
+#else
+ if (NULL != fgets(lineBuffer, LINEBUFFER_SIZE, inputStream))
+ lineLength = strlen(lineBuffer);
+ else
+ lineLength = 0;
+#endif
+ /* printf("Read: \"%s\"", lineBuffer); */
+ if (lineLength <= 0) { /* EOF / IO error, who knows.. */
+ return lineLength;
+ }
+ else if (lineLength >= 2 && lineBuffer[0] == '#' && lineBuffer[1] == '!') {
+ lineBuffer[0]='\n'; /* pretend it's a blank line */
+ lineBuffer[1]='\0';
+ lineLength=1;
+ } else if (thisLiterate) {
+ if (linecmp(BEGINCODE, lineBuffer)) {
+ if (!inCodeBlock) { /* Entered a code block */
+ inCodeBlock = TRUE;
+ lineBuffer[0]='\n'; /* pretend it's a blank line */
+ lineBuffer[1]='\0';
+ lineLength=1;
+ }
+ else {
+ ERRMSG(row) "\\begin{code} encountered inside code block"
+ EEND;
+ }
+ }
+ else if (linecmp(ENDCODE, lineBuffer)) {
+ if (inCodeBlock) { /* Finished code block */
+ inCodeBlock = FALSE;
+ lineBuffer[0]='\n'; /* pretend it's a blank line */
+ lineBuffer[1]='\0';
+ lineLength=1;
+ }
+ else {
+ ERRMSG(row) "\\end{code} encountered outside code block"
+ EEND;
+ }
+ }
+ }
+ /* printf("Read: \"%s\"", lineBuffer); */
+ return lineLength;
+}
+
+static Void local skip() { /* move forward one char in input */
+ if (c0!=EOF) { /* stream, updating c0, c1, ... */
+ if (c0=='\n') { /* Adjusting cursor coords as nec. */
+ row++;
+ column=1;
+ if (reading==SCRIPTFILE)
+ soFar(readSoFar);
+ }
+ else if (c0=='\t')
+ column += TABSIZE - ((column-1)%TABSIZE);
+ else
+ column++;
+
+ c0 = c1;
+ readSoFar++;
+
+ if (c0==EOF) {
+ column = 0;
+ if (reading==SCRIPTFILE)
+ done();
+ closeAnyInput();
+ }
+ else if (reading==KEYBOARD) {
+ allowBreak();
+ if (c0=='\n')
+ c1 = EOF;
+ else {
+ c1 = nextConsoleChar();
+ /* On Win32, hitting ctrl-C causes the next getchar to
+ * fail - returning "-1" to indicate an error.
+ * This is one of the rare cases where "-1" does not mean EOF.
+ */
+ if (EOF == c1 && !feof(stdin)) {
+ c1 = ' ';
+ }
+ }
+ }
+ else if (reading==STRING) {
+ c1 = (unsigned char) *nextStringChar++;
+ if (c1 == '\0')
+ c1 = EOF;
+ }
+ else {
+ if (lineLength <=0 || linePtr == lineLength) {
+ /* Current line, exhausted - get new one */
+ if (nextLine() <= 0) { /* EOF */
+ c1 = EOF;
+ }
+ else {
+ linePtr = 0;
+ c1 = (unsigned char)lineBuffer[linePtr++];
+ }
+ }
+ else {
+ c1 = (unsigned char)lineBuffer[linePtr++];
+ }
+ }
+
+ }
+}
+
+static Void local thisLineIs(kind) /* register kind of current line */
+Int kind; { /* & check for literate script errs */
+ if (literateErrors) {
+ if ((kind==DEFNLINE && lastLine==TEXTLINE) ||
+ (kind==TEXTLINE && lastLine==DEFNLINE)) {
+ ERRMSG(row) "Program line next to comment"
+ EEND;
+ }
+ lastLine = kind;
+ }
+}
+
+static Void local newlineSkip() { /* skip `\n' (supports lit scripts) */
+ /* assert(c0=='\n'); */
+ if (reading==SCRIPTFILE && thisLiterate) {
+ do {
+ skip();
+ if (inCodeBlock) { /* pass chars on definition lines */
+ thisLineIs(CODELINE); /* to lexer (w/o leading DEFNCHAR) */
+ litLines++;
+ return;
+ }
+ if (c0==DEFNCHAR) { /* pass chars on definition lines */
+ thisLineIs(DEFNLINE); /* to lexer (w/o leading DEFNCHAR) */
+ skip();
+ litLines++;
+ return;
+ }
+ while (c0==' ' || c0=='\t')/* maybe line is blank? */
+ skip();
+ if (c0=='\n' || c0==EOF)
+ thisLineIs(BLANKLINE);
+ else {
+ thisLineIs(TEXTLINE); /* otherwise it must be a comment */
+ while (c0!='\n' && c0!=EOF)
+ skip();
+ } /* by now, c0=='\n' or c0==EOF */
+ } while (c0!=EOF); /* if new line, start again */
+
+ if (litLines==0 && literateErrors) {
+ ERRMSG(row) "Empty script - perhaps you forgot the `%c's?",
+ DEFNCHAR
+ EEND;
+ }
+ return;
+ }
+ skip();
+}
+
+static Void local closeAnyInput() { /* Close input stream, if open, */
+ switch (reading) { /* or skip to end of console line */
+ case PROJFILE :
+ case SCRIPTFILE : if (inputStream) {
+#if USE_PREPROCESSOR && (defined(HAVE_POPEN) || defined(HAVE__POPEN))
+ if (preprocessor) {
+ pclose(inputStream);
+ } else {
+ fclose(inputStream);
+ }
+#else
+ fclose(inputStream);
+#endif
+ inputStream = 0;
+ }
+ break;
+ case KEYBOARD : while (c0!=EOF)
+ skip();
+ break;
+ }
+ reading=NOTHING;
+}
+
+/* --------------------------------------------------------------------------
+ * Parser: Uses table driven parser generated from parser.y using yacc
+ * ------------------------------------------------------------------------*/
+
+#include "parser.c"
+
+/* --------------------------------------------------------------------------
+ * Single token input routines:
+ *
+ * The following routines read the values of particular kinds of token given
+ * that the first character of the token has already been located in c0 on
+ * entry to the routine.
+ * ------------------------------------------------------------------------*/
+
+#define MAX_TOKEN 500
+#define startToken() tokPos = 0
+#define saveTokenChar(c) if (tokPos<=MAX_TOKEN) saveChar(c); else ++tokPos
+#define saveChar(c) tokenStr[tokPos++]=(char)(c)
+#define overflows(n,b,d,m) (n > ((m)-(d))/(b))
+
+static char tokenStr[MAX_TOKEN+1]; /* token buffer */
+static Int tokPos; /* input position in buffer */
+static Int identType; /* identifier type: CONID / VARID */
+static Int opType; /* operator type : CONOP / VAROP */
+
+static Void local endToken() { /* check for token overflow */
+ if (tokPos>MAX_TOKEN) {
+ ERRMSG(row) "Maximum token length (%d) exceeded", MAX_TOKEN
+ EEND;
+ }
+ tokenStr[tokPos] = '\0';
+}
+
+static Text local readOperator() { /* read operator symbol */
+ startToken();
+ do {
+ saveTokenChar(c0);
+ skip();
+ } while (isISO(c0) && isIn(c0,SYMBOL));
+ opType = (tokenStr[0]==':' ? CONOP : VAROP);
+ endToken();
+ return findText(tokenStr);
+}
+
+static Text local readIdent() { /* read identifier */
+ startToken();
+ do {
+ saveTokenChar(c0);
+ skip();
+ } while (isISO(c0) && isIn(c0,IDAFTER));
+ endToken();
+ identType = isIn(tokenStr[0],LARGE) ? CONID : VARID;
+ return findText(tokenStr);
+}
+
+static Cell local readRadixNumber(r) /* Read literal in specified radix */
+Int r; { /* from input of the form 0c{digs} */
+ Int d;
+ startToken();
+ saveTokenChar(c0);
+ skip(); /* skip leading zero */
+ if ((d=readHexDigit(c1))<0 || d>=r) {
+ /* Special case; no digits, lex as */
+ /* if it had been written "0 c..." */
+ saveTokenChar('0');
+ } else {
+ Int n = 0;
+ saveTokenChar(c0);
+ skip();
+ do {
+ saveTokenChar(c0);
+ skip();
+ d = readHexDigit(c0);
+ } while (d>=0 && d<r);
+ }
+ endToken();
+ /* ToDo: return an INTCELL if small enough */
+ return stringToBignum(tokenStr);
+}
+
+static Cell local readNumber() { /* read numeric constant */
+ Bool intTooLarge = FALSE;
+
+ if (c0=='0') {
+ if (c1=='x' || c1=='X') /* Maybe a hexadecimal literal? */
+ return readRadixNumber(16);
+ if (c1=='o' || c1=='O') /* Maybe an octal literal? */
+ return readRadixNumber(8);
+ }
+
+ startToken();
+ do {
+ saveTokenChar(c0);
+ skip();
+ } while (isISO(c0) && isIn(c0,DIGIT));
+
+ if (c0!='.' || !isISO(c1) || !isIn(c1,DIGIT)) {
+ endToken();
+ /* ToDo: return an INTCELL if small enough */
+ return stringToBignum(tokenStr);
+ }
+
+ saveTokenChar(c0); /* save decimal point */
+ skip();
+ do { /* process fractional part ... */
+ saveTokenChar(c0);
+ skip();
+ } while (isISO(c0) && isIn(c0,DIGIT));
+
+ if (c0=='e' || c0=='E') { /* look for exponent part... */
+ saveTokenChar('e');
+ skip();
+ if (c0=='-') {
+ saveTokenChar('-');
+ skip();
+ }
+ else if (c0=='+')
+ skip();
+
+ if (!isISO(c0) || !isIn(c0,DIGIT)) {
+ ERRMSG(row) "Missing digits in exponent"
+ EEND;
+ }
+ else {
+ do {
+ saveTokenChar(c0);
+ skip();
+ } while (isISO(c0) && isIn(c0,DIGIT));
+ }
+ }
+
+ endToken();
+ return stringToFloat(tokenStr);
+}
+
+static Cell local readChar() { /* read character constant */
+ Cell charRead;
+
+ skip(/* '\'' */);
+ if (c0=='\'' || c0=='\n' || c0==EOF) {
+ ERRMSG(row) "Illegal character constant"
+ EEND;
+ }
+
+ charRead = readAChar(FALSE);
+
+ if (c0=='\'')
+ skip(/* '\'' */);
+ else {
+ ERRMSG(row) "Improperly terminated character constant"
+ EEND;
+ }
+ return charRead;
+}
+
+static Cell local readString() { /* read string literal */
+ Cell c;
+
+ startToken();
+ skip(/* '\"' */);
+ while (c0!='\"' && c0!='\n' && c0!=EOF) {
+ c = readAChar(TRUE);
+ if (nonNull(c))
+ saveStrChr(charOf(c));
+ }
+
+ if (c0=='\"')
+ skip(/* '\"' */);
+ else {
+ ERRMSG(row) "Improperly terminated string"
+ EEND;
+ }
+ endToken();
+ return mkStr(findText(tokenStr));
+}
+
+static Void local saveStrChr(c) /* save character in string */
+Char c; {
+ if (c!='\0' && c!='\\') { /* save non null char as single char*/
+ saveTokenChar(c);
+ }
+ else { /* save null char as TWO null chars */
+ if (tokPos+1<MAX_TOKEN) {
+ saveChar('\\');
+ if (c=='\\')
+ saveChar('\\');
+ else
+ saveChar('0');
+ }
+ }
+}
+
+static Cell local readAChar(isStrLit) /* read single char constant */
+Bool isStrLit; { /* TRUE => enable \& and gaps */
+ Cell c = mkChar(c0);
+
+ if (c0=='\\') /* escape character? */
+ return readEscapeChar(isStrLit);
+ if (!isISO(c0)) {
+ ERRMSG(row) "Non ISO character `\\%d' in constant", ((int)c0)
+ EEND;
+ }
+ skip(); /* normal character? */
+ return c;
+}
+
+/* --------------------------------------------------------------------------
+ * Character escape code sequences:
+ * ------------------------------------------------------------------------*/
+
+static struct { /* table of special escape codes */
+ char *codename;
+ int codenumber;
+} escapes[] = {
+ {"a", 7}, {"b", 8}, {"f", 12}, {"n", 10}, /* common escapes */
+ {"r", 13}, {"t", 9}, {"\\",'\\'}, {"\"",'\"'},
+ {"\'",'\''}, {"v", 11},
+ {"NUL", 0}, {"SOH", 1}, {"STX", 2}, {"ETX", 3}, /* ascii codenames */
+ {"EOT", 4}, {"ENQ", 5}, {"ACK", 6}, {"BEL", 7},
+ {"BS", 8}, {"HT", 9}, {"LF", 10}, {"VT", 11},
+ {"FF", 12}, {"CR", 13}, {"SO", 14}, {"SI", 15},
+ {"DLE", 16}, {"DC1", 17}, {"DC2", 18}, {"DC3", 19},
+ {"DC4", 20}, {"NAK", 21}, {"SYN", 22}, {"ETB", 23},
+ {"CAN", 24}, {"EM", 25}, {"SUB", 26}, {"ESC", 27},
+ {"FS", 28}, {"GS", 29}, {"RS", 30}, {"US", 31},
+ {"SP", 32}, {"DEL", 127},
+ {0,0}
+};
+
+static Int alreadyMatched; /* Record portion of input stream */
+static char alreadyRead[10]; /* that has been read w/o a match */
+
+static Bool local lazyReadMatches(s) /* compare input stream with string */
+String s; { /* possibly using characters that */
+ int i; /* have already been read */
+
+ for (i=0; i<alreadyMatched; ++i)
+ if (alreadyRead[i]!=s[i])
+ return FALSE;
+
+ while (s[i] && s[i]==c0) {
+ alreadyRead[alreadyMatched++]=(char)c0;
+ skip();
+ i++;
+ }
+
+ return s[i]=='\0';
+}
+
+static Cell local readEscapeChar(isStrLit)/* read escape character */
+Bool isStrLit; {
+ int i=0;
+
+ skip(/* '\\' */);
+ switch (c0) {
+ case '&' : if (isStrLit) {
+ skip();
+ return NIL;
+ }
+ ERRMSG(row) "Illegal use of `\\&' in character constant"
+ EEND;
+ break;/*NOTREACHED*/
+
+ case '^' : return readCtrlChar();
+
+ case 'o' : return readOctChar();
+ case 'x' : return readHexChar();
+
+ default : if (!isISO(c0)) {
+ ERRMSG(row) "Illegal escape sequence"
+ EEND;
+ }
+ else if (isIn(c0,SPACE)) {
+ if (isStrLit) {
+ skipGap();
+ return NIL;
+ }
+ ERRMSG(row) "Illegal use of gap in character constant"
+ EEND;
+ break;
+ }
+ else if (isIn(c0,DIGIT))
+ return readDecChar();
+ }
+
+ for (alreadyMatched=0; escapes[i].codename; i++)
+ if (lazyReadMatches(escapes[i].codename))
+ return mkChar(escapes[i].codenumber);
+
+ alreadyRead[alreadyMatched++] = (char)c0;
+ alreadyRead[alreadyMatched++] = '\0';
+ ERRMSG(row) "Illegal character escape sequence \"\\%s\"",
+ alreadyRead
+ EEND;
+ return NIL;/*NOTREACHED*/
+}
+
+static Void local skipGap() { /* skip over gap in string literal */
+ do /* (simplified in Haskell 1.1) */
+ if (c0=='\n')
+ newlineSkip();
+ else
+ skip();
+ while (isISO(c0) && isIn(c0,SPACE));
+ if (c0!='\\') {
+ ERRMSG(row) "Missing `\\' terminating string literal gap"
+ EEND;
+ }
+ skip(/* '\\' */);
+}
+
+static Cell local readCtrlChar() { /* read escape sequence \^x */
+ static String controls = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
+ String which;
+
+ skip(/* '^' */);
+ if ((which = strchr(controls,c0))==NULL) {
+ ERRMSG(row) "Unrecognised escape sequence `\\^%c'", c0
+ EEND;
+ }
+ skip();
+ return mkChar(which-controls);
+}
+
+static Cell local readOctChar() { /* read octal character constant */
+ Int n = 0;
+ Int d;
+
+ skip(/* 'o' */);
+ if ((d = readHexDigit(c0))<0 || d>=8) {
+ ERRMSG(row) "Empty octal character escape"
+ EEND;
+ }
+ do {
+ if (overflows(n,8,d,MAXCHARVAL)) {
+ ERRMSG(row) "Octal character escape out of range"
+ EEND;
+ }
+ n = 8*n + d;
+ skip();
+ } while ((d = readHexDigit(c0))>=0 && d<8);
+
+ return mkChar(n);
+}
+
+static Cell local readHexChar() { /* read hex character constant */
+ Int n = 0;
+ Int d;
+
+ skip(/* 'x' */);
+ if ((d = readHexDigit(c0))<0) {
+ ERRMSG(row) "Empty hexadecimal character escape"
+ EEND;
+ }
+ do {
+ if (overflows(n,16,d,MAXCHARVAL)) {
+ ERRMSG(row) "Hexadecimal character escape out of range"
+ EEND;
+ }
+ n = 16*n + d;
+ skip();
+ } while ((d = readHexDigit(c0))>=0);
+
+ return mkChar(n);
+}
+
+static Int local readHexDigit(c) /* read single hex digit */
+Char c; {
+ if ('0'<=c && c<='9')
+ return c-'0';
+ if ('A'<=c && c<='F')
+ return 10 + (c-'A');
+ if ('a'<=c && c<='f')
+ return 10 + (c-'a');
+ return -1;
+}
+
+static Cell local readDecChar() { /* read decimal character constant */
+ Int n = 0;
+
+ do {
+ if (overflows(n,10,(c0-'0'),MAXCHARVAL)) {
+ ERRMSG(row) "Decimal character escape out of range"
+ EEND;
+ }
+ n = 10*n + (c0-'0');
+ skip();
+ } while (c0!=EOF && isIn(c0,DIGIT));
+
+ return mkChar(n);
+}
+
+/* --------------------------------------------------------------------------
+ * Produce printable representation of character:
+ * ------------------------------------------------------------------------*/
+
+String unlexChar(c,quote) /* return string representation of */
+Char c; /* character... */
+Char quote; { /* protect quote character */
+ static char buffer[12];
+
+ if (c<0) /* deal with sign extended chars.. */
+ c += NUM_CHARS;
+
+ if (isISO(c) && isIn(c,PRINT)) { /* normal printable character */
+ if (c==quote || c=='\\') { /* look for quote of approp. kind */
+ buffer[0] = '\\';
+ buffer[1] = (char)c;
+ buffer[2] = '\0';
+ }
+ else {
+ buffer[0] = (char)c;
+ buffer[1] = '\0';
+ }
+ }
+ else { /* look for escape code */
+ Int escs;
+ for (escs=0; escapes[escs].codename; escs++)
+ if (escapes[escs].codenumber==c) {
+ sprintf(buffer,"\\%s",escapes[escs].codename);
+ return buffer;
+ }
+ sprintf(buffer,"\\%d",c); /* otherwise use numeric escape */
+ }
+ return buffer;
+}
+
+Void printString(s) /* print string s, using quotes and */
+String s; { /* escapes if any parts need them */
+ if (s) {
+ String t = s;
+ Char c;
+ while ((c = *t)!=0 && isISO(c) && isIn(c,PRINT) && c!='"' && !isIn(c,SPACE)) {
+ t++;
+ }
+ if (*t) {
+ Putchar('"');
+ for (t=s; *t; t++)
+ Printf("%s",unlexChar(*t,'"'));
+ Putchar('"');
+ }
+ else
+ Printf("%s",s);
+ }
+}
+
+/* -------------------------------------------------------------------------
+ * Handle special types of input for us in interpreter:
+ * -----------------------------------------------------------------------*/
+
+Command readCommand(cmds,start,sys) /* read command at start of input */
+struct cmd *cmds; /* line in interpreter */
+Char start; /* characters introducing a cmd */
+Char sys; { /* character for shell escape */
+ while (c0==' ' || c0 =='\t')
+ skip();
+
+ if (c0=='\n') /* look for blank command lines */
+ return NOCMD;
+ if (c0==EOF) /* look for end of input stream */
+ return QUIT;
+ if (c0==sys) { /* single character system escape */
+ skip();
+ return SYSTEM;
+ }
+ if (c0==start && c1==sys) { /* two character system escape */
+ skip();
+ skip();
+ return SYSTEM;
+ }
+
+ startToken(); /* All cmds start with start */
+ if (c0==start) /* except default (usually EVAL) */
+ do { /* which is empty */
+ saveTokenChar(c0);
+ skip();
+ } while (c0!=EOF && !isIn(c0,SPACE));
+ endToken();
+
+ for (; cmds->cmdString; ++cmds)
+ if (strcmp((cmds->cmdString),tokenStr)==0 ||
+ (tokenStr[0]==start &&
+ tokenStr[1]==(cmds->cmdString)[1] &&
+ tokenStr[2]=='\0'))
+ return (cmds->cmdCode);
+ return BADCMD;
+}
+
+String readFilename() { /* Read filename from input (if any)*/
+ if (reading==PROJFILE)
+ skipWhitespace();
+ else
+ while (c0==' ' || c0=='\t')
+ skip();
+
+ if (c0=='\n' || c0==EOF) /* return null string at end of line*/
+ return 0;
+
+ startToken();
+ while (c0!=EOF && !isIn(c0,SPACE)) {
+ if (c0=='"') {
+ skip();
+ while (c0!=EOF && c0!='\"') {
+ Cell c = readAChar(TRUE);
+ if (nonNull(c))
+ saveTokenChar(charOf(c));
+ }
+ if (c0=='"')
+ skip();
+ else {
+ ERRMSG(row) "a closing quote, '\"', was expected"
+ EEND;
+ }
+ }
+ else {
+ saveTokenChar(c0);
+ skip();
+ }
+ }
+ endToken();
+ return tokenStr;
+}
+
+String readLine() { /* Read command line from input */
+ while (c0==' ' || c0=='\t') /* skip leading whitespace */
+ skip();
+
+ startToken();
+ while (c0!='\n' && c0!=EOF) {
+ saveTokenChar(c0);
+ skip();
+ }
+ endToken();
+
+ return tokenStr;
+}
+
+/* --------------------------------------------------------------------------
+ * This lexer supports the Haskell layout rule:
+ *
+ * - Layout area bounded by { ... }, with `;'s in between.
+ * - A `{' is a HARD indentation and can only be matched by a corresponding
+ * HARD '}'
+ * - Otherwise, if no `{' follows the keywords WHERE/LET or OF, a SOFT `{'
+ * is inserted with the column number of the first token after the
+ * WHERE/LET/OF keyword.
+ * - When a soft indentation is uppermost on the indetation stack with
+ * column col' we insert:
+ * `}' in front of token with column<col' and pop indentation off stack,
+ * `;' in front of token with column==col'.
+ * ------------------------------------------------------------------------*/
+
+#define MAXINDENT 100 /* maximum nesting of layout rule */
+static Int layout[MAXINDENT+1];/* indentation stack */
+#define HARD (-1) /* indicates hard indentation */
+static Int indentDepth = (-1); /* current indentation nesting */
+
+static Void local goOffside(col) /* insert offside marker */
+Int col; { /* for specified column */
+ if (indentDepth>=MAXINDENT) {
+ ERRMSG(row) "Too many levels of program nesting"
+ EEND;
+ }
+ layout[++indentDepth] = col;
+}
+
+static Void local unOffside() { /* leave layout rule area */
+ indentDepth--;
+}
+
+static Bool local canUnOffside() { /* Decide if unoffside permitted */
+ return indentDepth>=0 && layout[indentDepth]!=HARD;
+}
+
+/* --------------------------------------------------------------------------
+ * Main tokeniser:
+ * ------------------------------------------------------------------------*/
+
+static Void local skipWhitespace() { /* Skip over whitespace/comments */
+ for (;;) /* Strictly speaking, this code is */
+ if (c0==EOF) /* a little more liberal than the */
+ return; /* report allows ... */
+ else if (c0=='\n')
+ newlineSkip();
+ else if (isIn(c0,SPACE))
+ skip();
+ else if (c0=='{' && c1=='-') { /* (potentially) nested comment */
+ Int nesting = 1;
+ Int origRow = row; /* Save original row number */
+ skip();
+ skip();
+ while (nesting>0 && c0!=EOF)
+ if (c0=='{' && c1=='-') {
+ skip();
+ skip();
+ nesting++;
+ }
+ else if (c0=='-' && c1=='}') {
+ skip();
+ skip();
+ nesting--;
+ }
+ else if (c0=='\n')
+ newlineSkip();
+ else
+ skip();
+ if (nesting>0) {
+ ERRMSG(origRow) "Unterminated nested comment {- ..."
+ EEND;
+ }
+ }
+ else if (c0=='-' && c1=='-') { /* One line comment */
+ do
+ skip();
+ while (c0!='\n' && c0!=EOF);
+ if (c0=='\n')
+ newlineSkip();
+ }
+ else
+ return;
+}
+
+static Bool firstToken; /* Set to TRUE for first token */
+static Int firstTokenIs; /* ... with token value stored here */
+
+static Int local yylex() { /* Read next input token ... */
+ static Bool insertOpen = FALSE;
+ static Bool insertedToken = FALSE;
+ static Text textRepeat;
+
+#define lookAhead(t) {skipWhitespace(); insertOpen = (c0!='{'); return t;}
+
+ if (firstToken) { /* Special case for first token */
+ indentDepth = (-1);
+ firstToken = FALSE;
+ insertOpen = FALSE;
+ insertedToken = FALSE;
+ if (reading==KEYBOARD)
+ textRepeat = findText(repeatStr);
+ return firstTokenIs;
+ }
+
+ if (insertOpen) { /* insert `soft' opening brace */
+ insertOpen = FALSE;
+ insertedToken = TRUE;
+ goOffside(column);
+ push(yylval = mkInt(row));
+ return '{';
+ }
+
+ /* ----------------------------------------------------------------------
+ * Skip white space, and insert tokens to support layout rules as reqd.
+ * --------------------------------------------------------------------*/
+
+ skipWhitespace();
+ startColumn = column;
+ push(yylval = mkInt(row)); /* default token value is line no. */
+ /* subsequent changes to yylval must also set top() to the same value */
+
+ if (indentDepth>=0) /* layout rule(s) active ? */
+ if (insertedToken) /* avoid inserting multiple `;'s */
+ insertedToken = FALSE; /* or putting `;' after `{' */
+ else if (layout[indentDepth]!=HARD)
+ if (column<layout[indentDepth]) {
+ unOffside();
+ return '}';
+ }
+ else if (column==layout[indentDepth] && c0!=EOF) {
+ insertedToken = TRUE;
+ return ';';
+ }
+
+ /* ----------------------------------------------------------------------
+ * Now try to identify token type:
+ * --------------------------------------------------------------------*/
+
+ switch (c0) {
+ case EOF : return 0; /* End of file/input */
+
+ /* The next 10 characters make up the `special' category in 1.3 */
+ case '(' : skip(); return '(';
+ case ')' : skip(); return ')';
+ case ',' : skip(); return ',';
+ case ';' : skip(); return ';';
+ case '[' : skip(); return '[';
+ case ']' : skip(); return ']';
+ case '`' : skip(); return '`';
+ case '{' : goOffside(HARD);
+ skip();
+ return '{';
+ case '}' : if (indentDepth<0) {
+ ERRMSG(row) "Misplaced `}'"
+ EEND;
+ }
+ if (layout[indentDepth]==HARD) /* skip over hard }*/
+ skip();
+ unOffside(); /* otherwise, we have to insert a }*/
+ return '}'; /* to (try to) avoid an error... */
+
+ /* Character and string literals */
+ case '\'' : top() = yylval = readChar();
+ return CHARLIT;
+
+ case '\"' : top() = yylval = readString();
+ return STRINGLIT;
+ }
+
+#if TREX
+ if (c0=='#' && isIn(c1,SMALL)) { /* Look for record selector name */
+ Text it;
+ skip();
+ it = readIdent();
+ top() = yylval = ap(RECSEL,mkExt(it));
+ return identType=RECSELID;
+ }
+#endif
+ if (isIn(c0,LARGE)) { /* Look for qualified name */
+ Text it = readIdent(); /* No keyword begins with LARGE ...*/
+ if (c0=='.' && isIn(c1,(SMALL|LARGE|SYMBOL))) {
+ Text it2 = NIL;
+ skip(); /* Skip qualifying dot */
+ if (isIn(c0,SYMBOL)) { /* Qualified operator */
+ it2 = readOperator();
+ if (opType==CONOP) {
+ top() = yylval = mkQConOp(it,it2);
+ return QCONOP;
+ } else {
+ top() = yylval = mkQVarOp(it,it2);
+ return QVAROP;
+ }
+ } else { /* Qualified identifier */
+ it2 = readIdent();
+ if (identType==CONID) {
+ top() = yylval = mkQCon(it,it2);
+ return QCONID;
+ } else {
+ top() = yylval = mkQVar(it,it2);
+ return QVARID;
+ }
+ }
+ } else {
+ top() = yylval = mkCon(it);
+ return identType;
+ } /* We could easily keep a record of*/
+ } /* the qualifying name here ... */
+ if (isIn(c0,(SMALL|LARGE)) || c0 == '_') {
+ Text it = readIdent();
+
+ if (it==textCase) return CASEXP;
+ if (it==textOfK) lookAhead(OF);
+ if (it==textData) return DATA;
+ if (it==textType) return TYPE;
+ if (it==textIf) return IF;
+ if (it==textThen) return THEN;
+ if (it==textElse) return ELSE;
+ if (it==textWhere) lookAhead(WHERE);
+ if (it==textLet) lookAhead(LET);
+ if (it==textIn) return IN;
+ if (it==textInfix) return INFIX;
+ if (it==textInfixl) return INFIXL;
+ if (it==textInfixr) return INFIXR;
+ if (it==textForeign) return FOREIGN;
+ if (it==textUnsafe) return UNSAFE;
+ if (it==textNewtype) return TNEWTYPE;
+ if (it==textDefault) return DEFAULT;
+ if (it==textDeriving) return DERIVING;
+ if (it==textDo) lookAhead(DO);
+ if (it==textClass) return TCLASS;
+ if (it==textInstance) return TINSTANCE;
+ if (it==textModule) return MODULETOK;
+ if (it==textInterface) return INTERFACE;
+ if (it==textRequires) return REQUIRES;
+ if (it==textImport) return IMPORT;
+ if (it==textExport) return EXPORT;
+ if (it==textHiding) return HIDING;
+ if (it==textQualified) return QUALIFIED;
+ if (it==textAsMod) return ASMOD;
+ if (it==textWildcard) return '_';
+ if (it==textAll) return ALL;
+ if (it==textRepeat && reading==KEYBOARD)
+ return repeatLast();
+
+ top() = yylval = ap((identType==CONID ? CONIDCELL : VARIDCELL),it);
+ return identType;
+ }
+
+ if (isIn(c0,SYMBOL)) {
+ Text it = readOperator();
+
+ if (it==textCoco) return COCO;
+ if (it==textEq) return '=';
+ if (it==textUpto) return UPTO;
+ if (it==textAs) return '@';
+ if (it==textLambda) return '\\';
+ if (it==textBar) return '|';
+ if (it==textFrom) return FROM;
+ if (it==textMinus) return '-';
+ if (it==textBang) return '!';
+ if (it==textDot) return '.';
+ if (it==textArrow) return ARROW;
+ if (it==textLazy) return '~';
+ if (it==textImplies) return IMPLIES;
+ if (it==textRepeat && reading==KEYBOARD)
+ return repeatLast();
+
+ top() = yylval = ap((opType==CONOP ? CONOPCELL : VAROPCELL),it);
+ return opType;
+ }
+
+ if (isIn(c0,DIGIT)) {
+ top() = yylval = readNumber();
+ return NUMLIT;
+ }
+
+ ERRMSG(row) "Unrecognised character `\\%d' in column %d", ((int)c0), column
+ EEND;
+ return 0; /*NOTREACHED*/
+}
+
+static Int local repeatLast() { /* Obtain last expression entered */
+ if (isNull(yylval=getLastExpr())) {
+ ERRMSG(row) "Cannot use %s without any previous input", repeatStr
+ EEND;
+ }
+ return REPEAT;
+}
+
+/* --------------------------------------------------------------------------
+ * main entry points to parser/lexer:
+ * ------------------------------------------------------------------------*/
+
+static Void local parseInput(startWith)/* Parse input with given first tok,*/
+Int startWith; { /* determining whether to read a */
+ firstToken = TRUE; /* script or an expression */
+ firstTokenIs = startWith;
+
+ clearStack();
+ if (yyparse()) { /* This can only be parser overflow */
+ ERRMSG(row) "Parser overflow" /* as all syntax errors are caught */
+ EEND; /* in the parser... */
+ }
+ drop();
+ assert(stackEmpty()); /* stack should now be empty */
+}
+
+Void parseScript(nm,len) /* Read a script */
+String nm;
+Long len; { /* Used to set a target for reading */
+ input(RESET);
+ fileInput(nm,len);
+ parseInput(SCRIPT);
+}
+
+Void parseInterface(nm,len) /* Read a GHC interface file */
+String nm;
+Long len; { /* Used to set a target for reading */
+ input(RESET);
+ fileInput(nm,len);
+ parseInput(INTERFACE);
+}
+
+Void parseExp() { /* Read an expression to evaluate */
+ parseInput(EXPR);
+ setLastExpr(inputExpr);
+}
+
+/* --------------------------------------------------------------------------
+ * Input control:
+ * ------------------------------------------------------------------------*/
+
+Void input(what)
+Int what; {
+ switch (what) {
+ case INSTALL : initCharTab();
+ textCase = findText("case");
+ textOfK = findText("of");
+ textData = findText("data");
+ textType = findText("type");
+ textIf = findText("if");
+ textThen = findText("then");
+ textElse = findText("else");
+ textWhere = findText("where");
+ textLet = findText("let");
+ textIn = findText("in");
+ textInfix = findText("infix");
+ textInfixl = findText("infixl");
+ textInfixr = findText("infixr");
+ textForeign = findText("foreign");
+ textUnsafe = findText("unsafe");
+ textNewtype = findText("newtype");
+ textDefault = findText("default");
+ textDeriving = findText("deriving");
+ textDo = findText("do");
+ textClass = findText("class");
+ textInstance = findText("instance");
+ textCoco = findText("::");
+ textEq = findText("=");
+ textUpto = findText("..");
+ textAs = findText("@");
+ textLambda = findText("\\");
+ textBar = findText("|");
+ textMinus = findText("-");
+ textFrom = findText("<-");
+ textArrow = findText("->");
+ textLazy = findText("~");
+ textBang = findText("!");
+ textDot = findText(".");
+ textImplies = findText("=>");
+#if NPLUSK
+ textPlus = findText("+");
+#endif
+ textModule = findText("module");
+ textInterface = findText("__interface");
+ textRequires = findText("__requires");
+ textImport = findText("import");
+ textExport = findText("__export");
+ textHiding = findText("hiding");
+ textQualified = findText("qualified");
+ textAsMod = findText("as");
+ textWildcard = findText("_");
+ textAll = findText("forall");
+ varMinus = mkVar(textMinus);
+ varBang = mkVar(textBang);
+ varDot = mkVar(textDot);
+ varHiding = mkVar(textHiding);
+ varQualified = mkVar(textQualified);
+ varAsMod = mkVar(textAsMod);
+ conMain = mkCon(findText("Main"));
+ varMain = mkVar(findText("main"));
+ textPrelude = findText("Prelude");
+ textPreludeHugs= findText("PreludeBuiltin");
+ conPrelude = mkCon(textPrelude);
+ conNil = mkCon(findText("[]"));
+ conList = mkCon(findText("[]"));
+ conUnit = mkCon(findText("()"));
+ conPreludeNil = mkQCon(textPreludeHugs,findText("[]"));
+ conPreludeList = mkQCon(textPreludeHugs,findText("[]"));
+ conPreludeUnit = mkQCon(textPreludeHugs,findText("()"));
+ varNegate = mkQVar(textPreludeHugs,findText("negate"));
+ varFlip = mkQVar(textPreludeHugs,findText("flip"));
+ varEnumFrom = mkQVar(textPreludeHugs,findText("enumFrom"));
+ varEnumFromThen = mkQVar(textPreludeHugs,findText("enumFromThen"));
+ varEnumFromTo = mkQVar(textPreludeHugs,findText("enumFromTo"));
+ varEnumFromThenTo = mkQVar(textPreludeHugs,findText("enumFromThenTo"));
+
+ evalDefaults = NIL;
+
+ input(RESET);
+ break;
+
+ case RESET : tyconDefns = NIL;
+ typeInDefns = NIL;
+ valDefns = NIL;
+ opDefns = NIL;
+ classDefns = NIL;
+ instDefns = NIL;
+ selDefns = NIL;
+ genDefns = NIL;
+ unqualImports= NIL;
+ foreignImports= NIL;
+ foreignExports= NIL;
+ defaultDefns = NIL;
+ defaultLine = 0;
+ inputExpr = NIL;
+ imps = NIL;
+ closeAnyInput();
+ break;
+
+ case BREAK : if (reading==KEYBOARD)
+ c0 = EOF;
+ break;
+
+ case MARK : mark(tyconDefns);
+ mark(typeInDefns);
+ mark(valDefns);
+ mark(opDefns);
+ mark(classDefns);
+ mark(instDefns);
+ mark(selDefns);
+ mark(genDefns);
+ mark(unqualImports);
+ mark(foreignImports);
+ mark(foreignExports);
+ mark(defaultDefns);
+ mark(evalDefaults);
+ mark(inputExpr);
+ mark(varMinus);
+ mark(varNegate);
+ mark(varFlip);
+ mark(varEnumFrom);
+ mark(varEnumFromThen);
+ mark(varEnumFromTo);
+ mark(varEnumFromThenTo);
+ mark(varBang);
+ mark(varDot);
+ mark(varHiding);
+ mark(varQualified);
+ mark(varAsMod);
+ mark(varMain);
+ mark(conPrelude);
+ mark(conMain);
+ mark(conNil);
+ mark(conList);
+ mark(conUnit);
+ mark(conPreludeNil);
+ mark(conPreludeList);
+ mark(conPreludeUnit);
+ mark(imps);
+ break;
+ }
+}
+
+/*-------------------------------------------------------------------------*/