[project @ 1996-01-08 20:28:12 by partain]
[ghc-hetmet.git] / ghc / compiler / yaccParser / infix.c
diff --git a/ghc/compiler/yaccParser/infix.c b/ghc/compiler/yaccParser/infix.c
new file mode 100644 (file)
index 0000000..d53131b
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ *     Infix operator stuff -- modified from LML
+ */
+
+#include <stdio.h>
+
+#include "hspincl.h"
+#ifdef DPH
+#include "hsparser-DPH.tab.h"
+#else
+#include "hsparser.tab.h"
+#endif
+#include "constants.h"
+#include "utils.h"
+
+static short iscope = 1;
+
+static struct infix {
+    char *iname;
+    short ilen;
+    short ifixity;
+    short iprecedence;
+} infixtab[INFIX_SCOPES][MAX_INFIX] =
+  {
+  /*
+       Name            Len     Fixity          Precedence
+  */
+       "$",            1,      INFIXR,         0,
+       ":=",           2,      INFIX,          1,
+       "||",           2,      INFIXR,         2,
+       "&&",           2,      INFIXR,         3,
+       "==",           2,      INFIX,          4,
+       "/=",           2,      INFIX,          4,
+       "<",            1,      INFIX,          4,
+       "<=",           2,      INFIX,          4,
+       ">",            1,      INFIX,          4,
+       ">=",           2,      INFIX,          4,
+       "elem",         4,      INFIX,          4,
+       "notElem",      7,      INFIX,          4,
+       "\\\\",         2,      INFIX,          5,
+       ":",            1,      INFIXR,         5,
+       "++",           2,      INFIXR,         5,
+       "+",            1,      INFIXL,         6,
+       "-",            1,      INFIXL,         6,
+       ":+",           2,      INFIX,          6,
+       "*",            1,      INFIXL,         7,
+       "/",            1,      INFIXL,         7,
+       "mod",          3,      INFIXL,         7,
+       "div",          3,      INFIXL,         7,
+       "rem",          3,      INFIXL,         7,
+       "quot",         4,      INFIXL,         7,
+       ":%",           2,      INFIXL,         7, /* possibly wrong; should be omitted? */
+       "%",            1,      INFIXL,         7,
+       "**",           2,      INFIXR,         8,
+       "^",            1,      INFIXR,         8,
+       "^^",           2,      INFIXR,         8,
+       "!",            1,      INFIXL,         9,
+       "!!",           2,      INFIXL,         9,
+       "//",           2,      INFIXL,         9,
+       ".",            1,      INFIXR,         9
+};
+
+
+#define NFIX 31                                                /* The number of predefined operators */
+#define ninfix (ninfixtab[iscope])
+static int ninfixtab[INFIX_SCOPES] = {NFIX,0};         /* # of predefined operators */
+static char infixstr[MAX_ISTR];
+static char *infixp = infixstr;
+
+/* An "iscope" is an "infix scope": the scope of infix declarations
+   (either the main module or an interface) */
+
+void
+enteriscope()
+{
+  if(++iscope > INFIX_SCOPES)
+    {
+      char errbuf[ERR_BUF_SIZE];
+      sprintf(errbuf,"Too many infix scopes (> %d)\n",INFIX_SCOPES);
+    }
+  ninfix = 0;
+}
+
+void
+exitiscope()
+{
+  --iscope;
+}
+
+void
+exposeis()
+{
+  int i;
+  --iscope;
+
+  for (i=0; i < ninfixtab[iscope+1]; ++i)
+    {
+      struct infix *ip = infixtab[iscope+1] + i;
+      makeinfix(install_literal(ip->iname),ip->ifixity,ip->iprecedence);
+    }
+}
+
+
+static int
+ionelookup(name,iscope)
+  id name;
+  int iscope;
+{
+  int i;
+  char *iname = id_to_string(name);
+
+  for(i = 0; i < ninfixtab[iscope]; i++)
+    {
+      if(strcmp(iname,infixtab[iscope][i].iname)==0)
+       return(i);
+    }
+
+  return(-1);
+}
+
+
+struct infix *
+infixlookup(name)
+  id name;
+{
+  int i;
+  for (i=iscope; i >= 0; --i)
+    {
+     int n = ionelookup(name,i);
+      if (n >= 0)
+       return (infixtab[i]+n);
+    }
+  return (NULL);
+}
+
+int
+nfixes()
+{
+       return ninfix;
+}
+
+char *
+fixop(n)
+  int n;
+{
+       return infixtab[iscope][n].iname;
+}
+
+char *
+fixtype(n)
+  int n;
+{
+       switch(infixtab[iscope][n].ifixity) {
+       case INFIXL:
+                  return "infixl";
+
+       case INFIXR:
+                  return "infixr";
+
+       case INFIX:
+                return "infix";
+
+       default : return 0;
+       /* Why might it return 0 ?? (WDP 94/11) */
+       }
+}
+
+
+int
+fixity(n)
+  int n;
+{
+#ifdef HSP_DEBUG
+  fprintf(stderr,"fixity of %s (at %d) is %d\n",infixtab[iscope][n].iname,n,infixtab[iscope][n].ifixity);
+#endif
+  return(n < 0? INFIXL: infixtab[iscope][n].ifixity);
+}
+
+
+long int
+precedence(n)
+  int n;
+{
+#ifdef HSP_DEBUG
+  fprintf(stderr,"precedence of %s (at %d) is %d\n",infixtab[iscope][n].iname,n,infixtab[iscope][n].iprecedence);
+#endif
+  return(n < 0? 9: infixtab[iscope][n].iprecedence);
+}
+
+
+int
+pfixity(ip)
+  struct infix *ip;
+{
+#ifdef HSP_DEBUG
+  fprintf(stderr,"fixity of %s is %d\n",ip->iname,ip->ifixity);
+#endif
+  return(ip == NULL? INFIXL: ip->ifixity);
+}
+
+int
+pprecedence(ip)
+  struct infix *ip;
+{
+#ifdef HSP_DEBUG
+  fprintf(stderr,"precedence of %s (at %d) is %d\n",ip->iname,ip->iprecedence);
+#endif
+  return(ip == NULL? 9: ip->iprecedence);
+}
+
+
+void
+makeinfix(ssi, fixity, precedence)
+  id ssi;
+  int fixity, precedence;
+{
+    register int i, l;
+    char s[1000];
+    char *ss = id_to_string(ssi);
+
+    for(i=0; i < ninfix; ++i)
+      {
+       if(strcmp(ss,infixtab[iscope][i].iname)==0)
+         {
+           /* Allow duplicate definitions if they are identical */
+           if(infixtab[iscope][i].ifixity!=fixity || 
+              infixtab[iscope][i].iprecedence!=precedence )
+             {
+               char errbuf[ERR_BUF_SIZE];
+               sprintf(errbuf,"(%s) already declared to be %s %d\n",
+                       ss,
+                       fixtype(i),
+                       infixtab[iscope][i].iprecedence);
+               hsperror(errbuf);
+             }
+           return;
+         }
+      }
+
+    strcpy(s, ss);
+    l = strlen(s);
+    s[l] = 0;
+
+    if (ninfix >= MAX_INFIX || infixp+l+1 >= &infixstr[MAX_ISTR]) {
+        char errbuf[ERR_BUF_SIZE];
+       sprintf(errbuf,"Too many Infix identifiers (> %d)",MAX_INFIX);
+       hsperror(errbuf);
+    }
+
+#ifdef HSP_DEBUG
+    fprintf(stderr,"adding %s (was %s), fixity=%d, prec=%d\n",s,ss,fixity,precedence);
+#endif
+    infixtab[iscope][ninfix].iname = infixp;
+    strcpy(infixp, s);
+    infixp += l+1;
+    infixtab[iscope][ninfix].ifixity = fixity;
+    infixtab[iscope][ninfix].iprecedence = precedence;
+    infixtab[iscope][ninfix].ilen = l-1;
+    ninfix++;
+}