#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "Wff.h"
#include "Parser.h"

Wff forked(int, Wff, Wff); /* prototype */
Wff wff();                 /* prototype */


char  word[11];  int len;  int ch;  int sy; /*parser "state" variables*/


void Error(char *msg) /* print error message and stop */
 { printf("Error: %s (word=%s)(ch=%c)\n", msg, word, ch); exit(-1); }/*Error*/


void insymbol()  /* Simple Lexical Analyser Routine */
 { strncpy(word, "?", 10);
   while( ch==' ' ) ch=getchar();
   len = 0;
   if( ch == '\n' ) sy=eoExp;
   else
    { if( ch >= 'a' && ch <= 'z' ) /* alphanumeric */
       { while( ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9' )
          { if(len <= 10)
             { word[len] = ch; len++; word[len] = 0/*eos*/; }
            ch=getchar();
          }
         if(      strcmp("true",  word) == 0 ) sy = trueSy;
         else if( strcmp("false", word) == 0 ) sy = falseSy;
         else if( strcmp("not",   word) == 0 ) sy = notSy;
         else if( strcmp("and",   word) == 0 ) sy = andSy;
         else if( strcmp("or",    word) == 0 ) sy = orSy;
         else sy=ident;
       }
      else/*not alphanumeric*/
       { word[0]=ch; word[1]=0; len=1;
         switch(ch)
          { case '&': sy=andSy;   break;
            case '|': sy=orSy;    break;
            case '(': sy=openSy;  break;
            case ')': sy=closeSy; break;
            case '-': /* drop through */
            case '=':
              ch = getchar();
              if( ch == '>' ) { sy=implies; break; }
            default: Error("bad symbol");
          }/*switch*/
         ch=getchar();
    }  }
 }/*insymbol*/


void check( int symbol, char *errMsg ) /* check and skip specified symbol */
 { if( sy == symbol ) insymbol(); else Error(errMsg); }


Wff sequence(Wff NonTerminal(void), int symbols)                  /*L*/
/* Parse  <NonTerminal> [ symbols <NonTerminal> ]*                  .*/
 { int operator;  Wff T;                                          /*A*/
   T = NonTerminal();                                             /*l*/
   while( sy & symbols ) /* i.e. sy in symbols */                 /*l*/
    { operator = sy;                                              /*i*/
      insymbol();                                                 /*s*/
      T = forked(operator, T, NonTerminal()); /* left associative.  o*/
    }                                                             /*n*/
   return T;
 }/*sequence*/


Wff operand()                               /* the parser proper starts here */
 { Wff oprnd;
   if( sy & (ident | trueSy | falseSy) )             /* ident | true | false */
    { oprnd = forked(sy, (Wff)NULL, (Wff)NULL);
      if( sy == ident ) strncpy(oprnd->id, word, 10);
      insymbol();
      return oprnd;
    }
   else if( sy == notSy )                                     /* not operand */
    { insymbol();
      return forked(notSy, (Wff)NULL, operand()); /* NB unary operator */
    }
   else if( sy == openSy )                                        /* ( wff ) */
    { insymbol();
      oprnd = wff();
      check(closeSy, "missing )");
      return oprnd;
    }
   else Error("bad Operand");
 }/*operand*/


/* Released under the GNU General Public License  Version 2, June 1991,
   L.Allison 19 February 2001, 18 January 2002,
*/

                                 /* conjunction ::= operand [and operand]*   */
Wff conjunction() { return sequence(operand,     andSy);   }

                          /* disjunction ::= conjunction [or conjunction]*   */
Wff disjunction() { return sequence(conjunction, orSy);    }

                                  /* wff ::= disjunction [=> disjunction]*   */
Wff wff()         { return sequence(disjunction, implies); }

/* i.e. a wff is a sequence of one or more        */
/*      disjunctions separated by implies symbols */


Wff parse()
 { Wff w;
   strncpy(word, "?", 10); len=0; ch=' '; /* initialise state... */

   insymbol();                            /* begin! */
   w = wff();                             /* parse  */
   check(eoExp, "incomplete");            /* done?  */

   return w;
 }/*parse*/

/* Simple Wff Parser */
