//
//  NAME
//    parse.cpp
//
//  DESCRIPTION
//    This file contains functions used to implement the Parse module.
//
//    For descriptions of the parameters and return values of 
//    exported (non-static) functions, see parse.h.
//


//
//  Include files.
//

#include <stdlib.h>
#include <iostream.h>
#include "bool.h"
#include "parse.h"


//
//  Function prototypes.
//

static expr * parseExpr(const char * & str);
static expr * parseTerm(const char * & str);
static expr * parseFactor(const char * & str);


//
//  NAME
//    parse
//
//  DESCRIPTION
//    This function parses the given character string using
//    recursion.
//

expr * parse(const char * str) {

   return parseExpr(str);
}


//
//  NAME
//    parseExpr
//
//  DESCRIPTION
//    This function parses an expression from the given character
//    string.
//
//  PARAMETERS
//    str  (in)  - string to parse.
//    ptr  (out) - pointer to the remainder of the string.
//
//  RETURNS
//    pointer to the expression.
//

static expr * parseExpr(const char * & str) {

   expr * e;             // Expression to return.
   expr * tempExpr;      // Temporary expression holder.

   //  Parse the first term.
   e = parseTerm(str);

   //  Loop while there are more terms in the expression.
   while ((*str == '+') || (*str == '-')) {

      //  Make the current expression a subexpression.
      tempExpr = e;
      e = new expr;
      e->op1 = tempExpr;

      switch (*str) {
         case '+': {
            e->oper = Addition;
            str++;
            break;
            }
         case '-': {
            e->oper = Subtraction;
            str++;
            break;
            }
         }

      //  Parse the next term.
      e->op2 = parseTerm(str);
      }

   return e;
}


//
//  NAME
//    parseTerm
//
//  DESCRIPTION
//    This function parses a term from the given character
//    string.
//
//  PARAMETERS
//    str  (in)  - string to parse.
//    ptr  (out) - pointer to the remainder of the string.
//
//  RETURNS
//    pointer to the expression.
//

static expr * parseTerm(const char * & str) {

   expr * e;             // Expression to return.
   expr * tempExpr;      // Temporary expression holder.

   //  Parse the first factor.
   e = parseFactor(str);

   //  Loop while there are more factor in the term.
   while ((*str == '*') || (*str == '/')) {

      //  Make the current expression a subexpression.
      tempExpr = e;
      e = new expr;
      e->op1 = tempExpr;

      switch (*str) {
         case '*': {
            e->oper = Multiplication;
            str++;
            break;
            }
         case '/': {
            e->oper = Division;
            str++;
            break;
            }
         }

      //  Parse the next factor.
      e->op2 = parseFactor(str);
      }

   return e;
}


//
//  NAME
//    parseFactor
//
//  DESCRIPTION
//    This function parses a factor from the given character
//    string.
//
//  PARAMETERS
//    str  (in)  - string to parse.
//    ptr  (out) - pointer to the remainder of the string.
//
//  RETURNS
//    pointer to the factor.
//

static expr * parseFactor(const char * & str) {

   expr * e;         // Expression to return.
   char * tempStr;   // Temporary placeholder.

   //  Is the next character a parenthesis?
   if (*str == '(') {
      str++;            // Skip over '('.
      e = parseExpr(str);
      str++;            // Skip over ')'.
      return e;
      }

   //  Parse the constant.
   e         = new expr;
   e->oper   = Constant;
   e->number = strtod(str, &tempStr);
   e->op1    = NULL;
   e->op2    = NULL;

   str       = tempStr;

   return e;
}


//
//  End of file.
//