view tests/agcl/parsifal/eval-e.syn @ 24:a4899cdfc2d6 default tip

Obfuscate the regexps to strip off the IBM compiler's copyright banners. I don't want bots scanning github to think they're real copyright notices because that could cause real problems.
author David A. Holland
date Mon, 13 Jun 2022 00:40:23 -0400
parents 13d2b8934445
children
line wrap: on
line source

{
/*
 EVALKERN.SYN

 evaluateExpression: A Simple Expression Evaluator
 Copyright (c) 1996 Parsifal Software, All Rights Reserved.
 See the file COPYING for license and usage terms.

 EVALKERN.SYN is the kernel of the example, consisting
 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.

 The parse function defined in EVALKERN.SYN is called
 evalKernel. All communication with evalKernel is via
 the parser control block. The wrapper function,
 evaluateExpression, defined in EVALWRAP.C, provides
 a more convenient interface for the 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 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.

 eval 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 are included in EVALDEFS.H

 EVALKERN.SYN is compiled with the AnaGram parser generator
 yielding EVALKERN.H and EVALKERN.C.

 For information about AnaGram, visit http://www.parsifalsoft.com.
*/

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

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

(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
 -> factor
 -> multiplicative expression:x, '*', factor:y                 =x*y;
 -> multiplicative expression:x, '/', factor:y      =x/checkZero(y);

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

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

(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 + -1
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;

{
#define SYNTAX_ERROR printf("%s in %s, line %d, column %d\n", \
  (PCB).error_message, TOKEN_NAMES[(PCB).error_frame_token], (PCB).line, (PCB).column)

}

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