📄 bwb_ops.c
字号:
/**************************************************************** bwb_ops.c Expression Parsing Operations for Bywater BASIC Interpreter Copyright (c) 1993, Ted A. Campbell Bywater Software email: tcamp@delphi.com Copyright and Permissions Information: All U.S. and international rights are claimed by the author, Ted A. Campbell. This software is released under the terms of the GNU General Public License (GPL), which is distributed with this software in the file "COPYING". The GPL specifies the terms under which users may copy and use the software in this distribution. A separate license is available for commercial distribution, for information on which you should contact the author.****************************************************************//*---------------------------------------------------------------*//* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, *//* 11/1995 (eidetics@cerf.net). *//*---------------------------------------------------------------*/#include <stdio.h>#include <ctype.h>#include <math.h>#include "bwbasic.h"#include "bwb_mes.h"/* declarations for functions visible in this file only */#if ANSI_Cstatic int op_oplevel( int level );static int op_add( int level, int precision );static int op_subtract( int level, int precision );static int op_multiply( int level, int precision );static int op_divide( int level, int precision );static int op_assign( int level, int precision );static int op_equals( int level, int precision );static int op_lessthan( int level, int precision );static int op_greaterthan( int level, int precision );static int op_lteq( int level, int precision );static int op_gteq( int level, int precision );static int op_notequal( int level, int precision );static int op_modulus( int level, int precision );static int op_exponent( int level, int precision );static int op_intdiv( int level, int precision );static int op_or( int level, int precision );static int op_and( int level, int precision );static int op_not( int level, int precision );static int op_xor( int level, int precision );static int op_negation( int level, int precision ); /* JBV */static int op_islevelstr( int level );static int op_getprecision( int level );static int op_isoperator( int operation );static int op_pulldown( int how_far );#elsestatic int op_oplevel();static int op_add();static int op_subtract();static int op_multiply();static int op_divide();static int op_assign();static int op_equals();static int op_lessthan();static int op_greaterthan();static int op_lteq();static int op_gteq();static int op_notequal();static int op_modulus();static int op_exponent();static int op_intdiv();static int op_or();static int op_and();static int op_not();static int op_xor();static int op_negation(); /* JBV */static int op_islevelstr();static int op_getprecision();static int op_isoperator();static int op_pulldown();#endif /* ANSI_C for prototypes */static int op_level;/*************************************************************** FUNCTION: exp_operation() DESCRIPTION: This function performs whatever operations are necessary at the end of function bwb_exp() (i.e., the end of the parsing of an expression; see file bwb_exp.c).***************************************************************/#if ANSI_Cintexp_operation( int entry_level )#elseintexp_operation( entry_level ) int entry_level;#endif { register int precedence; int operator;#if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in exp_operation(): entered function." ); bwb_debug( bwb_ebuf );#endif /* cycle through all levels of precedence and perform required operations */ for ( precedence = 0; precedence <= MAX_PRECEDENCE; ++precedence ) { /* Operation loop: cycle through every level above entry level and perform required operations as needed */ op_level = entry_level + 1; while( ( op_level < CURTASK expsc ) && ( op_isoperator( CURTASK exps[ op_level ].operation ) == FALSE )) { ++op_level; } while ( ( op_level > entry_level ) && ( op_level < CURTASK expsc ) ) { /* see if the operation at this level is an operator with the appropriate precedence level by running through the table of operators */ for ( operator = 0; operator < N_OPERATORS; ++operator ) { if ( exp_ops[ operator ].operation == CURTASK exps[ op_level ].operation ) { /* check for appropriate level of precedence */ if ( exp_ops[ operator ].precedence == precedence ) {#if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in exp_operation(): level <%d> operation <%d>", op_level, CURTASK exps[ op_level ].operation ); bwb_debug( bwb_ebuf );#endif op_oplevel( op_level ); /* perform the operation */ } } } /* advance level if appropriate; one must check, however, since the op_oplevel() function may have decremented CURTASK expsc */ if ( op_level < CURTASK expsc ) { ++op_level;#if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in exp_operation() first increment op_level to <%d>", op_level ); bwb_debug( bwb_ebuf );#endif while ( ( op_isoperator( CURTASK exps [ op_level ].operation ) == FALSE ) && ( op_level < CURTASK expsc ) ) { ++op_level;#if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in exp_operation() further increment op_level to <%d>", op_level ); bwb_debug( bwb_ebuf );#endif } } /* end of increment of op_level */ } /* end of for loop for stack levels */ } /* end of for loop for precedence levels */ return TRUE; } /* end of function exp_operation() *//*************************************************************** FUNCTION: op_oplevel() DESCRIPTION: This function performs a specific operation at a specific level as the expression parser resolves its arguments.***************************************************************/#if ANSI_Cstatic intop_oplevel( int level )#elsestatic intop_oplevel( level ) int level;#endif { int precision; /* set the precision */ if ( ( precision = op_getprecision( level ) ) == OP_ERROR ) {#if PROG_ERRORS sprintf( bwb_ebuf, "exp_operation(): failed to set precision." ); bwb_error( bwb_ebuf );#else bwb_error( err_mismatch ); /*** ??? ***/#endif op_pulldown( 2 ); } /* precision is set correctly */ else {#if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in op_oplevel(): level <%d>, precision <%c>", level, precision ); bwb_debug( bwb_ebuf );#endif switch ( CURTASK exps[ level ].operation ) { case OP_ADD: op_add( level, precision ); break; case OP_SUBTRACT: op_subtract( level, precision ); break; case OP_MULTIPLY: op_multiply( level, precision ); break; case OP_DIVIDE: op_divide( level, precision ); break; case OP_ASSIGN: op_assign( level, precision ); break; case OP_EQUALS: op_equals( level, precision ); break; case OP_LESSTHAN: op_lessthan( level, precision ); break; case OP_GREATERTHAN: op_greaterthan( level, precision ); break; case OP_LTEQ: op_lteq( level, precision ); break; case OP_GTEQ: op_gteq( level, precision ); break; case OP_NOTEQUAL: op_notequal( level, precision ); break; case OP_MODULUS: op_modulus( level, precision ); break; case OP_INTDIVISION: op_intdiv( level, precision ); break; case OP_OR: op_or( level, precision ); break; case OP_AND: op_and( level, precision ); break; case OP_NOT: op_not( level, precision ); break; case OP_XOR: op_xor( level, precision ); break; case OP_EXPONENT: op_exponent( level, precision ); break; case OP_NEGATION: /* JBV */ op_negation( level, precision ); break; default:#if PROG_ERRORS sprintf( bwb_ebuf, "PROGRAMMING ERROR: operator <%d> not (yet) supported.", CURTASK exps[ level ].operation ); op_pulldown( 2 ); bwb_error( bwb_ebuf );#else bwb_error( err_syntax );#endif break; } /* end of case statement for operators */ } /* end of else statement, precision set */ return TRUE; } /* end of function op_oplevel() *//*************************************************************** FUNCTION: op_isoperator() DESCRIPTION: This function detects whether its argument is an operator.***************************************************************/#if ANSI_Cstatic intop_isoperator( int operation )#elsestatic intop_isoperator( operation ) int operation;#endif { register int c; for( c = 0; c < N_OPERATORS; ++c ) { if ( operation == exp_ops[ c ].operation ) {#if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in op_isoperator(): found match <%s>", exp_ops[ c ].symbol ); bwb_debug( bwb_ebuf );#endif return TRUE; } } /* test failed; return FALSE */#if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in op_isoperator(): no match found for operation <%d>", operation ); bwb_debug( bwb_ebuf );#endif return FALSE; }/*************************************************************** FUNCTION: op_add() DESCRIPTION: This function adds two numbers or concatenates two strings.***************************************************************/#if ANSI_Cstatic intop_add( int level, int precision )#elsestatic intop_add( level, precision ) int level; int precision;#endif { int error_condition; static bstring b; /* JBV */ error_condition = FALSE; b.rab = FALSE; /* JBV */ switch( precision ) { case STRING: /* both sides of the operation should be strings for string addition; if not, report an error */ if ( ( op_islevelstr( level - 1 ) != TRUE ) || ( op_islevelstr( level + 1 ) != TRUE ) ) {#if PROG_ERRORS sprintf( bwb_ebuf, "in op_add(): Type mismatch in string addition." ); bwb_error( bwb_ebuf );#else bwb_error( err_mismatch );#endif error_condition = TRUE; } /* concatenate the two strings */ if ( error_condition == FALSE ) {#if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in op_add(): try exp_getsval(), level <%d> op <%d> type <%c>:", level - 1, CURTASK exps[ level - 1 ].operation, CURTASK exps[ level - 1 ].type ); bwb_debug( bwb_ebuf ); exp_getsval( &( CURTASK exps[ level - 1 ] )); sprintf( bwb_ebuf, "in op_add(): try exp_getsval(), level <%d> op <%d> type <%c>:", level + 1, CURTASK exps[ level + 1 ].operation, CURTASK exps[ level + 1 ].type ); bwb_debug( bwb_ebuf ); exp_getsval( &( CURTASK exps[ level + 1 ] )); sprintf( bwb_ebuf, "in op_add(): string addition, exp_getsval()s completed" ); bwb_debug( bwb_ebuf );#endif /* Removed by JBV (incomplete, modifies wrong string variable!) */ /* str_cat( exp_getsval( &( CURTASK exps[ level - 1 ] ) ), exp_getsval( &( CURTASK exps[ level + 1 ] ) ) ); */ /* Added by JBV */ str_btob( &b, exp_getsval( &( CURTASK exps[ level - 1 ] ) ) ); str_cat( &b, exp_getsval( &( CURTASK exps[ level + 1 ] ) ) ); str_btob( &( CURTASK exps[ level - 1 ].sval ), &b ); CURTASK exps[ level - 1 ].operation = CONST_STRING;#if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in op_add(): str_cat() returns <%d>-byte string to level <%d>", exp_getsval( &( CURTASK exps[ level - 1 ] ) )->length, level - 1 ); bwb_debug( bwb_ebuf );#endif } break; case NUMBER: CURTASK exps[ level - 1 ].nval = exp_getnval( &( CURTASK exps[ level - 1 ] )) + exp_getnval( &( CURTASK exps[ level + 1 ] )); CURTASK exps[ level - 1 ].operation = NUMBER; break; } /* set variable to requested precision */ CURTASK exps[ level - 1 ].type = (char) precision;#if INTENSIVE_DEBUG sprintf( bwb_ebuf, "in op_add() returns with operation <%d> type <%c>", CURTASK exps[ level - 1 ].operation, CURTASK exps[ level - 1 ].type ); bwb_debug( bwb_ebuf );#endif /* decrement the stack twice */ op_pulldown( 2 ); return TRUE; }/*************************************************************** FUNCTION: op_subtract() DESCRIPTION: This function subtracts the number on the left from the number on the right.***************************************************************/#if ANSI_Cstatic intop_subtract( int level, int precision )#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -