📄 script.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 : script.c
// PURPOSE: the interpreter body, contains the routines
// implementing the statements.
// Call the tokenizer to get a token, the executes it.
// Implements the control stack for flow control
// statements (IF-THEN-ELSE-ENDIF, WHILE-WEND)
//
////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include "types.h"
#include "ascii.h"
#include "memory.h"
#include "serial.h"
#include "lcd.h" //per cls
#include "errors.h"
#include "variables.h"
#include "language.h"
#include "tokenizer.h"
#include "expression.h"
#include "script.h"
#include "variables.h"
#include "main.h"
////////////////////////////////////////////////////////////////
// control stack
////////////////////////////////////////////////////////////////
ram_pointer_t prog = 0;
#define STACK_SIZE 10
ram_pointer_t control_stack[STACK_SIZE];
unsigned char tos = 0;
//pushes an address (usually the program counter) on the control stack
void push(ram_pointer_t pc)
{
if (tos < STACK_SIZE)
{
control_stack[tos++] = pc;
}
else
syntax_error(NESTING_TOO_DEEP);
}
ram_pointer_t pop(void)
{
if (tos == 0)
syntax_error(NESTING_UNBALANCED);
return control_stack[--tos];
}
// skips a block of code, matching the give token
// e.g. WHILE skips to WEND, etc.
static void skip_block(unsigned char start_token)
{
while(TRUE)
{
switch( get_token() )
{
case IF:
case WHILE:
case FUNCTION:
skip_block( token );
break;
case END_WHILE:
ensure( start_token == WHILE, NESTING_UNBALANCED);
return;
case END_FUNCTION:
ensure( start_token == FUNCTION, NESTING_UNBALANCED);
return;
case END_IF:
ensure( start_token == IF || start_token == ELSE, NESTING_UNBALANCED);
return;
case END_FILE:
syntax_error(NESTING_UNBALANCED);
/*break intentionally removed*/
case END_PROGRAM:
return;
case ELSE:
if ( start_token == ELSE ) return;
break;
};
};
}
////////////////////////////////////////////////////////////////
// language statement routines
////////////////////////////////////////////////////////////////
//prints a number, called by PRINT
static void prettyprint(int n, void (*put_char)(unsigned char))
{
unsigned char buf[5];
signed char i;
if (n < 0) { n = -n; put_char('-');}
else { put_char(' '); };
for (i=0; i<5; )
{
buf[i++] = '0'+ n % 10;
n = n / 10;
};
do { i--; } while ( (buf[i] == '0') && (i != 0) );
do { put_char( buf[i--] ); } while (i >= 0);
}
////////////////////////////////////////////////////////////////
//PRINT
////////////////////////////////////////////////////////////////
void print(void)
{
void (*put_char)(unsigned char) = LCD_putchar;
do
{
get_token();
switch(token)
{
case AT:
{ unsigned char r, c;
r = get_expression();
ensure(get_token() == COMMA , SYNTAX_ERROR); //expected:comma
c = get_expression();
LCD_locate(r,c);
};
break;
case CR:
put_char(END_OF_LINE);
break;
case COM:
put_char = com_putchar;
break;
case QUOTE:
while( peek_flash(++token_address) != APEX )
put_char( peek_flash(token_address) );
break;
default:
unget_token();
prettyprint( get_expression(), put_char );
break;
};
} while(get_token() == COMMA);
unget_token();
}
////////////////////////////////////////////////////////////////
//GET
////////////////////////////////////////////////////////////////
void get_serial(void)
{
ensure(get_token() == VARIABLE_NAME , SYNTAX_ERROR); //expected:variable
set_variable( token_address, ( com_pending() ? com_getchar() : -1 ) );
}
////////////////////////////////////////////////////////////////
//BOX
////////////////////////////////////////////////////////////////
void box(void)
{
unsigned char x1,x2,y1,y2;
unsigned char color = 1;
unsigned char d;
x1 = get_expression() & 0x7F;
ensure(get_token() == COMMA , SYNTAX_ERROR); //expected:comma
y1 = get_expression() & 0x3F;
ensure(get_token() == COMMA , SYNTAX_ERROR); //expected:comma
x2 = get_expression() & 0x7F;
ensure(get_token() == COMMA , SYNTAX_ERROR); //expected:comma
y2 = get_expression() & 0x3F;
if (get_token() == COMMA)
color = get_expression();
else
unget_token();
if (x1 > x2) { d = x2; x2 = x1; x1 = d; };
if (y1 > y2) { d = y2; y2 = y1; y1 = d; };
for( ; y1 <= y2; y1++)
for ( d=x1; d <= x2; d++)
LCD_pset(d, y1, color);
}
////////////////////////////////////////////////////////////////
// IF-THEN-ELSE-ENDIF
////////////////////////////////////////////////////////////////
void do_if(void)
{
int condition;
condition = get_expression();
ensure (get_token() == THEN, EXPECTED_THEN);
if(!condition)
{
skip_block(ELSE); //endif will do as well
};
}
// ELSE
void do_else(void)
{
skip_block(IF);
}
////////////////////////////////////////////////////////////////
// WHILE-WEND
////////////////////////////////////////////////////////////////
void do_while(void)
{
push( token_address );
if(!get_expression())
{
pop();
skip_block(WHILE);
}
}
// WEND
void end_while(void)
{
prog = pop();
}
////////////////////////////////////////////////////////////////
// VAR
////////////////////////////////////////////////////////////////
void variable(void)
{
do
{
if( get_token() != VARIABLE_NAME ) syntax_error(EXPECTED_NAME);
push_variable(token_address, 0);
} while( get_token() == COMMA);
unget_token();
}
////////////////////////////////////////////////////////////////
// FUNCTION
////////////////////////////////////////////////////////////////
void function(void)
{
ram_pointer_t function_name;
unsigned char count=0;
function_name = token_address;
push_variable(RETURN_VALUE, 0); //marks the frame and holds return value
get_token(); //skip ( or ()
do
{
if ( token == PAR_CLOSE || token == PAR_VOID) break;
push_variable( ANONIMUS, get_expression() ); //push parameters as anonimus variables
count++;
} while (get_token() == COMMA);
push(prog); //push return address
prog = (ram_pointer_t) get_variable( function_name );
//jump to function body
get_token(); //skip (
do
{ //scan argument list
if ( token == PAR_CLOSE || token == PAR_VOID) break;
ensure(get_token() == VARIABLE_NAME, EXPECTED_NAME);
name_parameter( token_address ); //rename anonymus parameters with argument names
count--;
} while (get_token() == COMMA);
ensure( count == 0, SYNTAX_ERROR); //argument number mismatch
}
////////////////////////////////////////////////////////////////
// FUNCTION CALL - FEND
////////////////////////////////////////////////////////////////
void function_immediate(void)
{
push(NULL_NAME); //push NULL variable as return value recipient
function();
}
////////////////////////////////////////////////////////////////
// FEND
////////////////////////////////////////////////////////////////
void end_function(void)
{
prog = pop(); //continue from where we left
set_variable(pop(), pop_frame());
}
////////////////////////////////////////////////////////////////
// ASSIGNMENT (=)
////////////////////////////////////////////////////////////////
void assignment(void)
{
push( token_address ); //store name
ensure( get_token() == ASSIGN, SYNTAX_ERROR); //expected "="
if (get_token() == FUNCTION_NAME)
//leave the variable name on top of stack, to be used by end_function
function();
else
{
unget_token();
set_variable( pop(), get_expression() );
};
}
// utilities
void end_program(void)
{
//an embedded program never ends really
flags.running = FALSE;
//restart editing from the beginning
token_address = 0;
}
void do_nothing(void)
{}
////////////////////////////////////////////////////////////////
//prepare the environment for program execution
////////////////////////////////////////////////////////////////
void prepare_to_run(void)
{
flags.running = TRUE;
tos = 0;
reset_expression_evaluator();
clear_variables();
register_functions();
token_address = prog = PROGRAM_START;
}
////////////////////////////////////////////////////////////////
// the real interpreter: gets a token and jump to the routine
// that implements it
////////////////////////////////////////////////////////////////
void exec_command(void)
{
ensure(get_token() < MAX_RUNNABLE, SYNTAX_ERROR);
jump_table[ token & 0x7F ]();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -