📄 parse.c
字号:
/* *//* *//* FORMULA PARSER *//* *//* USER CALLABLE ROUTINES *//* *//* (1) double evalform (char **f, char *err) *//* *//* returns value of expression. *//* *//* *f ASCII string containing formula. Returns *//* pointer to end of string if formula is ok, *//* otherwise points to location of error. *//* *err Returns 0 if OK, >0 for error. Use value to *//* call *parsemessage for error message *//* *//* (2) char *parsemsg (char err) *//* *//* returns pointer to error message *//* *//* err error value returned by evalfrom *//* *//* *//* *//* FORMULA SYNTAX *//* *//* evalform can recognize the following items *//* *//* (1) number constants *//* (2) constants "e" and "pi" *//* (3) operators + - * / ^ ( ) = *//* (unlimited number of parenthesis) *//* (4) variables (up to MAXNUMBERVAR of them) *//* (5) single argument functions *//* ( SIN COS TAN EXP LOG LOG10 ACOS ASIN ATAN ABS SQRT RAND) *//* *//* VARIABLES *//* *//* () names can be any length - case is irrelevant *//* () up to MAXNUMBERVAR variables *//* () set variables with = *//* string "a = 5^2" sets variable A to 25. *//* () variables used in right hand side of equation *//* are taken to be zero if not initialized. *//* () can set multiple variables on one line. *//* string "a0 = a1 = a2 = sqrt(2)" sets all three *//* variables to sqrt(2). *//* *//* *//* *//*************************************************************************Include Files*************************************************************************/#include <stdlib.h>#include <math.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include "parse.h"#include "cdhouse.h"/*************************************************************************Defines*************************************************************************/#define MAXNUMBERVAR 128#define MAXTOKENLENGTH 32#define FALSE 0#define TRUE 1#define NOTFOUND -1#define NOROOM -2#define NOHEAP -3#define BOOLEAN int#define DEFAULT_RETURN 0.0#ifndef M_E#define M_E 2.7182818284590452354E0#endif#ifndef M_PI#define M_PI 3.1415926535897931160E0#endif/*************************************************************************Type Definitions*************************************************************************//* OPERATORS (IN ORDER FROM LOWEST TO HIGHEST PRECEDENCE) */typedef enum { OP_EndLine, OP_BeginLine, OP_CloseParenthesis, OP_OpenParenthesis, OP_Assignment, OP_Add, OP_Subtract, OP_Multiply, OP_Divide, OP_RaisePower } operator_t;typedef enum { FUNC_err, FUNC_sin, FUNC_cos, FUNC_tan, FUNC_exp, FUNC_log, FUNC_log10, FUNC_fabs, FUNC_acos, FUNC_asin, FUNC_atan, FUNC_sqrt, FUNC_int, FUNC_rand, FUNC_nrand } function_t;typedef enum { ERROR_none, ERROR_operand, ERROR_openparen, ERROR_closeparen, ERROR_operator, ERROR_division, ERROR_function, ERROR_variable_expected, ERROR_variable_full, ERROR_variable_long, ERROR_heap_full, ERROR_parameter } errorcode_t;/*************************************************************************Glogal Variables*************************************************************************/extern int Debug_g;/*************************************************************************Module-Wide Variables*************************************************************************/static char *VariableNames_m [MAXNUMBERVAR];static double VariableValues_m [MAXNUMBERVAR];static char *FormulaString_m;static char TokenString_m[MAXTOKENLENGTH];static double DivisorValue_m;static int ParenthesisLevel_m;static errorcode_t ErrorCode_m;static int NumberOfVariables_m = 0;/*************************************************************************Local Function Prototypes*************************************************************************/char *_strhed (char **);int GetVariableID (char *TestName);int AssignVariable ( char *NewName, double NewValue);function_t LookupFunction (char *FunctionName);double EvaluateFunction (function_t InputFunction, double x);static void SkipWhiteSpace (char **f);int GetNextTokenLength ( char *cptr );void CopyUppercaseString ( char *TargetString, char *SourceString, int Size );double ParseFormula (operator_t *PendingOperator);/*************************************************************************Local Subroutines*************************************************************************//* RETURN Variable Index CORRESPONDING TO VARIABLE NAME */int GetVariableID (char *TestName) { int VariableID = NumberOfVariables_m-1; /* SEARCH STORED VARIABLE NAMES */ for (VariableID=0; VariableID<NumberOfVariables_m; VariableID++) { if (strcmpi( VariableNames_m [ VariableID ], TestName) == 0) /* RETURN CURRENT INDEX */ return VariableID; } /* VARIABLE NAME NOT FOUND */ return NOTFOUND; }function_t LookupFunction (char *FunctionName) { if (!strcmp(FunctionName, "SIN" )) return( FUNC_sin); if (!strcmp(FunctionName, "COS" )) return( FUNC_cos); if (!strcmp(FunctionName, "TAN" )) return( FUNC_tan); if (!strcmp(FunctionName, "EXP" )) return( FUNC_exp); if (!strcmp(FunctionName, "LOG" )) return( FUNC_log); if (!strcmp(FunctionName, "LOG10")) return( FUNC_log10); if (!strcmp(FunctionName, "ACOS" )) return( FUNC_acos); if (!strcmp(FunctionName, "ASIN" )) return( FUNC_asin); if (!strcmp(FunctionName, "ATAN" )) return( FUNC_atan); if (!strcmp(FunctionName, "ABS" )) return( FUNC_fabs); if (!strcmp(FunctionName, "SQRT" )) return( FUNC_sqrt); if (!strcmp(FunctionName, "INT" )) return( FUNC_int ); if (!strcmp(FunctionName, "RAND" )) return( FUNC_rand ); if (!strcmp(FunctionName, "NRAND")) return( FUNC_nrand); return(FUNC_err); }double EvaluateFunction (function_t InputFunction, double x) { BOOLEAN Ok; /* Check argument ranges */ Ok = TRUE; switch (InputFunction) { case FUNC_log: case FUNC_log10: case FUNC_sqrt: if (x<=0.0) { Ok = FALSE; } break; case FUNC_acos: case FUNC_asin: if (x<-1.0 || x>=1.0) { Ok = FALSE; } } /* If arguments not ok, then return 0 */ if (!Ok) { ErrorCode_m = ERROR_parameter; return DEFAULT_RETURN; } /* Evaluate function */ switch (InputFunction) { case FUNC_sin : return sin(x); case FUNC_cos : return cos(x); case FUNC_tan : return tan(x); case FUNC_exp : return exp(x); case FUNC_log : return log(x); case FUNC_log10 : return log10(x); case FUNC_fabs : return fabs(x); case FUNC_acos : return acos(x); case FUNC_asin : return asin(x); case FUNC_atan : return atan(x); case FUNC_sqrt : return sqrt(x); case FUNC_rand : return (x/RAND_MAX)*rand(); case FUNC_nrand : return x*nrand(); case FUNC_int : /* INSURES INT(-1.2) = -1, NOT -2 */ if (x<0) return ceil(x); else return floor(x); default: printf("\nINTERNAL ERROR: unknown function sent to EvaluateFunction %i\n\n", InputFunction); exit(1); /* DUMMY RETURN TO PREVENT COMPILER WARNING */ return 0.0; } }static void SkipWhiteSpace (char **f) { while (**f==' ' || **f==9 || **f==10 || **f==13) (*f)++; }int GetNextTokenLength ( char *cptr ) { int TokenLength; /* FIRST CHARACTER MUST BE LETTER */ if ( ! ( ( *cptr >= 'A' && *cptr <= 'Z' ) || ( *cptr >= 'a' && *cptr <= 'z' ) ) ) return 0; /* REMAINING CHARACTERS CAN BE LETTERS, NUMBERS OR UNDERSCORES */ TokenLength = 1; cptr++; while ( isalnum(*cptr) || *cptr=='_' ) { cptr++; TokenLength++; } return TokenLength; }void CopyUppercaseString ( char *TargetString, char *SourceString, int Size ) { int ichar; for (ichar=0;ichar<Size;ichar++) TargetString[ichar] = toupper(SourceString[ichar]); /* ADD STRING TERMINATOR */ TargetString[Size] = 0; }double ParseFormula (operator_t *PendingOperator) { operator_t CurrentOperator; function_t CurrentFunction; double CurrentValue; BOOLEAN MinusSignPresent; BOOLEAN ApplyOperator; int VariableID; int TokenLength; /* PARSE VALUE */ /* Values can take one of 5 forms - Parenthetical Expression - Numeric Constant - Function - Variable - Special Constant (ie e or pi ) */ /* INITIALIZE VARIABLE ID TO NONE */ VariableID = NOTFOUND; /* REMOVE OPENING WHITE SPACE */ SkipWhiteSpace (&FormulaString_m); /* CHECK FOR MINUS SIGN */ MinusSignPresent = FALSE; if (*FormulaString_m=='-') { MinusSignPresent = TRUE; FormulaString_m++; } /* .. OR PLUS SIGN */ else if (*FormulaString_m=='+') FormulaString_m++; /* GET VALUE -- PARENTHETICAL EXPRESSION .. */ if ( *FormulaString_m=='(' ) { FormulaString_m++; ParenthesisLevel_m++; CurrentOperator = OP_OpenParenthesis; /* OPERATOR SHOULD RETURN AS OP_CloseParenthesis ')' */ CurrentValue = ParseFormula (&CurrentOperator); if ( ErrorCode_m != ERROR_none ) return DEFAULT_RETURN; if (CurrentOperator!=OP_CloseParenthesis) { ErrorCode_m = ERROR_openparen; return DEFAULT_RETURN; } } /* .. GET VALUE -- CONSTANT */ else if ( (FormulaString_m[0] >= '0' && FormulaString_m[0] <= '9') || FormulaString_m[0]=='.' ) {#ifdef TEST char *TempString; TempString = _strhed (&FormulaString_m); CurrentValue = atof (TempString);#endif CurrentValue = strtod (FormulaString_m, &FormulaString_m); } /* .. GET VALUE -- NAME (EITHER FUNCTION, VARIABLE, SPECIAL CONSTANT) */ else { /* SCAN NAME TOKEN IN FORMULA */ TokenLength = GetNextTokenLength ( FormulaString_m );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -