{
/*
 EVALKERN.SYN  Version 1.1

 evaluateExpression: A Simple Expression Evaluator
 Copyright (c) 1996 - 1999 Parsifal Software, All
 Rights Reserved.

 evaluateExpression is an example program for evaluating
 C-style expressions which demonstrates some of the
 capabilities of the AnaGram parser generator.

 EVALKERN.SYN is the kernel of the example, consisting
 of the definition of the expression parser itself.
 Support functions are defined in EVALWRAP.C. A test
 program is defined in EVALDEMO.C. Global declarations
 are contained in EVALDEFS.H.

 EVALKERN.SYN is an AnaGram syntax (.SYN) file which
 describes, in this case, the syntax of expressions. It
 is written in the AnaGram language, which is a variang of
 BNF (Backus-Naur Form) with additional constructs to
 allow more concise descriptions and greater analytical
 power. AnaGram analyzes a syntax file containing a
 grammar and produces a parser in C or C++.

 The vital part of a syntax file consists of its
 productions, each of which takes the form:
        p -> p1, p2, p3, ... pn
 Productions describe the grammatical elements to be
 recognized by the parser. This rule says that the
 grammatical element p consists of a single instance
 each of the elements p1, p2, p3, ... pn in order.

 You will notice that a production may have some C code
 at its right end following an equals sign. This code
 constitutes a "reduction procedure", which will be
 executed automatically when the grammatical element
 specified by the production is identified in the input
 to the parser.

 AnaGram analyzes EVALKERN.SYN and produces the parser
 file EVALKERN.C and a header file EVALKERN.H.

 The parse function defined in EVALKERN.SYN is called
 evalKernel. All communication with evalKernel is via
 the parser control block (PCB). The wrapper function,
 evaluateExpression, defined in EVALWRAP.C, provides
 a more convenient interface for the parse function.

 The expression syntax is borrowed from C but with the
 addition of the FORTRAN exponentiation operator (**).

 The cast, increment, and decrement operators are not
 implemented, nor are the following operations that
 are defined only for integers:
   Bitwise logical operators:   &, |, ^, ~, &=, |=, ^=
   Remainder operators:         %, %=
   Shift operators:             <<, >>, >>=, <<=

 The supported operations are:
   Assignment operators:        =, +=, -=, *=, /=
   Conditional expressions:     ? :
   Logical operators:           !, &&, ||
   Comparison operators:        ==, !=, <, <=, >, >=
   Binary arithmetic operators: +, -, *, /
   Exponentiation:              **
   Unary arithmetic operators:  +, -
   Parentheses
   Function calls

 All arithmetic is double precision floating point.

 Input strings may contain any number of expressions, separated by
 commas or semicolons. White space may be used freely, including
 both C and C++ style comments.

 evalKernel() makes the following external calls:
 ------------------------------------------------
   void pushChar(int character);
     Push the specified character onto a character stack.

   double *locateVariable(int nameLength);
     Pop the last nameLength characters from the character stack
     and, treating them as the name of a variable, return a pointer
     to the location where the value of the variable is stored.

   void pushArg(double value);
     Push the specified value onto an argument stack.

   double callFunction(nameLength, int argCount);
     Pop the last nameLength characters from the character stack
     and, treating them as the name of a function, identify the
     function and invoke it with argCount arguments popped from
     the argument stack.

   double checkZero(double value);
     Verify that value is not zero.

 Overrides for macros defined by AnaGram, such as SYNTAX_ERROR
 should be included in EVALDEFS.H

 For information about AnaGram, contact
   Parsifal Software
   http://www.parsifalsoft.com
   info@parsifalsoft.com
   1-800-879-2755, Voice/Fax 1-508-358-2564
   P.O. Box 219
   Wayland, MA 01778
*/

#include <math.h>
#include "evaldefs.h"                  // defines external interface

}
// -- CONFIGURATION SECTION ----------------------------
[
  default token type = double
  disregard white space
  lexeme {real, name}
  pointer input
  parser name = evalKernel
]
//------------------------------------------------------

(void) input string $                       // specify grammar token
 -> expressions, eof

