📄 ceval.c
字号:
/** expressions (byte-code)** Nicholas Christopoulos** This program is distributed under the terms of the GPL v2.0 or later* Download the GNU Public License (GPL) from www.gnu.org*/#include "sys.h"#include "str.h"#include "kw.h"#include "panic.h"#include "bc.h"extern void sc_raise(const char *fmt, ...) SEC(BCSCAN);extern int scan_line;extern int scan_error;#define IP bc_in->cp#define CODE(x) bc_in->ptr[(x)]#define CODE_PEEK() CODE(IP)#define CHECKOP1(s) if (CODE(IP) == kwTYPE_OPR && CODE(IP+1) == (s)) { IP += 2; return (s); }#define CHECKOP2(s,o) if (CODE(IP) == kwTYPE_OPR && CODE(IP+1) == (s)[0] && CODE(IP+2) == kwTYPE_OPR && CODE(IP+3) == (s)[1]) { IP += 4; return (o); }void cev_udp(void) SEC(TRASH);void cev_udp(void) { sc_raise("(EXPR): UDP INSIDE EXPR"); }#if defined(_PalmOS)void cev_missing_rp(void) SEC(TRASH);void cev_missing_rp(void) { sc_raise("(EXPR): MISSING ')'"); }void cev_opr_err(void) SEC(TRASH);void cev_opr_err(void) { sc_raise("(EXPR): SYNTAX ERROR (1st OP)"); }#else#define cev_missing_rp() printf("C %s:%d, BAS: %d, EXPR: MISSING ')' (CS:IP=%d)", __FILE__, __LINE__, scan_line, CODE_PEEK() | scan_error++)#define cev_opr_err() printf("C %s:%d, BAS: %d, EXPR: SYNTAX ERROR (1st OP) (CS:IP=%d)", __FILE__, __LINE__, scan_line, CODE_PEEK() | scan_error++)#endifvoid cev_log(void) SEC(BCSCAN);static bc_t *bc_in;static bc_t *bc_out;#define cev_add1(x) bc_add1(bc_out, (x))#define cev_add2(x, y) bc_add2c(bc_out, (x), (y))/** prim*/void cev_prim(void) SEC(BCSCAN);void cev_prim(){ byte code; word len; if ( scan_error ) return; code = CODE(IP); IP ++; cev_add1(code); switch ( code ) { case kwTYPE_INT: bc_add_n(bc_out, bc_in->ptr+bc_in->cp, 4); IP += 4; break; case kwTYPE_NUM: bc_add_n(bc_out, bc_in->ptr+bc_in->cp, 8); IP += 8; break; case kwTYPE_STR: memcpy(&len, bc_in->ptr+bc_in->cp, 2); IP += 2; bc_add1i(bc_out, len); bc_add_n(bc_out, bc_in->ptr+bc_in->cp, len); IP += len; break; case kwTYPE_CALL_UDP: cev_udp(); break; case kwTYPE_CALL_UDF: bc_add_n(bc_out, bc_in->ptr+bc_in->cp, 2); IP += 2; // no 'break' here case kwTYPE_VAR: bc_add_n(bc_out, bc_in->ptr+bc_in->cp, 2); IP += 2; if ( CODE_PEEK() == kwTYPE_LEVEL_BEGIN ) { cev_add1(kwTYPE_LEVEL_BEGIN); IP ++; if ( CODE_PEEK() == kwTYPE_LEVEL_END ) { // NULL ARRAYS cev_add1(kwTYPE_LEVEL_END); IP ++; } else { cev_log(); while ( CODE_PEEK() == kwTYPE_SEP || CODE_PEEK() == kwTO ) { // DIM X(A TO B) if ( CODE_PEEK() == kwTYPE_SEP ) { cev_add1(CODE(IP)); IP ++; } cev_add1(CODE(IP)); IP ++; cev_log(); } if ( CODE_PEEK() != kwTYPE_LEVEL_END ) cev_missing_rp(); else { cev_add1(kwTYPE_LEVEL_END); IP ++; } } } break; default: // function [(...)] if ( CODE_PEEK() == kwTYPE_LEVEL_BEGIN ) { cev_add1(kwTYPE_LEVEL_BEGIN); IP ++; cev_log(); while ( CODE_PEEK() == kwTYPE_SEP ) { cev_add1(CODE(IP)); IP ++; cev_add1(CODE(IP)); IP ++; cev_log(); } if ( CODE_PEEK() != kwTYPE_LEVEL_END ) cev_missing_rp(); else { cev_add1(kwTYPE_LEVEL_END); IP ++; } } };}/** parenthesis*/void cev_parenth(void) SEC(BCSCAN);void cev_parenth(){ if ( scan_error ) return; if ( CODE_PEEK() == kwTYPE_LEVEL_BEGIN ) { cev_add1(kwTYPE_LEVEL_BEGIN); IP ++; cev_log(); // R = cev_log if ( scan_error ) return; if ( CODE_PEEK() != kwTYPE_LEVEL_END ) { cev_missing_rp(); return; } else { cev_add1(kwTYPE_LEVEL_END); IP ++; } } else cev_prim();}/** unary*/void cev_unary(void) SEC(BCSCAN);void cev_unary(){ char op; if ( scan_error ) return; if ( CODE(IP) == kwTYPE_UNROPR || CODE(IP) == kwTYPE_ADDOPR ) { op = CODE(IP+1); IP += 2; } else op = 0; cev_parenth(); // R = cev_parenth if ( op ) cev_add2(kwTYPE_UNROPR, op); // R = op R}/** pow*/void cev_pow(void) SEC(BCSCAN);void cev_pow(){ cev_unary(); // R = cev_unary if ( scan_error ) return; while ( CODE(IP) == kwTYPE_POWOPR ) { IP += 2; cev_add1(kwTYPE_EVPUSH); // PUSH R cev_unary(); // R = cev_unary if ( scan_error ) return; cev_add1(kwTYPE_EVPOP); // POP LEFT cev_add2(kwTYPE_POWOPR, '^'); // R = LEFT op R }}/** mul | div | mod*/void cev_mul(void) SEC(BCSCAN);void cev_mul(){ cev_pow(); // R = cev_pow() if ( scan_error ) return; while ( CODE(IP) == kwTYPE_MULOPR ) { char op; op = CODE(++IP); IP ++; cev_add1(kwTYPE_EVPUSH); // PUSH R cev_pow(); if ( scan_error ) return; cev_add1(kwTYPE_EVPOP); // POP LEFT cev_add2(kwTYPE_MULOPR, op); // R = LEFT op R }}/** add | sub*/void cev_add(void) SEC(BCSCAN);void cev_add(){ cev_mul(); // R = cev_mul() if ( scan_error ) return; while ( CODE(IP) == kwTYPE_ADDOPR ) { char op; IP ++; op = CODE(IP); IP ++; cev_add1(kwTYPE_EVPUSH); // PUSH R cev_mul(); // R = cev_mul if ( scan_error ) return; cev_add1(kwTYPE_EVPOP); // POP LEFT cev_add2(kwTYPE_ADDOPR, op); // R = LEFT op R }}/** compare*/void cev_cmp(void) SEC(BCSCAN);void cev_cmp(){ cev_add(); // R = cev_add() if ( scan_error ) return; while ( CODE(IP) == kwTYPE_CMPOPR ) { char op; IP ++; op = CODE(IP); IP ++; cev_add1(kwTYPE_EVPUSH); // PUSH R cev_add(); // R = cev_add() if ( scan_error ) return; cev_add1(kwTYPE_EVPOP); // POP LEFT cev_add2(kwTYPE_CMPOPR, op); // R = LEFT op R }}/** logical*/void cev_log(void){ cev_cmp(); // R = cev_cmp() if ( scan_error ) return; while ( CODE(IP) == kwTYPE_LOGOPR ) { char op; IP ++; op = CODE(IP); IP ++; cev_add1(kwTYPE_EVPUSH); // PUSH R cev_cmp(); // right seg // R = cev_cmp() if ( scan_error ) return; cev_add1(kwTYPE_EVPOP); // POP LEFT cev_add2(kwTYPE_LOGOPR, op); // R = LEFT op R }}/** main*/void expr_parser(bc_t *bc_src) SEC(BCSCAN);void expr_parser(bc_t *bc_src){ byte code; // init bc_in = bc_src; bc_out = tmp_alloc(sizeof(bc_t)); bc_create(bc_out); code = CODE_PEEK(); // NIL! if ( code == kwTYPE_LINE || code == kwTYPE_EOC ) { // || code == kwFILLED || code == kwON || code == kwOFF ) { bc_destroy(bc_out); tmp_free(bc_out); return; } // LET|CONST SPECIAL CODE if ( code == kwTYPE_CMPOPR ) { IP ++; if ( CODE(IP) != '=' ) { cev_opr_err(); bc_destroy(bc_out); tmp_free(bc_out); return; } else { IP ++; cev_add2(kwTYPE_CMPOPR, '='); } } // sep. code = CODE_PEEK(); while ( code == kwTYPE_SEP ) { cev_add1(CODE(IP)); IP ++; cev_add1(CODE(IP)); IP ++; code = CODE_PEEK(); } // start cev_log(); code = CODE_PEEK(); while ( code == kwTYPE_SEP || code == kwFILLED || code == kwCOLOR || code == kwTO || code == kwSTEP || code == kwFORSEP || code == kwINPUTSEP || code == kwINPUT || code == kwOUTPUT || code == kwAPPEND || code == kwAS ) { if ( scan_error ) break; if ( code == kwAS ) { cev_add1(kwAS); IP ++; if ( CODE_PEEK() == kwTYPE_SEP ) { cev_add1(kwTYPE_SEP); IP ++; cev_add1(CODE(IP)); IP ++; } } else { cev_add1(CODE(IP)); IP ++; if ( code == kwTYPE_SEP ) { cev_add1(CODE(IP)); IP ++; } } code = CODE_PEEK(); if ( code == kwTYPE_EOC || code == kwTYPE_LINE ) break; cev_log(); code = CODE_PEEK(); } // finish if ( bc_out->count ) { bc_in->count = 0; bc_append(bc_in, bc_out); } bc_destroy(bc_out); tmp_free(bc_out);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -