WIP : Storing line numbers, detecting immediate mode vs storage mode, solver tests are not working
This commit is contained in:
111
src/basic.c
111
src/basic.c
@@ -3,14 +3,19 @@
|
||||
#include "conio.h"
|
||||
#include "string.h"
|
||||
#include "stdlib.h"
|
||||
#ifdef __GNUC__
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
struct basic_expr math_expressions[32];
|
||||
int basic_errno;
|
||||
int basic_last_stored_lineno;
|
||||
|
||||
char _tokenizer_value[BASIC_TOKENIZER_MAX_LENGTH];
|
||||
char *_tokenizer_prev;
|
||||
char *_tokenizer_prev_next;
|
||||
|
||||
char basic_memory_lines[BASIC_MAX_LINES][BASIC_MAX_LINE_LENGTH];
|
||||
|
||||
void basic_report_error()
|
||||
{
|
||||
char decimal[2];
|
||||
@@ -33,6 +38,44 @@ void basic_cmd_rem(void *expr)
|
||||
return;
|
||||
}
|
||||
|
||||
void basic_cmd_list(void *data)
|
||||
{
|
||||
basic_expr *expr;
|
||||
char decimal[32];
|
||||
int i = 0;
|
||||
int limit = basic_last_stored_lineno;
|
||||
|
||||
if ( data == NULL ) {
|
||||
basic_errno = BASIC_ERR_INTERNAL_NULLPOINTER;
|
||||
return;
|
||||
}
|
||||
|
||||
expr = basic_parse_expr((char *)data, 0);
|
||||
if ( expr == NULL ) {
|
||||
basic_errno = BASIC_ERR_INTERNAL_NULLPOINTER;
|
||||
return;
|
||||
}
|
||||
/* The default state of the lval integer argument is zero. Nothing special happens in the parsing
|
||||
* of a "LIST" command with no integer argument that ensures this, that's just the default state.
|
||||
* So the only time expr->lval.i will be non-zero is if user said "LIST NNNN". We're relying on that here.
|
||||
*/
|
||||
if ( expr->lval.i != 0 ) {
|
||||
limit = expr->lval.i;
|
||||
}
|
||||
|
||||
memset((char *)&decimal, 0x00, 32);
|
||||
for ( i = 0; i < limit ; i++ ) {
|
||||
if ( basic_memory_lines[i][0] != 0x00 ) {
|
||||
itoa(i, (char *)&decimal);
|
||||
_cputs((char *)&decimal);
|
||||
/* this funky pointer dereferencing is to make bcc happy, it can't
|
||||
* manage indexing the array and dereferencing that */
|
||||
_cputs(((char *)&basic_memory_lines)+i);
|
||||
_cputs("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void basic_cmd_print(void *data)
|
||||
{
|
||||
struct basic_variable result;
|
||||
@@ -42,11 +85,7 @@ void basic_cmd_print(void *data)
|
||||
return;
|
||||
}
|
||||
|
||||
_cputs("PRINT(");
|
||||
_cputs((char *)data);
|
||||
_cputs(")\n");
|
||||
|
||||
expr = basic_parse_expr((char *)data);
|
||||
expr = basic_parse_expr((char *)data, 0);
|
||||
if ( expr == NULL ) {
|
||||
basic_errno = BASIC_ERR_INTERNAL_NULLPOINTER;
|
||||
return;
|
||||
@@ -214,6 +253,21 @@ int basic_solve_expr(struct basic_expr *expr, struct basic_variable *result)
|
||||
result->value.i = BASIC_CONST_FALSE;
|
||||
}
|
||||
break;
|
||||
case BASIC_OPTP_STOR:
|
||||
/* this funky pointer dereferencing is to make bcc happy, it can't
|
||||
* manage indexing the array and dereferencing that */
|
||||
if ( memcpy(
|
||||
(((char *)&basic_memory_lines) + expr->lval.i),
|
||||
(char *)expr->rval.ptr,
|
||||
strlen((char *)expr->rval.ptr)
|
||||
) == 0 ) {
|
||||
basic_errno = BASIC_ERR_INTERNAL_MEMORY;
|
||||
return 0;
|
||||
}
|
||||
result->flags = (result->flags | BASIC_VARFLAG_TSTR | BASIC_VARFLAG_INIT);
|
||||
result->value.ptr = BASIC_MESSAGE_OK;
|
||||
basic_last_stored_lineno = expr->lval.i;
|
||||
return 0;
|
||||
case BASIC_OPTP_ASN:
|
||||
basic_errno = BASIC_ERR_INTERNAL_UNIMPLEMENTED;
|
||||
return 0;
|
||||
@@ -224,11 +278,15 @@ int basic_solve_expr(struct basic_expr *expr, struct basic_variable *result)
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct basic_expr *basic_parse_expr(char *expbuf)
|
||||
struct basic_expr *basic_parse_expr(char *expbuf, int require_line_numbers)
|
||||
{
|
||||
struct basic_expr *ret = &math_expressions[0];
|
||||
char *token = NULL;
|
||||
char flags = 0;
|
||||
if ( require_line_numbers == 1 ) {
|
||||
flags = BASIC_PARSE_FIRSTTOKEN;
|
||||
}
|
||||
|
||||
/*char *subptr = 0;*/
|
||||
|
||||
_tokenizer_init();
|
||||
@@ -243,6 +301,17 @@ struct basic_expr *basic_parse_expr(char *expbuf)
|
||||
expbuf = _tokenize(expbuf, " ");
|
||||
token = tokenizer_token();
|
||||
if ( isdigit(*token) == 1 ) {
|
||||
if ( flags == BASIC_PARSE_FIRSTTOKEN ) {
|
||||
ret->type = BASIC_OPTP_STOR;
|
||||
ret->lval_type = BASIC_LVAL_CONST_INT;
|
||||
ret->lval.i = atoi(token);
|
||||
#ifdef __GNUC__
|
||||
printf("Stored line number %d for %s\n", ret->lval.i, token);
|
||||
#endif
|
||||
ret->rval.ptr = expbuf;
|
||||
ret->rval_type = BASIC_RVAL_PTR;
|
||||
break;
|
||||
}
|
||||
if ( (ret->type == 0) && (flags & BASIC_PARSE_FOUND_LVAL) == BASIC_PARSE_FOUND_LVAL ) {
|
||||
basic_errno = BASIC_ERR_SYNTAX_MULTIPLE_LVALUES;
|
||||
return NULL;
|
||||
@@ -258,6 +327,9 @@ struct basic_expr *basic_parse_expr(char *expbuf)
|
||||
ret->rval_type = BASIC_RVAL_CONST_INT;
|
||||
}
|
||||
} else if ( token != NULL && ret->type == 0x0 ) {
|
||||
if ( flags == BASIC_PARSE_FIRSTTOKEN ) {
|
||||
basic_errno = BASIC_ERR_SYNTAX_NO_LINE_NUMBER;
|
||||
}
|
||||
switch ( *token ) {
|
||||
case '+':
|
||||
ret->type = BASIC_OPTP_ADD;
|
||||
@@ -289,6 +361,13 @@ struct basic_expr *basic_parse_expr(char *expbuf)
|
||||
ret->rval_type = BASIC_RVAL_PTR;
|
||||
ret->rval.ptr = expbuf;
|
||||
return ret;
|
||||
} else if ( strcmp(token, "LIST") == 0 ) {
|
||||
ret->type = BASIC_OPTP_CMD;
|
||||
ret->lval_type = BASIC_LVAL_CMDPTR;
|
||||
ret->lval.cmd_ptr = basic_cmd_list;
|
||||
ret->rval_type = BASIC_RVAL_PTR;
|
||||
ret->rval.ptr = expbuf;
|
||||
return ret;
|
||||
} else {
|
||||
basic_errno = BASIC_ERR_SYNTAX_GENERAL;
|
||||
return NULL;
|
||||
@@ -325,7 +404,7 @@ void basic_print_var(struct basic_variable *var)
|
||||
}
|
||||
}
|
||||
|
||||
void basic_repl(basic_program *program)
|
||||
void basic_repl(void)
|
||||
{
|
||||
char keybuff[512];
|
||||
char outbuff[128];
|
||||
@@ -347,11 +426,19 @@ void basic_repl(basic_program *program)
|
||||
if ( _cgets((char *)&keybuff) != NULL ) {
|
||||
_cputs("\n");
|
||||
|
||||
/* Evaluate */
|
||||
expr = basic_parse_expr((char *)&keybuff);
|
||||
/* Evaluate
|
||||
* First we look for line numbers
|
||||
* When we check for immediate mode operation (which catches commands like LIST)
|
||||
* Then we give up
|
||||
*/
|
||||
expr = basic_parse_expr((char *)&keybuff, 1);
|
||||
if ( basic_errno == BASIC_ERR_SYNTAX_NO_LINE_NUMBER ) {
|
||||
expr = basic_parse_expr((char *)&keybuff, 0);
|
||||
}
|
||||
if ( expr == NULL ) {
|
||||
basic_report_error();
|
||||
basic_errno = 0;
|
||||
continue;
|
||||
}
|
||||
if ( expr->lval_type == BASIC_LVAL_CMDPTR ) {
|
||||
if ( expr->lval.cmd_ptr == NULL ) {
|
||||
@@ -360,6 +447,10 @@ void basic_repl(basic_program *program)
|
||||
basic_errno = 0;
|
||||
} else {
|
||||
(*expr->lval.cmd_ptr)(expr->rval.ptr);
|
||||
if ( basic_errno != 0 ) {
|
||||
basic_report_error();
|
||||
basic_errno = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
23
src/basic.h
23
src/basic.h
@@ -40,24 +40,14 @@
|
||||
#define BASIC_ERR_INTERNAL_UNDEFINED_BEHAVIOR 8
|
||||
#define BASIC_ERR_INTERNAL_UNIMPLEMENTED 9
|
||||
#define BASIC_ERR_MATH_DBZ 10
|
||||
#define BASIC_ERR_SYNTAX_NO_LINE_NUMBER 11
|
||||
|
||||
#define BASIC_MESSAGE_OK "OK\n"
|
||||
|
||||
#define BASIC_TOKENIZER_TOKENS "+-/%*="
|
||||
#define BASIC_TOKENIZER_MAX_LENGTH 512
|
||||
#define BASIC_VARNAME_MAX_LENGTH 16
|
||||
|
||||
struct basic_line {
|
||||
int lineno;
|
||||
char content[BASIC_MAX_LINE_LENGTH];
|
||||
struct basic_line *nextline;
|
||||
};
|
||||
typedef struct basic_line basic_line;
|
||||
|
||||
struct basic_program {
|
||||
char name[128];
|
||||
basic_line *first;
|
||||
};
|
||||
typedef struct basic_program basic_program;
|
||||
|
||||
union basic_value {
|
||||
char c;
|
||||
int i;
|
||||
@@ -97,13 +87,16 @@ typedef struct basic_variable basic_variable;
|
||||
|
||||
extern int basic_errno;
|
||||
|
||||
void basic_repl(basic_program *program);
|
||||
basic_expr *basic_parse_expr(char *);
|
||||
extern char basic_memory_lines[BASIC_MAX_LINES][BASIC_MAX_LINE_LENGTH];
|
||||
|
||||
void basic_repl(void);
|
||||
basic_expr *basic_parse_expr(char *, int);
|
||||
int basic_solve_expr(struct basic_expr *expr, struct basic_variable *result);
|
||||
char *tokenizer_token(void);
|
||||
|
||||
void basic_cmd_rem(void *data);
|
||||
void basic_cmd_print(void *data);
|
||||
void basic_cmd_list(void *data);
|
||||
|
||||
void basic_print_var(basic_variable *var);
|
||||
void basic_report_error();
|
||||
|
||||
@@ -5,6 +5,5 @@
|
||||
|
||||
void main(void)
|
||||
{
|
||||
basic_program program;
|
||||
basic_repl(&program);
|
||||
basic_repl();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user