(void) expressions
 -> expression?
 -> expressions, ',' + ';', expression?

expression
 -> conditional expression
 -> name:k, '=',  expression:x             =*locateVariable(k)  = x;
 -> name:k, "+=", expression:x             =*locateVariable(k) += x;
 -> name:k, "-=", expression:x             =*locateVariable(k) -= x;
 -> name:k, "*=", expression:x             =*locateVariable(k) *= x;
 -> name:k, "/=", expression:x             =*locateVariable(k) /= x;

conditional expression
 -> logical or expression
 -> logical or expression:c, '?',
      expression:x, ':', conditional expression:y            =c?x:y;

logical or expression
 -> logical and expression
 -> logical or expression:x, "||", logical and expression:y   =x||y;

logical and expression
 -> equality expression
 -> logical and expression:x, "&&", equality expression:y     =x&&y;

equality expression
 -> relational expression
 -> equality expression:x, "==", relational expression:y      =x==y;
 -> equality expression:x, "!=", relational expression:y      =x!=y;

relational expression
 -> additive expression
 -> relational expression:x, '<',  additive expression:y       =x<y;
 -> relational expression:x, "<=", additive expression:y      =x<=y;
 -> relational expression:x, '>',  additive expression:y       =x>y;
 -> relational expression:x, ">=", additive expression:y      =x>=y;

additive expression
 -> multiplicative expression
 -> additive expression:x, '+', multiplicative expression:y    =x+y;
 -> additive expression:x, '-', multiplicative expression:y    =x-y;

multiplicative expression
 -> unary expression
 -> multiplicative expression:x, '*', unary expression:y           =x*y;
 -> multiplicative expression:x, '/', unary expression:y =x/checkZero(y);

unary expression
 -> factor:x                                                    = x;
 -> '-', unary expression:x                                     =-x;
 -> '+', unary expression:x                                     = x;

factor
 -> primary
 -> primary:x, "**", unary expression:y                  = pow(x,y);

primary
 -> real
 -> name:k                                      =*locateVariable(k);
 -> '(', expression:x, ')'                                       =x;
 -> '!', primary:x                                              =!x;


/**** Function calls **********************************************/

/* The following productions have been added to make the grammar  */
/* handle function calls with any number of arguments. Note how   */
/* easy it is to change the grammar - this is all you have to do  */
/* to handle function calls. Arguments may be expressions.        */

primary
 -> name:k, '(', arguments:n, ')'                =callFunction(k,n);

(int) arguments               //value of arguments is number of args
 ->                                                              =0;
 -> argument list              //argument count passes automatically

(int) argument list       //value of argument list is number of args
 -> expression:x                                     =pushArg(x), 1;
 -> argument list:k, ',', expression:x             =pushArg(x), k+1;
/******************************************************************/


// -- LEXICAL UNITS ------------------------------------------------
digit   = '0-9'
eof     = 0
letter  = 'a-z' + 'A-Z' + '_'

(void) white space
 -> ' ' + '\t' + '\f' + '\v' + '\r' + '\n'
 -> "/*", ~eof?..., "*/"                          // C style comment
 -> "//", ~(eof+'\n')?..., '\n'                 // C++ style comment

real
 -> simple real
 -> simple real:x, 'e'+'E', '+'?,exponent:e            =x*pow(10,e);
 -> simple real:x, 'e'+'E', '-',exponent:e            =x*pow(10,-e);

simple real
 -> integer part:i, '.', fraction part:f                      = i+f;
 -> integer part, '.'?
 -> '.', fraction part:f                                        = f;

integer part
 -> digit:d                                                 = d-'0';
 -> integer part:x, digit:d                          = 10*x + d-'0';

fraction part
 -> digit:d                                            =(d-'0')/10.;
 -> digit:d, fraction part:f                       =(d-'0' + f)/10.;

(int) exponent
 -> digit:d                                                 = d-'0';
 -> exponent:x, digit:d                              = 10*x + d-'0';

(int) name           //value of name token is length of name string
 -> letter: c                                       =pushChar(c), 1;
 -> name:k, letter+digit: c                       =pushChar(c), k+1;

/********************* End of EVALKERN.SYN ************************/
