📄 expression.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 + -