|
|
|
|
||
|
DEFINITION MODULE FormulIntrpr; (******************************************************************* Module FormulIntrpr (Version 1.2) Copyright (c) 1988-2006 by Olivier Roth, Andreas Fischlin, Reiner Zah and ETH Zurich. Purpose Management and computation of mathematical formulas/expressions given in form of strings. Remarks See companion module FormulVars for the declaration of real variable operands to be used in formulas. This module supports the dynamic installation or deinstallation of monadic, diadic, and triadic functions, which may be freely used during the interpretation of formulas. This module supports only a single scope, i.e. all intalled functions are always available for evaluations in all expressions. Reference: Meyzis, E. (1988). "Der Formelinterpreter; Teil IV: Implementation in Modula-2", Toolbox, Dec. 1988: 49-53. The EBNF for expressions: ========================= numDigit "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9". schar "a"|"b"|"c"|"d"|"e"|"f"|"g"|"h"|"i"|"j"|"k"|"l"|"m"| "n"|"o"|"p"|"q"|"r"|"s"|"t"|"u"|"v"|"w"|"x"|"y"|"z". cchar "A"|"B"|"C"|"D"|"E"|"F"|"G"|"H"|"I"|"J"|"K"|"L"|"M"| "N"|"O"|"P"|"Q"|"R"|"S"|"T"|"U"|"V"|"W"|"X"|"Y"|"Z". character schar|cchar. number numDigit{numDigit}. scaleFactor "e"["+"|"-"]number. realNumber number["."number][scaleFactor]. ident character{character|numDigit}. mathFunction "abs"|"sin"|"cos"|"tan"|"sqrt"|"exp"|"ln". factor realNumber|ident|mathFunction|"("term")". sign ["-"]factor. exponent sign["^"sign]. product exponent[("*"|"/")exponent]. term product[("+"|"-")product]. NOTE: In contrast to variable idents, mathFunction idents are not case sensitive. Terms: ====== Expression: the definition of a mathematical construct specified by a formula (string). Formula: is the textual form of an expression, i.e. a string containing names of variables, operators, brackets and mathematical functions. Function: a mathematical mapping of 1, 2 or 3 arguments (independent variables) to another dependent variable. E.g. F "sin": y <- sin(x) maps x to y according to the monadic (1 argument) function sin. You may use any type of function (may require installation by InstallMonadicFunc etc. procedures) as long as the function requires not more than 3 arguments. Operator: basic algebraic operators such as + - * / and ^. Operand: actual argument passed to a mathematical function Programming o Design Olivier Roth 27/11/1988 Andreas Fischlin 24/04/1996 (Version 1.2) o Implementation Olivier Roth 27/11/1988 Reiner Zah 02/09/1990 Andreas Fischlin 24/04/1996 ETH Zurich Systems Ecology CHN E 35.1 Universitaetstrasse 16 8092 Zurich SWITZERLAND URLs: <mailto:RAMSES@env.ethz.ch> <http://www.sysecol.ethz.ch> <http://www.sysecol.ethz.ch/SimSoftware/RAMSES> Last revision of definition: 24/04/1996 AF *******************************************************************) FROM SYSTEM IMPORT ADDRESS; TYPE Expression; Func1Arg = PROCEDURE ( REAL ): REAL; Func2Arg = PROCEDURE ( REAL, REAL ): REAL; Func3Arg = PROCEDURE ( REAL, REAL, REAL ): REAL; SyntaxError = ( noErr, badReal, noLParen, noRParen, tooManyRParen, noComma, unknownIdent, unknownFctIdent, badChar, badOperator, illEnd ); Symbol = ( null, ident, num, lParen, rParen, comma, plus, minus, multiply, divide, power, unknown ); ProcPtr = POINTER TO ADDRESS; FuncType = (none, monadic, diadic, triadic); SymbolProc = PROCEDURE ( Symbol, INTEGER, ARRAY OF CHAR ); (* type of found symbol, pos = index where symbol starts, symStr = found symbol *) StringProc = PROCEDURE ( VAR ARRAY OF CHAR ); ArithmeticError = (noAriErr, invalidOperand, underFlow, overFlow, divByZero, complex, undefined); VAR notInstalledExpression: Expression; (* read only *) (**************************************************************) PROCEDURE GetSymbol( VAR formulStr: ARRAY OF CHAR; len : INTEGER; VAR pos : INTEGER; VAR symStr : ARRAY OF CHAR): Symbol; (* ========== This is the basic scanner procedure also used by ScanFormula. From position pos of the formulStr containing len characters, procedure GetSymbol returns the type of the next symbol and copies the symbol itself to symStr. It requires at all times 0 <= pos < len = Length(formulStr) plus Length(symStr >= 2 ); *) PROCEDURE ScanFormula( VAR formulStr: ARRAY OF CHAR; doWithSymbol: SymbolProc ); (* ============== This procedure scans the entire formulStr and calls the SymbolProc doWithSymbol consecutively for each encountered symbol (Uses GetSymbol). In doWithSymbol you may extract idents or look ahead by calling GetSymbol for particular parsing purposes. *) PROCEDURE WhatFunc( VAR ident: ARRAY OF CHAR; VAR p: ProcPtr ): FuncType; (* ======== This procedure returns the type of function associated with ident, returns none if ident is not an installed function. The address pointing to the procedure with name ident is returned with p. Note that functions idents are not case sensitive. *) (**************************************************************) PROCEDURE InstallExpression( VAR e : Expression; eName : ARRAY OF CHAR; formulaStr : ARRAY OF CHAR; VAR posBadCHinF : INTEGER ); PROCEDURE DeclAndParseExpr( VAR e : Expression; fName : ARRAY OF CHAR; VAR formulaStr : ARRAY OF CHAR; VAR posBadCHinF : INTEGER ); (* ================= Install an expression e defined by the formula F within an assignment of the form Y = F(var), e.g. "a*2/(1+Exp(b))" given by the string formulaStr. Additionally a name can be assigned by eName. If the given formula was successfully parsed the variable posBadCHinF returns -1, otherwise the position of the first erroneous symbol within formulaStr is returned. If the formula was not successfully compiled the expression Y = 0.0 is installed. Attempts to reinstall an expression another time purges the former expression and replaces it by the new one. DeclAndParseExpr is an alternative with formulaStr as a var parameter for speed up reasons only. If the installation fails, e.g. due to a memory shortage, e returns notInstalledExpression. The following mathematical operators are available: +, -, *, /, ^. The following mathematical (non case sensitive idents, all arguments reals, return real) are initally preinstalled: Mmonadic functions: ABS, SIN, COS, TAN, SQRT, LN, EXP Diadic functions: MIN(x,y), MAX(x,y) Triadic functions: SWITCH(x,y1,y2) if x < 0 returns y1 else returns y2 LIMIT(x,min,max) if x < min returns min if x > max returns max else returns x The computing follows the ordinary infix notation, i.e. parantheses "(" and ")" may be used to control priorities of evaluation. E.g. a * b + c adds c to the product of a times b, but a * (b + c) multiplies a with the sum of b and c. *) PROCEDURE LastSyntaxErr(): SyntaxError; (* ============= Returns the last, possibly encountered syntax error during the parsing process initiated by InstallExpression respectively DeclAndParseExpr. *) PROCEDURE GetErrMsg( err: SyntaxError; VAR errStr: ARRAY OF CHAR ); (* ========= Returns the error message in "errStr" corresponding to the value of err. It is suggested to use that procedure together with the variable formErr. *) PROCEDURE RemoveExpression( VAR e : Expression ); (* ================ Frees the memory used by the expression e and marks the variable e as an undefined Expression. *) PROCEDURE ComputeExpression( e : Expression; VAR ariErr: ArithmeticError): REAL; (* ================= Returns the computed value of expression e denoting a formula string. Note: arithmetic errors, i.e. over-/underflow, division by 0, negative arguments for LN, etc. are returned by arithmErr. However, computation continues as best as can, i.e.: invalid operand => 0.0 underflow 1/infinity => 0.0 overflow - infinity => MIN(REAL) overflow + infinity => MAX(REAL) division by 0 +x/0 => MAX(REAL) division by 0 -x/0 => MIN(REAL) undefined 0/0 => 0.0 complex SQRT(-x) => 0.0 *) PROCEDURE GetArithmErrMsg (ariErr: ArithmeticError; VAR errStr: ARRAY OF CHAR); (* =============== Returns the error message associated with the arithmetic error ariErr. Typically you call this procedure if ComputeExpression returns with arithmErr <> noAriErr to learn about which arithmetic error was actually encountered (it is the first error condition encountered during formula interpretation). *) PROCEDURE ExtractFString( e: Expression; VAR fstr: ARRAY OF CHAR ); (* ============== Returns the stored formula string of expression e (is also stored if the installed expression was illegal). *) PROCEDURE GetFormulaName( e: Expression; VAR fName: ARRAY OF CHAR ); (* ============== Returns the stored formula name of expression e. *) PROCEDURE SetFormulaName( e: Expression; VAR fName: ARRAY OF CHAR ); (* ============== Sets the formula name of expression e. *) PROCEDURE InstallMonadicFunc( f1 : Func1Arg; funcName: ARRAY OF CHAR; VAR done: BOOLEAN ); (* ================== Allows the installation of a ONE argument math function f1, e.g. Sin( arg1 ). The function's name is passed via funcName ! Note that function names are not case sensitive, (but variables are). *) PROCEDURE InstallDiadicFunc( f2 : Func2Arg; funcName: ARRAY OF CHAR; VAR done: BOOLEAN ); (* ================= Allows the installation of a TWO argument math function f2, e.g. RMax( arg1, arg2 ). The function's name is passed via funcName ! Note that function names are not case sensitive, (but variables are). *) PROCEDURE InstallTriadicFunc( f3 : Func3Arg; funcName: ARRAY OF CHAR; VAR done: BOOLEAN ); (* ================== Allows the installation of a THREE argument math function f3, e.g. RLimit( x, xlow, xhigh ). The function's name is passed via funcName ! Note that function names are not case sensitive, (but variables are). *) PROCEDURE RemoveFunc( funcName: ARRAY OF CHAR ); (* ========== Allows to remove a previously installed function via its name. ! Note that function names are not case sensitive. *) PROCEDURE PresentFuncNames( funcType: FuncType; strProc: StringProc ); (* ================ This procedure calls the StrProc for each installed function of the specified funcType in ascending alphabetic order. *) END FormulIntrpr.
|
||
|
|
|