⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expression.c

📁 COP8 CPU的一个解释型BASIC源码
💻 C
字号:
////////////////////////////////////////////////////////////////
//
//                S C R I P T H E R M
//             A SCRIPTABLE THERMOMETER
// 
// entry of the National Semiconductor COP8FLASH Design Contest
//        submitted by Alberto Ricci Bitti (C) 2001
//              a.riccibitti@ra.nettuno.it
//
//--------------------------------------------------------------
//       FOR A BETTER VIEW SET TAB SIZE=4, INDENT SIZE=4
//--------------------------------------------------------------
// FILE   : expression.c
// PURPOSE: just call get_expression to evaluate a math expression
//          starting from current token_address
//			expressions can include constants and variables
//
////////////////////////////////////////////////////////////////

#include <stdlib.h>
#include "memory.h"
#include "language.h"
#include "tokenizer.h"
#include "variables.h"
#include "errors.h"
#include "expression.h"


/////////////////////////////////////////////////////////
// set up the expression evaluator  stack
/////////////////////////////////////////////////////////

struct STACK_ENTRY {
    int				value;		// "left side" of previous function 
    unsigned char	token;		//  previous function
};

typedef struct STACK_ENTRY STACK_ENTRY;


#define MAX_STACK 33
static  STACK_ENTRY				stack[MAX_STACK];
static  STACK_ENTRY		*		stack_top;
#define push_stack(tok, val)	((++stack_top)->token = (tok), stack_top->value = (val))
#define pop_stack()				(--stack_top)
#define stack_empty()			(stack_top < stack)

//token classification:
//non-math tokens that bound the expression
//unary tokens that accept only one argument
//binary tokens that require two arguments

#define is_math(tok)	 ((tok) >= START_EXP)

#define is_unary(tok)    (	(tok) == SUB			||	\
							(tok) == LOGIC_NOT		||	\
							(tok) == BITWISE_NOT	||	\
							(tok) == PAR_OPEN		||	\
							(tok) == START_EXP )

#define is_binary(tok)	 (	(	(tok) != LOGIC_NOT		&&	\
								(tok) != BITWISE_NOT	&&	\
								(tok) != START_EXP			\
							)   &&  is_math(tok) )




///////////////////////////////////////////////////////////////////////////////
//applies operation to arguments v1 and v2 (v1 is ignored for unary operators)
///////////////////////////////////////////////////////////////////////////////
int operation( unsigned char token, int v2, int v1)
{
	switch(token)
	{
	case ADD:			return v1 +  v2;
	case SUB:			return v1 -  v2;
	case MULT:			return v1 *  v2;
	case DIV:			return v1 /  v2;
	case MOD:			return v1 %  v2;
	case PAR_OPEN:		return v1;
	case NOT_EQUAL:		return v1 != v2;
	case EQUAL:			return v1 == v2;
	case END_EXP:		return 0;
	case LOGIC_NOT:		return    !  v2;	
	case GREATER:		return v1 >  v2;
	case LESS:			return v1 <  v2;
	case GREATER_EQUAL:	return v1 >= v2;
	case LESS_EQUAL:	return v1 <= v2;
	case LOGIC_AND:		return v1 && v2;
	case LOGIC_OR:		return v1 || v2;
	case BITWISE_NOT:	return    ~  v2;
	case BITWISE_AND:	return v1 &  v2;
	case BITWISE_OR:	return v1 |  v2;
	case BITWISE_XOR:	return v1 ^  v2;
	case SHIFT_LEFT:	return v1 << v2;
	case SHIFT_RIGHT:	return v1 >> v2;	
	};
	syntax_error(SYNTAX_ERROR);
	return(0);
}



void reset_expression_evaluator()
{
    stack_top = stack - 1; //crazy pointer - requires push()
}


////////////////////////////////////////////////////////////////////////////////////
// evaluates an ASCII constant
////////////////////////////////////////////////////////////////////////////////////
int get_number( ram_pointer_t address)
{	unsigned char buf;
	int retval = 0;

	while( is_digit(buf = peek_flash(address++)) ) 
	{
		retval = retval * 10 + (buf - '0');
	};
	return	retval;
}


/////////////////////////////////////////////////////////////////////////////////////
// main evaluation 
/////////////////////////////////////////////////////////////////////////////////////
int get_expression(void)				
{
	//declared as static to save stack space
	static int value;		
	static unsigned char stack_token;
	static unsigned char depth;
	
	depth = 0;				//counts parenthesis
    value = 0; 				//currnet operand/result
	token = PAR_OPEN;		//current token (push an open parenthesis to force evaluation at end)

    do
	{
		while(1)
		{
			push_stack(token, value);
			get_token();
			if (token == NUMBER)
			{	
				value = get_number(token_address); 
				break;
			}
			else if (token == VARIABLE_NAME)
			{	
				value = get_variable(token_address); 
				break;
			} 
			else if (token == PAR_OPEN)
			{	
				depth++;
			} 
			else
			{	value = 0;
				//not a math token, force end expression
				if ( ! is_unary(token))  
				{
					token = END_EXP;
					goto flush_stack;
				};
			};
		}; 

get_operation:
		get_token();

		if (! is_math(token)) token = END_EXP;
		else 	ensure( is_binary(token), SYNTAX_ERROR ); 	    
		
		if (token == PAR_CLOSE)
			if (depth-- == 0) token = END_EXP;

flush_stack:
		while ( ! stack_empty() )
		{
			stack_token = stack_top->token;			

			if (stack_token == PAR_OPEN)
			{
				if (token == PAR_CLOSE)
				{
					depth--;
					pop_stack();
					goto get_operation;
				};
				break;
			};

			if(stack_token <= token) break;  /* Lower precedence; need to wait to evaluate */
			
			// stack takes precedence: evaluate
			value = operation(stack_token, value, stack_top->value);
			pop_stack();
		}
		//value now has result of sub-expression
		//func now has right side  function */
	} while (token != END_EXP);
	pop_stack();
	unget_token();	 // push back closing token
    return value;    // when we break loop, 'value' has the final value
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -