+added sub routine type insurance; *prompted more friendly dummy function message; *polished code and document
This commit is contained in:
parent
1c1771280c
commit
789cc76eb3
5
HISTORY
5
HISTORY
@ -1,3 +1,8 @@
|
|||||||
|
Sep. 2 2015
|
||||||
|
Added sub routine type insurance
|
||||||
|
Prompted more friendly dummy function message
|
||||||
|
Polished code and document
|
||||||
|
|
||||||
Sep. 1 2015
|
Sep. 1 2015
|
||||||
Added support for user customized routine by DEF/ENDDEF
|
Added support for user customized routine by DEF/ENDDEF
|
||||||
|
|
||||||
|
Binary file not shown.
17
README.md
17
README.md
@ -4,28 +4,31 @@ Copyright (C) 2011 - 2015 [Wang Renxin](https://twitter.com/wangrenxin)
|
|||||||
|
|
||||||
[LinkedIn](https://cn.linkedin.com/pub/wang-renxin/43/494/20)
|
[LinkedIn](https://cn.linkedin.com/pub/wang-renxin/43/494/20)
|
||||||
|
|
||||||
|
Why are existing script interpreters so complex? Why is it so difficult to integrate with them? Why not try MY-BASIC today!
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
MY-BASIC is a tiny cross-platform easy extendable BASIC interpreter written in pure C with about 7000 lines of source code. Its grammar is similar to structured BASIC in early era, but without line number. It is aimed to be either an embeddable scripting language or a standalone interpreter. The core is pretty light; all in a C source file and an associated header file. You can combine MY-BASIC with an existing C, C++, Objective-C, etc. project easily, scripting driven can make your projects more powerful, elegant and neat.
|
MY-BASIC is a tiny cross-platform easy extendable BASIC interpreter written in pure C with about 7000 lines of source code. Its grammar is similar to structured BASIC. It is aimed to be either an embeddable scripting language or a standalone interpreter. The core is pretty light; all in a C source file and an associated header file. You can combine MY-BASIC with an existing C, C++, Objective-C, etc. project easily, scripting driven can make your projects more powerful, elegant and neat.
|
||||||
|
|
||||||
## Main features
|
## Main features
|
||||||
|
|
||||||
* It is free
|
* It is free
|
||||||
* Written in clean ANSI C, source code portable
|
* Written in clean ANSI C, source code portable
|
||||||
* Most retro BASIC like syntax, without line numbers
|
* With most common BASIC syntax
|
||||||
* Small (within memory usage less than 128KB) and fast
|
* Small (within memory usage less than 128KB) and fast
|
||||||
* Case-insensitive tokenization
|
* Case-insensitive tokenization
|
||||||
* Integer, float point, string, boolean, user defined data types with array support
|
* Integer, float point, string, boolean, user defined data types with array support, etc.
|
||||||
* `IF-THEN-ELSEIF-ELSE-ENDIF` support
|
* Structured `IF-THEN-ELSEIF-ELSE-ENDIF` support
|
||||||
* `FOR-TO-STEP-NEXT/WHILE-WEND/DO-UNTIL` support
|
* Structured `FOR-TO-STEP-NEXT/WHILE-WEND/DO-UNTIL` support
|
||||||
|
* Structured user costomized sub routine definition by `DEF/ENDDEF` support
|
||||||
* `GOTO/GOSUB-RETURN` support
|
* `GOTO/GOSUB-RETURN` support
|
||||||
* Standard numeric functions
|
* Standard numeric functions
|
||||||
* Standard string functions
|
* Standard string functions
|
||||||
* Debug APIs
|
* Debug APIs
|
||||||
* High expansibility, easy to use APIs, easy to write customized scripting interfaces
|
* High expansibility, easy to use APIs, easy to write customized scripting interfaces
|
||||||
* It's able to use it as a standalone interpreter, or integrate it with existing C, C++, Objective-C, etc. projects
|
* It's able to use it as a standalone interpreter, or integrate it with existing C, C++, Objective-C, etc. projects
|
||||||
* It's able to learn how to build an interpreter from scratch from it
|
* It's able to learn how to build an interpreter from scratch from MY-BASIC
|
||||||
* It's able to build your own dialect based on it
|
* It's able to build your own dialect based on MY-BASIC
|
||||||
* More features/modules under developing
|
* More features/modules under developing
|
||||||
|
|
||||||
## [Interpreter workflow diagram](https://github.com/paladin-t/my_basic/wiki/Interpreter-workflow-diagram)
|
## [Interpreter workflow diagram](https://github.com/paladin-t/my_basic/wiki/Interpreter-workflow-diagram)
|
||||||
|
418
core/my_basic.c
418
core/my_basic.c
File diff suppressed because it is too large
Load Diff
@ -215,7 +215,9 @@ typedef enum mb_error_e {
|
|||||||
SE_RN_MOD_BY_ZERO,
|
SE_RN_MOD_BY_ZERO,
|
||||||
SE_RN_INVALID_EXPRESSION,
|
SE_RN_INVALID_EXPRESSION,
|
||||||
SE_RN_OUT_OF_MEMORY,
|
SE_RN_OUT_OF_MEMORY,
|
||||||
|
SE_RN_WRONG_FUNCTION_REACHED,
|
||||||
SE_RN_DONT_SUSPEND_IN_A_ROUTINE,
|
SE_RN_DONT_SUSPEND_IN_A_ROUTINE,
|
||||||
|
SE_RN_DONT_MIX_INSTRUCTIONAL_AND_STRUCTURED,
|
||||||
SE_RN_ROUTINE_EXPECTED,
|
SE_RN_ROUTINE_EXPECTED,
|
||||||
/** Extended abort */
|
/** Extended abort */
|
||||||
SE_EA_EXTENDED_ABORT,
|
SE_EA_EXTENDED_ABORT,
|
||||||
@ -249,7 +251,7 @@ typedef unsigned short mb_mem_tag_t;
|
|||||||
|
|
||||||
typedef int (* mb_func_t)(struct mb_interpreter_t*, void**);
|
typedef int (* mb_func_t)(struct mb_interpreter_t*, void**);
|
||||||
typedef void (* mb_debug_stepped_handler_t)(struct mb_interpreter_t*, int, unsigned short, unsigned short);
|
typedef void (* mb_debug_stepped_handler_t)(struct mb_interpreter_t*, int, unsigned short, unsigned short);
|
||||||
typedef void (* mb_error_handler_t)(struct mb_interpreter_t*, enum mb_error_e, char*, int, unsigned short, unsigned short, int);
|
typedef void (* mb_error_handler_t)(struct mb_interpreter_t*, enum mb_error_e, char*, char*, int, unsigned short, unsigned short, int);
|
||||||
typedef int (* mb_print_func_t)(const char*, ...);
|
typedef int (* mb_print_func_t)(const char*, ...);
|
||||||
typedef int (* mb_input_func_t)(char*, int);
|
typedef int (* mb_input_func_t)(char*, int);
|
||||||
typedef char* (* mb_memory_allocate_func_t)(unsigned s);
|
typedef char* (* mb_memory_allocate_func_t)(unsigned s);
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -36,8 +36,8 @@
|
|||||||
IDI_ICON_MAIN ICON "icon.ico"
|
IDI_ICON_MAIN ICON "icon.ico"
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,1,65,0
|
FILEVERSION 1,1,66,0
|
||||||
PRODUCTVERSION 1,1,65,0
|
PRODUCTVERSION 1,1,66,0
|
||||||
FILEFLAGSMASK 0x17L
|
FILEFLAGSMASK 0x17L
|
||||||
# ifdef _DEBUG
|
# ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
@ -55,13 +55,13 @@
|
|||||||
VALUE "Comments", "MY-BASIC"
|
VALUE "Comments", "MY-BASIC"
|
||||||
VALUE "CompanyName", "Wang Renxin"
|
VALUE "CompanyName", "Wang Renxin"
|
||||||
VALUE "FileDescription", "MY-BASIC Interpreter for Windows"
|
VALUE "FileDescription", "MY-BASIC Interpreter for Windows"
|
||||||
VALUE "FileVersion", "1, 1, 65, 0"
|
VALUE "FileVersion", "1, 1, 66, 0"
|
||||||
VALUE "InternalName", "my_basic"
|
VALUE "InternalName", "my_basic"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2011 - 2015 Wang Renxin"
|
VALUE "LegalCopyright", "Copyright (C) 2011 - 2015 Wang Renxin"
|
||||||
VALUE "LegalTrademarks", "MY-BASIC"
|
VALUE "LegalTrademarks", "MY-BASIC"
|
||||||
VALUE "OriginalFilename", "my_basic.exe"
|
VALUE "OriginalFilename", "my_basic.exe"
|
||||||
VALUE "ProductName", "MY-BASIC"
|
VALUE "ProductName", "MY-BASIC"
|
||||||
VALUE "ProductVersion", "1, 1, 65, 0"
|
VALUE "ProductVersion", "1, 1, 66, 0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
26
shell/main.c
26
shell/main.c
@ -43,6 +43,7 @@
|
|||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# pragma warning(disable : 4127)
|
# pragma warning(disable : 4127)
|
||||||
|
# pragma warning(disable : 4706)
|
||||||
# pragma warning(disable : 4996)
|
# pragma warning(disable : 4996)
|
||||||
#endif /* _MSC_VER */
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
@ -265,7 +266,9 @@ static _code_line_t* _create_code(void) {
|
|||||||
|
|
||||||
static void _destroy_code(_code_line_t* code) {
|
static void _destroy_code(_code_line_t* code) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
mb_assert(code);
|
mb_assert(code);
|
||||||
|
|
||||||
for(i = 0; i < code->count; ++i) {
|
for(i = 0; i < code->count; ++i) {
|
||||||
free(code->lines[i]);
|
free(code->lines[i]);
|
||||||
}
|
}
|
||||||
@ -275,7 +278,9 @@ static void _destroy_code(_code_line_t* code) {
|
|||||||
|
|
||||||
static void _clear_code(_code_line_t* code) {
|
static void _clear_code(_code_line_t* code) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
mb_assert(code);
|
mb_assert(code);
|
||||||
|
|
||||||
for(i = 0; i < code->count; ++i) {
|
for(i = 0; i < code->count; ++i) {
|
||||||
free(code->lines[i]);
|
free(code->lines[i]);
|
||||||
}
|
}
|
||||||
@ -285,7 +290,9 @@ static void _clear_code(_code_line_t* code) {
|
|||||||
static void _append_line(_code_line_t* code, char* txt) {
|
static void _append_line(_code_line_t* code, char* txt) {
|
||||||
int l = 0;
|
int l = 0;
|
||||||
char* buf = 0;
|
char* buf = 0;
|
||||||
|
|
||||||
mb_assert(code && txt);
|
mb_assert(code && txt);
|
||||||
|
|
||||||
if(code->count + 1 == code->size) {
|
if(code->count + 1 == code->size) {
|
||||||
code->size += _LINE_INC_STEP;
|
code->size += _LINE_INC_STEP;
|
||||||
code->lines = (char**)realloc(code->lines, sizeof(char*) * code->size);
|
code->lines = (char**)realloc(code->lines, sizeof(char*) * code->size);
|
||||||
@ -301,7 +308,9 @@ static void _append_line(_code_line_t* code, char* txt) {
|
|||||||
static char* _get_code(_code_line_t* code) {
|
static char* _get_code(_code_line_t* code) {
|
||||||
char* result = 0;
|
char* result = 0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
mb_assert(code);
|
mb_assert(code);
|
||||||
|
|
||||||
result = (char*)malloc((_MAX_LINE_LENGTH + 2) * code->count + 1);
|
result = (char*)malloc((_MAX_LINE_LENGTH + 2) * code->count + 1);
|
||||||
result[0] = '\0';
|
result[0] = '\0';
|
||||||
for(i = 0; i < code->count; ++i) {
|
for(i = 0; i < code->count; ++i) {
|
||||||
@ -316,7 +325,9 @@ static char* _get_code(_code_line_t* code) {
|
|||||||
static void _set_code(_code_line_t* code, char* txt) {
|
static void _set_code(_code_line_t* code, char* txt) {
|
||||||
char* cursor = 0;
|
char* cursor = 0;
|
||||||
char _c = '\0';
|
char _c = '\0';
|
||||||
|
|
||||||
mb_assert(code);
|
mb_assert(code);
|
||||||
|
|
||||||
if(!txt)
|
if(!txt)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -340,7 +351,9 @@ static char* _load_file(const char* path) {
|
|||||||
char* result = 0;
|
char* result = 0;
|
||||||
long curpos = 0;
|
long curpos = 0;
|
||||||
long l = 0;
|
long l = 0;
|
||||||
|
|
||||||
mb_assert(path);
|
mb_assert(path);
|
||||||
|
|
||||||
fp = fopen(path, "rb");
|
fp = fopen(path, "rb");
|
||||||
if(fp) {
|
if(fp) {
|
||||||
curpos = ftell(fp);
|
curpos = ftell(fp);
|
||||||
@ -359,7 +372,9 @@ static char* _load_file(const char* path) {
|
|||||||
|
|
||||||
static int _save_file(const char* path, const char* txt) {
|
static int _save_file(const char* path, const char* txt) {
|
||||||
FILE* fp = 0;
|
FILE* fp = 0;
|
||||||
|
|
||||||
mb_assert(path && txt);
|
mb_assert(path && txt);
|
||||||
|
|
||||||
fp = fopen(path, "wb");
|
fp = fopen(path, "wb");
|
||||||
if(fp) {
|
if(fp) {
|
||||||
fwrite(txt, sizeof(char), strlen(txt), fp);
|
fwrite(txt, sizeof(char), strlen(txt), fp);
|
||||||
@ -395,7 +410,9 @@ static int _new_program(void) {
|
|||||||
static void _list_program(const char* sn, const char* cn) {
|
static void _list_program(const char* sn, const char* cn) {
|
||||||
long lsn = 0;
|
long lsn = 0;
|
||||||
long lcn = 0;
|
long lcn = 0;
|
||||||
|
|
||||||
mb_assert(sn && cn);
|
mb_assert(sn && cn);
|
||||||
|
|
||||||
lsn = atoi(sn);
|
lsn = atoi(sn);
|
||||||
lcn = atoi(cn);
|
lcn = atoi(cn);
|
||||||
if(lsn == 0 && lcn == 0) {
|
if(lsn == 0 && lcn == 0) {
|
||||||
@ -430,7 +447,9 @@ static void _list_program(const char* sn, const char* cn) {
|
|||||||
static void _edit_program(const char* no) {
|
static void _edit_program(const char* no) {
|
||||||
char line[_MAX_LINE_LENGTH];
|
char line[_MAX_LINE_LENGTH];
|
||||||
long lno = 0;
|
long lno = 0;
|
||||||
|
|
||||||
mb_assert(no);
|
mb_assert(no);
|
||||||
|
|
||||||
lno = atoi(no);
|
lno = atoi(no);
|
||||||
if(lno < 1 || lno > c->count) {
|
if(lno < 1 || lno > c->count) {
|
||||||
printf("Line number %ld out of bound.\n", lno);
|
printf("Line number %ld out of bound.\n", lno);
|
||||||
@ -449,7 +468,9 @@ static void _insert_program(const char* no) {
|
|||||||
char line[_MAX_LINE_LENGTH];
|
char line[_MAX_LINE_LENGTH];
|
||||||
long lno = 0;
|
long lno = 0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
mb_assert(no);
|
mb_assert(no);
|
||||||
|
|
||||||
lno = atoi(no);
|
lno = atoi(no);
|
||||||
if(lno < 1 || lno > c->count) {
|
if(lno < 1 || lno > c->count) {
|
||||||
printf("Line number %ld out of bound.\n", lno);
|
printf("Line number %ld out of bound.\n", lno);
|
||||||
@ -474,7 +495,9 @@ static void _insert_program(const char* no) {
|
|||||||
static void _alter_program(const char* no) {
|
static void _alter_program(const char* no) {
|
||||||
long lno = 0;
|
long lno = 0;
|
||||||
long i = 0;
|
long i = 0;
|
||||||
|
|
||||||
mb_assert(no);
|
mb_assert(no);
|
||||||
|
|
||||||
lno = atoi(no);
|
lno = atoi(no);
|
||||||
if(lno < 1 || lno > c->count) {
|
if(lno < 1 || lno > c->count) {
|
||||||
printf("Line number %ld out of bound.\n", lno);
|
printf("Line number %ld out of bound.\n", lno);
|
||||||
@ -652,8 +675,9 @@ static void _on_stepped(struct mb_interpreter_t* s, int p, unsigned short row, u
|
|||||||
mb_unrefvar(col);
|
mb_unrefvar(col);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _on_error(struct mb_interpreter_t* s, mb_error_e e, char* m, int p, unsigned short row, unsigned short col, int abort_code) {
|
static void _on_error(struct mb_interpreter_t* s, mb_error_e e, char* m, char* f, int p, unsigned short row, unsigned short col, int abort_code) {
|
||||||
mb_unrefvar(s);
|
mb_unrefvar(s);
|
||||||
|
mb_unrefvar(f);
|
||||||
mb_unrefvar(p);
|
mb_unrefvar(p);
|
||||||
if(SE_NO_ERR != e) {
|
if(SE_NO_ERR != e) {
|
||||||
printf("Error:\n [LINE] %d, [COL] %d,\n [CODE] %d, [MESSAGE] %s, [ABORT CODE] %d\n", row, col, e, m, abort_code);
|
printf("Error:\n [LINE] %d, [COL] %d,\n [CODE] %d, [MESSAGE] %s, [ABORT CODE] %d\n", row, col, e, m, abort_code);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user