//
//  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.

   //  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.
      expr * temp = e;

      switch (*str) {
         case '+': {
            str++;
            e = new composite(composite::Addition, temp, parseTerm(str));
            break;
            }
         case '-': {
            str++;
            e = new composite(composite::Subtraction, temp, parseTerm(str));
            break;
            }
         }

      }

   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.

   //  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.
      expr * temp = e;

      switch (*str) {
         case '*': {
            str++;
            e = new composite(composite::Multiplication, temp, parseFactor(str));
            break;
            }
         case '/': {
            str++;
            e = new composite(composite::Division, temp, parseFactor(str));
            break;
            }
         }

      }

   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 constant(strtod(str, &tempStr));
   str = tempStr;

   return e;
}


//
//  End of file.
//