- 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
This commit is contained in:
52
src/basic.c
52
src/basic.c
@@ -6,11 +6,25 @@
|
|||||||
|
|
||||||
struct basic_expr math_expressions[32];
|
struct basic_expr math_expressions[32];
|
||||||
int basic_errno;
|
int basic_errno;
|
||||||
|
basic_line basic_memory_lines[BASIC_MAX_LINES];
|
||||||
char _tokenizer_value[BASIC_TOKENIZER_MAX_LENGTH];
|
char _tokenizer_value[BASIC_TOKENIZER_MAX_LENGTH];
|
||||||
char *_tokenizer_prev;
|
char *_tokenizer_prev;
|
||||||
char *_tokenizer_prev_next;
|
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)
|
void _tokenizer_init(void)
|
||||||
{
|
{
|
||||||
_tokenizer_prev = NULL;
|
_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;
|
result->value.i = BASIC_CONST_FALSE;
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case BASIC_OPTP_ASN:
|
||||||
basic_errno = BASIC_ERR_INTERNAL_UNIMPLEMENTED;
|
basic_errno = BASIC_ERR_INTERNAL_UNIMPLEMENTED;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -157,29 +175,31 @@ struct basic_expr *basic_parse_expr(char *expbuf)
|
|||||||
{
|
{
|
||||||
struct basic_expr *ret = &math_expressions[0];
|
struct basic_expr *ret = &math_expressions[0];
|
||||||
char *token = NULL;
|
char *token = NULL;
|
||||||
char flags = 0;
|
char flags = BASIC_PARSE_FIRSTTOKEN;
|
||||||
/*char *subptr = 0;*/
|
|
||||||
|
|
||||||
_tokenizer_init();
|
_tokenizer_init();
|
||||||
memset(ret, 0x0, sizeof(struct basic_expr));
|
memset(ret, 0x0, sizeof(struct basic_expr));
|
||||||
|
|
||||||
while ( *expbuf != '\0' ) {
|
while ( *expbuf != '\0' ) {
|
||||||
if ( *expbuf == ' ' ) {
|
|
||||||
expbuf += 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
expbuf = _tokenize(expbuf, BASIC_TOKENIZER_TOKENS);
|
expbuf = _tokenize(expbuf, BASIC_TOKENIZER_TOKENS);
|
||||||
token = _token_get();
|
token = _token_get();
|
||||||
if ( isdigit(*token) == 1 ) {
|
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;
|
basic_errno = BASIC_ERR_SYNTAX_MULTIPLE_LVALUES;
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if ( ret->type == 0x0 ) {
|
} else if ( ret->type == 0x0 ) {
|
||||||
ret->lval.i = atoi(token);
|
ret->lval.i = atoi(token);
|
||||||
ret->lval_type = BASIC_LVAL_CONST;
|
ret->lval_type = BASIC_LVAL_CONST;
|
||||||
flags = (flags | BASIC_FOUND_LVAL);
|
flags = (flags | BASIC_PARSE_FOUND_LVAL);
|
||||||
} else if ( ret->type != 0x0 && ((flags & BASIC_FOUND_RVAL) == BASIC_FOUND_RVAL)) {
|
} else if ( ret->type != 0x0 && ((flags & BASIC_PARSE_FOUND_RVAL) == BASIC_PARSE_FOUND_RVAL)) {
|
||||||
basic_errno = BASIC_ERR_SYNTAX_MULTIPLE_RVALUES;
|
basic_errno = BASIC_ERR_SYNTAX_MULTIPLE_RVALUES;
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if ( ret->type != 0x0 ) {
|
} else if ( ret->type != 0x0 ) {
|
||||||
@@ -197,6 +217,15 @@ struct basic_expr *basic_parse_expr(char *expbuf)
|
|||||||
ret->type = BASIC_OPTP_DIV;
|
ret->type = BASIC_OPTP_DIV;
|
||||||
} else if ( *token == '%' ) {
|
} else if ( *token == '%' ) {
|
||||||
ret->type = BASIC_OPTP_MOD;
|
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 {
|
} else {
|
||||||
basic_errno = BASIC_ERR_SYNTAX_GENERAL;
|
basic_errno = BASIC_ERR_SYNTAX_GENERAL;
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -237,6 +266,7 @@ void basic_repl(basic_program *program)
|
|||||||
decimal[0] = 0;
|
decimal[0] = 0;
|
||||||
decimal[1] = 0;
|
decimal[1] = 0;
|
||||||
|
|
||||||
|
memset((char *)&basic_memory_lines, 0x00, BASIC_MAX_LINES*BASIC_MAX_LINE_LENGTH);
|
||||||
blankScreen();
|
blankScreen();
|
||||||
setCursorPosition(0, 0);
|
setCursorPosition(0, 0);
|
||||||
_cputs("Piquant Basic v0.1\n\n");
|
_cputs("Piquant Basic v0.1\n\n");
|
||||||
|
|||||||
50
src/basic.h
50
src/basic.h
@@ -1,13 +1,17 @@
|
|||||||
#ifndef _BASIC_H_
|
#ifndef _BASIC_H_
|
||||||
#define _BASIC_H_
|
#define _BASIC_H_
|
||||||
|
|
||||||
#define BASIC_OPTP_ADD 1
|
#define BASIC_MAX_LINES 1000
|
||||||
#define BASIC_OPTP_SUB 2
|
#define BASIC_MAX_LINE_LENGTH 256
|
||||||
#define BASIC_OPTP_MUL 3
|
|
||||||
#define BASIC_OPTP_DIV 4
|
#define BASIC_OPTP_ADD 1 /* Add */
|
||||||
#define BASIC_OPTP_MOD 5
|
#define BASIC_OPTP_SUB 2 /* Subtract */
|
||||||
#define BASIC_OPTP_EQL 6
|
#define BASIC_OPTP_MUL 3 /* Multiply */
|
||||||
#define BASIC_OPTP_ASN 7
|
#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_LVAL_EXPR 0
|
#define BASIC_LVAL_EXPR 0
|
||||||
#define BASIC_LVAL_VAR 1
|
#define BASIC_LVAL_VAR 1
|
||||||
@@ -15,9 +19,11 @@
|
|||||||
#define BASIC_RVAL_EXPR 3
|
#define BASIC_RVAL_EXPR 3
|
||||||
#define BASIC_RVAL_VAR 4
|
#define BASIC_RVAL_VAR 4
|
||||||
#define BASIC_RVAL_CONST 5
|
#define BASIC_RVAL_CONST 5
|
||||||
|
#define BASIC_RVAL_PTR 6 /* Only used internally */
|
||||||
|
|
||||||
#define BASIC_FOUND_LVAL 0x0001
|
#define BASIC_PARSE_FOUND_LVAL 1
|
||||||
#define BASIC_FOUND_RVAL 0x0002
|
#define BASIC_PARSE_FOUND_RVAL 2
|
||||||
|
#define BASIC_PARSE_FIRSTTOKEN 4
|
||||||
|
|
||||||
#define BASIC_ERR_SYNTAX_MULTIPLE_LVALUES 1
|
#define BASIC_ERR_SYNTAX_MULTIPLE_LVALUES 1
|
||||||
#define BASIC_ERR_SYNTAX_TOKEN_LENGTH 2
|
#define BASIC_ERR_SYNTAX_TOKEN_LENGTH 2
|
||||||
@@ -34,6 +40,19 @@
|
|||||||
#define BASIC_TOKENIZER_MAX_LENGTH 512
|
#define BASIC_TOKENIZER_MAX_LENGTH 512
|
||||||
#define BASIC_VARNAME_MAX_LENGTH 16
|
#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 {
|
union basic_value {
|
||||||
char c;
|
char c;
|
||||||
int i;
|
int i;
|
||||||
@@ -67,19 +86,6 @@ struct basic_variable {
|
|||||||
};
|
};
|
||||||
typedef struct basic_variable 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_TRUE 1
|
||||||
#define BASIC_CONST_FALSE 0
|
#define BASIC_CONST_FALSE 0
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,25 @@
|
|||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
struct basic_expr *expr;
|
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 == NULL ) return 1;
|
||||||
if ( expr->lval_type != BASIC_LVAL_CONST ) return 2;
|
if ( expr->lval_type != BASIC_LVAL_CONST ) return 2;
|
||||||
if ( expr->rval_type != BASIC_RVAL_CONST ) return 3;
|
if ( expr->rval_type != BASIC_RVAL_CONST ) return 3;
|
||||||
if ( expr->lval.i != 1 ) return 4;
|
if ( expr->lval.i != 1 ) return 4;
|
||||||
if ( expr->rval.i != 1 ) return 5;
|
if ( expr->rval.i != 1 ) return 5;
|
||||||
if ( expr->type != BASIC_OPTP_ADD ) return 6;
|
if ( expr->type != BASIC_OPTP_ADD ) return 6;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user