From 591858334bfe8411eeb1cdd7a963c98760f0fb91 Mon Sep 17 00:00:00 2001 From: Andrew Kesterson Date: Sun, 5 May 2024 06:55:39 -0400 Subject: [PATCH] - Added the ability to start a line with a number and store it for later execution - Added the ability to force immediate mode processing (calculator mode) by beginning a line with = - Expanded parser testing - Expression execution seems to be broken now, everything is returning error code 0 and not returning results --- src/basic.c | 52 +++++++++++++++++++++++++++++-------- src/basic.h | 62 ++++++++++++++++++++++++-------------------- tests/basic_parser.c | 15 ++++++++++- 3 files changed, 89 insertions(+), 40 deletions(-) diff --git a/src/basic.c b/src/basic.c index 9c59dad..8e23782 100644 --- a/src/basic.c +++ b/src/basic.c @@ -6,11 +6,25 @@ struct basic_expr math_expressions[32]; int basic_errno; - +basic_line basic_memory_lines[BASIC_MAX_LINES]; char _tokenizer_value[BASIC_TOKENIZER_MAX_LENGTH]; char *_tokenizer_prev; char *_tokenizer_prev_next; +basic_line *_basic_store_line(char *line, int lineno) +{ + basic_line *unused = NULL; + int i = 0; + for ( i = 0; i < BASIC_MAX_LINES; i++ ) { + if ( basic_memory_lines[i].content[0] == 0x00 ) { + unused = (basic_line *)&basic_memory_lines[i]; + memcpy(unused->content, line, strlen(line)); + return unused; + } + } + return NULL; +} + void _tokenizer_init(void) { _tokenizer_prev = NULL; @@ -143,6 +157,10 @@ int basic_solve_expr(struct basic_expr *expr, struct basic_variable *result) result->value.i = BASIC_CONST_FALSE; } break; + case BASIC_OPTP_STOR: + result->flags = (result->flags | BASIC_VARFLAG_TSTR | BASIC_VARFLAG_INIT); + result->value.str = "OK\n"; + return 0; case BASIC_OPTP_ASN: basic_errno = BASIC_ERR_INTERNAL_UNIMPLEMENTED; return 0; @@ -157,29 +175,31 @@ struct basic_expr *basic_parse_expr(char *expbuf) { struct basic_expr *ret = &math_expressions[0]; char *token = NULL; - char flags = 0; - /*char *subptr = 0;*/ + char flags = BASIC_PARSE_FIRSTTOKEN; _tokenizer_init(); memset(ret, 0x0, sizeof(struct basic_expr)); while ( *expbuf != '\0' ) { - if ( *expbuf == ' ' ) { - expbuf += 1; - continue; - } - expbuf = _tokenize(expbuf, BASIC_TOKENIZER_TOKENS); token = _token_get(); if ( isdigit(*token) == 1 ) { - if ( (ret->type == 0) && (flags & BASIC_FOUND_LVAL) == BASIC_FOUND_LVAL ) { + if ( flags == BASIC_PARSE_FIRSTTOKEN ) { + ret->lval.i = atoi(token); + ret->lval_type = BASIC_LVAL_CONST; + ret->type = BASIC_OPTP_STOR; + ret->rval.ptr = _basic_store_line(expbuf, ret->lval.i); + 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; } else if ( ret->type == 0x0 ) { ret->lval.i = atoi(token); ret->lval_type = BASIC_LVAL_CONST; - flags = (flags | BASIC_FOUND_LVAL); - } else if ( ret->type != 0x0 && ((flags & BASIC_FOUND_RVAL) == BASIC_FOUND_RVAL)) { + flags = (flags | BASIC_PARSE_FOUND_LVAL); + } else if ( ret->type != 0x0 && ((flags & BASIC_PARSE_FOUND_RVAL) == BASIC_PARSE_FOUND_RVAL)) { basic_errno = BASIC_ERR_SYNTAX_MULTIPLE_RVALUES; return NULL; } else if ( ret->type != 0x0 ) { @@ -197,6 +217,15 @@ struct basic_expr *basic_parse_expr(char *expbuf) ret->type = BASIC_OPTP_DIV; } else if ( *token == '%' ) { ret->type = BASIC_OPTP_MOD; + } else if ( *token == '=' ) { + if ( flags == BASIC_PARSE_FIRSTTOKEN ) { + /* A statement with = as the first character is processed in + * immediate mode even if the expression begins with a digit and + * only performs arithmetic. aka calculator mode. + * This logic is only here to count the = as the first token so + * proceeding digits don't get counted as line numbers. */ + flags = 0; + } } else { basic_errno = BASIC_ERR_SYNTAX_GENERAL; return NULL; @@ -237,6 +266,7 @@ void basic_repl(basic_program *program) decimal[0] = 0; decimal[1] = 0; + memset((char *)&basic_memory_lines, 0x00, BASIC_MAX_LINES*BASIC_MAX_LINE_LENGTH); blankScreen(); setCursorPosition(0, 0); _cputs("Piquant Basic v0.1\n\n"); diff --git a/src/basic.h b/src/basic.h index 0bd56fe..e579d6b 100644 --- a/src/basic.h +++ b/src/basic.h @@ -1,23 +1,29 @@ #ifndef _BASIC_H_ #define _BASIC_H_ -#define BASIC_OPTP_ADD 1 -#define BASIC_OPTP_SUB 2 -#define BASIC_OPTP_MUL 3 -#define BASIC_OPTP_DIV 4 -#define BASIC_OPTP_MOD 5 -#define BASIC_OPTP_EQL 6 -#define BASIC_OPTP_ASN 7 +#define BASIC_MAX_LINES 1000 +#define BASIC_MAX_LINE_LENGTH 256 -#define BASIC_LVAL_EXPR 0 -#define BASIC_LVAL_VAR 1 -#define BASIC_LVAL_CONST 2 -#define BASIC_RVAL_EXPR 3 -#define BASIC_RVAL_VAR 4 -#define BASIC_RVAL_CONST 5 +#define BASIC_OPTP_ADD 1 /* Add */ +#define BASIC_OPTP_SUB 2 /* Subtract */ +#define BASIC_OPTP_MUL 3 /* Multiply */ +#define BASIC_OPTP_DIV 4 /* Divide */ +#define BASIC_OPTP_MOD 5 /* Modulus */ +#define BASIC_OPTP_EQL 6 /* Equality test */ +#define BASIC_OPTP_ASN 7 /* Assignment */ +#define BASIC_OPTP_STOR 8 /* Store line for later */ -#define BASIC_FOUND_LVAL 0x0001 -#define BASIC_FOUND_RVAL 0x0002 +#define BASIC_LVAL_EXPR 0 +#define BASIC_LVAL_VAR 1 +#define BASIC_LVAL_CONST 2 +#define BASIC_RVAL_EXPR 3 +#define BASIC_RVAL_VAR 4 +#define BASIC_RVAL_CONST 5 +#define BASIC_RVAL_PTR 6 /* Only used internally */ + +#define BASIC_PARSE_FOUND_LVAL 1 +#define BASIC_PARSE_FOUND_RVAL 2 +#define BASIC_PARSE_FIRSTTOKEN 4 #define BASIC_ERR_SYNTAX_MULTIPLE_LVALUES 1 #define BASIC_ERR_SYNTAX_TOKEN_LENGTH 2 @@ -34,6 +40,19 @@ #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; @@ -67,19 +86,6 @@ struct basic_variable { }; typedef struct basic_variable basic_variable; -struct basic_line { - int lineno; - char content[256]; - 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; - #define BASIC_CONST_TRUE 1 #define BASIC_CONST_FALSE 0 diff --git a/tests/basic_parser.c b/tests/basic_parser.c index d1c301a..2de1edc 100644 --- a/tests/basic_parser.c +++ b/tests/basic_parser.c @@ -5,12 +5,25 @@ int main(void) { struct basic_expr *expr; - expr = basic_parse_expr("1 + 1"); + struct basic_line *line; + /* Store a line */ + expr = basic_parse_expr("10 =1 + 1"); + if ( expr == NULL ) return 1; + if ( expr->lval_type != BASIC_LVAL_CONST ) return 2; + if ( expr->rval_type != BASIC_RVAL_PTR ) return 3; + if ( expr->lval.i != 10 ) return 4; + if ( expr->rval.ptr == NULL ) return 5; + if ( expr->type != BASIC_OPTP_STOR ) return 6; + + /* Parse the stored line */ + line = (basic_line *)expr->rval.ptr; + expr = basic_parse_expr(line->content); if ( expr == NULL ) return 1; if ( expr->lval_type != BASIC_LVAL_CONST ) return 2; if ( expr->rval_type != BASIC_RVAL_CONST ) return 3; if ( expr->lval.i != 1 ) return 4; if ( expr->rval.i != 1 ) return 5; if ( expr->type != BASIC_OPTP_ADD ) return 6; + return 0; } \ No newline at end of file