WIP : Storing line numbers, detecting immediate mode vs storage mode, solver tests are not working

This commit is contained in:
2024-05-06 17:51:42 -04:00
parent a428b905da
commit ee10cc6eb5
5 changed files with 146 additions and 53 deletions

View File

@@ -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;
}
}
}
}

View File

@@ -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();

View File

@@ -5,6 +5,5 @@
void main(void)
{
basic_program program;
basic_repl(&program);
basic_repl();
}