rewrite; a lot better now

master
Clyne Sullivan 7 years ago
parent accef5f54c
commit b9ceb80c9c

@ -0,0 +1,225 @@
#include <parser.h>
#include <stdbool.h>
#include <stdlib.h>
static const char *interpreter_operators = "=(";
bool strcmp(const char *a, const char *b)
{
int i = 0;
for (; a[i] == b[i] && a[i] != '\0'; i++);
return a[i] == b[i];
}
bool strncmp(const char *a, const char *b, int count)
{
int i = 0;
for (; a[i] == b[i] && i < count; i++);
return i == count;
}
uint8_t isalpha(char c)
{
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
uint8_t isnum(char c)
{
return (c >= '0' && c <= '9');
}
uint8_t isname(char c)
{
return isalpha(c) || isnum(c);
}
uint8_t isspace(char c)
{
return (c == ' ' || c == '\t' || c == '\n');
}
uint8_t isoper(char c)
{
for (uint8_t i = 0; i < sizeof(interpreter_operators); i++) {
if (c == interpreter_operators[i])
return 1;
}
return 0;
}
void interpreter_init(interpreter *interp)
{
interp->status = READY;
interp->vcount = 0;
interp->vars = (variable *)calloc(32, sizeof(variable));
interp->names = (char **)calloc(32, sizeof(char *));
interp->stack = (stack_t *)calloc(64, sizeof(stack_t));
}
void interpreter_define_value(interpreter *interp, const char *name, int32_t value)
{
interp->names[interp->vcount] = (char *)name;
interp->vars[interp->vcount].nameidx = interp->vcount;
interp->vars[interp->vcount].type = VALUE;
interp->vars[interp->vcount].value = (uint32_t)value;
interp->vcount++;
}
void interpreter_define_cfunc(interpreter *interp, const char *name, func_t addr)
{
interp->names[interp->vcount] = (char *)name;
interp->vars[interp->vcount].nameidx = interp->vcount;
interp->vars[interp->vcount].type = CFUNCTION;
interp->vars[interp->vcount].value = (uint32_t)addr;
interp->vcount++;
}
int32_t interpreter_get_value(interpreter *interp, const char *name)
{
for (uint16_t i = 0; i < interp->vcount; i++) {
if (!strcmp(interp->names[i], name))
return (int32_t)interp->vars[i].value;
}
return 0;
}
/**
* doline section
*/
bool namencmp(const char *name, const char *s)
{
uint16_t i;
for (i = 0; name[i] == s[i] && s[i] != '\0'; i++);
return (name[i] == '\0' && !isname(s[i]));
}
uint16_t spacecount(const char *s)
{
uint16_t i;
for (i = 0; isspace(s[i]); i++);
return i;
}
char *copystr(const char *s, char end)
{
uint16_t len = 0;
while (s[len++] != end);
char *buf = (char *)malloc(len);
for (uint16_t i = 0; i < len; i++)
buf[i] = s[i];
return buf;
}
char *copysubstr(const char *s, int end)
{
char *buf = (char *)malloc(end);
for (uint16_t i = 0; i < end; i++)
buf[i] = s[i];
return buf;
}
variable *interpreter_getvar(interpreter *interp, const char *line)
{
for (uint16_t i = 0; i < interp->vcount; i++) {
if (namencmp(interp->names[i], line))
return &interp->vars[i];
}
return 0;
}
int interpreter_doline(interpreter *interp, const char *line)
{
variable *bits[16];
uint16_t offset = 0, boffset = 0;
// check for var/func set or usage
int end;
getvar:
for (end = 0; isname(line[end]); end++);
variable *var = interpreter_getvar(interp, line);
if (var != 0) {
bits[boffset++] = var;
} else {
// defining new variable
interpreter_define_value(interp, copysubstr(line, end), 0);
goto getvar; // try again
}
// skip whitespace/name
offset += end;
offset += spacecount(line + offset);
if (boffset == 0 && line[offset] != '=')
return -1; // variable not found
// find operator
if (line[offset] == '\0') {
// print value
return -99;
} else if (line[offset] == '=') {
// assignment/expression
offset++;
offset += spacecount(line + offset);
bits[0]->value = (uint32_t)copystr(line + offset, '\0');
} else if (line[offset] == '(') {
// function call
offset++;
if (bits[0]->type != FUNCTION && bits[0]->type != CFUNCTION)
return -2;
offset += spacecount(line + offset);
// collect arg offsets
uint16_t offsets[8];
uint8_t ooffset = 0;
while (line[offset] != ')' && line[offset] != '\0') {
offsets[ooffset] = offset;
offset += spacecount(line + offset);
uint8_t isvn = 1;
do {
if (line[offset] == ' ' || line[offset] == '\t') {
offset += spacecount(line + offset);
isvn = 0;
}
if (line[offset] == ',') {
offset++;
ooffset++;
break;
} else if (line[offset] == ')') {
ooffset++;
break;
} else if (isvn == 0) {
return -3;
}
} while (++offset);
}
// populate stack
for (uint8_t i = 0; i < ooffset; i++) {
uint16_t j;
for (j = offsets[i]; line[j] != ' ' && line[j] != '\t' &&
line[j] != ',' && line[j] != ')'; j++);
j -= offsets[i];
variable *var = interpreter_getvar(interp, line + offsets[i]);
if (var != 0)
interp->stack[i] = copystr((char *)var->value, '\0');
else
interp->stack[i] = copysubstr(line + offsets[i], j);
}
((func_t)bits[0]->value)(interp->stack);
} else {
return -2; // invalid operation
}
return 0;
}

@ -0,0 +1,31 @@
#ifndef PARSER_H_
#define PARSER_H_
#include <variable.h>
typedef void *stack_t;
typedef struct {
uint16_t status;
uint16_t vcount;
variable *vars;
char **names;
stack_t *stack;
} interpreter;
enum status {
READY = 0
};
typedef void (*func_t)(stack_t *);
void interpreter_init(interpreter *);
void interpreter_define_value(interpreter *, const char *, int32_t);
void interpreter_define_cfunc(interpreter *, const char *, func_t);
int32_t interpreter_get_value(interpreter *, const char *);
int interpreter_doline(interpreter *, const char *);
#endif // PARSER_H_

@ -0,0 +1,24 @@
#ifndef TOKEN_H_
#define TOKEN_H_
#include <stdint.h>
typedef struct {
uint16_t nameidx;
uint8_t type;
uint8_t info;
uint32_t value;
} variable;
#define INFO_ARGS(x) ((x) & 0x07)
#define INFO_RET (1 << 3)
enum vartype {
VALUE = 0,
VARIABLE,
OPERATOR,
FUNCTION,
CFUNCTION
};
#endif // TOKEN_H_

@ -1,225 +1,238 @@
#include <parser.h> #include <parser.h>
#include <stdbool.h> #include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
static const char *interpreter_operators = "=("; #define MAX_VARS 16
#define MAX_STACK 32
bool strcmp(const char *a, const char *b) char *strclone(const char *s)
{ {
int i = 0; char *clone = (char *)malloc(strlen(s));
for (; a[i] == b[i] && a[i] != '\0'; i++); strcpy(clone, s);
return a[i] == b[i]; return clone;
} }
bool strncmp(const char *a, const char *b, int count) char *strnclone(const char *s, uint32_t n)
{ {
int i = 0; char *clone = (char *)malloc(n);
for (; a[i] == b[i] && i < count; i++); strncpy(clone, s, n);
return i == count; return clone;
} }
uint8_t isalpha(char c) void iinit(interpreter *interp)
{ {
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); interp->vars = (variable *)calloc(MAX_VARS, sizeof(variable));
interp->vnames = (char **)calloc(MAX_VARS, sizeof(char *));
interp->stack = (stack_t *)calloc(MAX_STACK, sizeof(stack_t));
interp->stidx = 0;
} }
uint8_t isnum(char c) variable *interpreter_get_variable(interpreter *interp, const char *name)
{ {
return (c >= '0' && c <= '9'); for (uint32_t i = 0; i < MAX_VARS; i++) {
if (!interp->vars[i].used) {
interp->vars[i].used = 1;
interp->vars[i].valtype = FUNC;
interp->vars[i].value = 0;
interp->vnames[i] = strclone(name);
return &interp->vars[i];
} else if (interp->vnames[i] != 0 && !strcmp(interp->vnames[i], name)) {
return &interp->vars[i];
}
}
return 0;
} }
uint8_t isname(char c) void inew_string(interpreter *interp, const char *name, char *value)
{ {
return isalpha(c) || isnum(c); variable *v = interpreter_get_variable(interp, name);
if (v != 0) {
v->valtype = STRING;
v->value = (uint32_t)value;
}
} }
uint8_t isspace(char c) void inew_integer(interpreter *interp, const char *name, int32_t value)
{ {
return (c == ' ' || c == '\t' || c == '\n'); variable *v = interpreter_get_variable(interp, name);
if (v != 0) {
v->valtype = INTEGER;
v->value = (uint32_t)value;
}
} }
uint8_t isoper(char c) void inew_float(interpreter *interp, const char *name, float value)
{ {
for (uint8_t i = 0; i < sizeof(interpreter_operators); i++) { variable *v = interpreter_get_variable(interp, name);
if (c == interpreter_operators[i]) if (v != 0) {
return 1; v->valtype = FLOAT;
v->value = (uint32_t)value;
} }
return 0;
} }
void interpreter_init(interpreter *interp) void inew_cfunc(interpreter *interp, const char *name, func_t func)
{ {
interp->status = READY; variable *v = interpreter_get_variable(interp, name);
interp->vcount = 0; if (v != 0) {
interp->vars = (variable *)calloc(32, sizeof(variable)); v->fromc = 1;
interp->names = (char **)calloc(32, sizeof(char *)); v->valtype = FUNC;
interp->stack = (stack_t *)calloc(64, sizeof(stack_t)); v->value = (uint32_t)func;
}
} }
void interpreter_define_value(interpreter *interp, const char *name, int32_t value) uint8_t eol(int c)
{ {
interp->names[interp->vcount] = (char *)name; return c == '\n' || c == '\0';
interp->vars[interp->vcount].nameidx = interp->vcount;
interp->vars[interp->vcount].type = VALUE;
interp->vars[interp->vcount].value = (uint32_t)value;
interp->vcount++;
} }
void interpreter_define_cfunc(interpreter *interp, const char *name, func_t addr) uint8_t eot(int c)
{ {
interp->names[interp->vcount] = (char *)name; return eol(c) || c == ' ';
interp->vars[interp->vcount].nameidx = interp->vcount;
interp->vars[interp->vcount].type = CFUNCTION;
interp->vars[interp->vcount].value = (uint32_t)addr;
interp->vcount++;
} }
int32_t interpreter_get_value(interpreter *interp, const char *name) variable *make_var(interpreter *interp, const char *line, uint32_t *next)
{ {
for (uint16_t i = 0; i < interp->vcount; i++) { if (line[0] == '\"') { // string literal
if (!strcmp(interp->names[i], name)) uint32_t end = 1;
return (int32_t)interp->vars[i].value; while (!eol(line[end])) {
if (line[end] == '\"'/* && line[end - 1] != '\\'*/) {
if (!eot(line[end + 1]))
return 0;
// TODO string breakdown
variable *v = (variable *)malloc(sizeof(variable));
v->valtype = STRING;
v->value = (uint32_t)strnclone(line + 1, end - 1);
*next = end + 1;
return v;
}
end++;
}
return 0;
} else if (line[0] == '(') { // equation literal
uint32_t end = 1;
while (!eol(line[end])) {
if (line[end] == ')' && line[end - 1] != '\\') {
if (!eot(line[end + 1]))
return 0;
// TODO string breakdown
// TODO make var
return 0;
}
end++;
}
} else if (isalpha(line[0])) { // variable/func
uint32_t end = 1;
for (; isalnum(line[end]); end++);
if (!eot(line[end]))
return 0;
char *name = (char *)malloc(end + 1);
strncpy(name, line, end);
name[end] = '\0';
*next = end;
return interpreter_get_variable(interp, name);
} else if (isdigit(line[0])) { // number
uint32_t end = 1;
uint8_t dec = 0;
for (; !eot(line[end]); end++) {
if (!isdigit(line[end])) {
if (line[end] == '.') {
if (!dec)
dec = 1;
else
return 0;
}
return 0;
}
}
variable *v = (variable *)malloc(sizeof(variable));
v->valtype = INTEGER;
v->value = atoi(line);
*next = end;
return v;
} }
return 0; return 0;
} }
/** int idoline(interpreter *interp, const char *line)
* doline section
*/
bool namencmp(const char *name, const char *s)
{ {
uint16_t i; variable *ops[8];
for (i = 0; name[i] == s[i] && s[i] != '\0'; i++); uint32_t ooffset = 0;
return (name[i] == '\0' && !isname(s[i])); uint32_t offset = 0;
} uint32_t next;
uint16_t spacecount(const char *s) // step 1 - convert to tokens
{ while (!eol(line[offset])) {
uint16_t i; ops[ooffset] = make_var(interp, line + offset, &next);
for (i = 0; isspace(s[i]); i++); if (ops[ooffset] == 0) {
return i; return -4;
} else {
ooffset++;
offset += next;
}
// skip whitespace
for (; line[offset] == ' ' && !eol(line[offset]); offset++);
}
// step 2 - execute
if (ooffset == 0)
return -1;
if (ops[0]->valtype != FUNC)
return -2;
if (ops[0]->value == 0)
return -3;
for (uint32_t i = 0; i < ooffset - 1; i++, interp->stidx++)
interp->stack[i] = ops[i + 1];
((func_t)ops[0]->value)(interp);
return 0;
} }
char *copystr(const char *s, char end) char *igetarg_string(interpreter *interp, uint32_t index)
{ {
uint16_t len = 0; if (index >= interp->stidx)
while (s[len++] != end); return 0;
char *buf = (char *)malloc(len); if (interp->stack[index]->valtype != STRING)
for (uint16_t i = 0; i < len; i++) return 0;
buf[i] = s[i]; return (char *)interp->stack[index]->value;
return buf;
} }
char *copysubstr(const char *s, int end) int igetarg_integer(interpreter *interp, uint32_t index)
{ {
char *buf = (char *)malloc(end); if (index >= interp->stidx)
for (uint16_t i = 0; i < end; i++) return 0;
buf[i] = s[i]; if (interp->stack[index]->valtype != INTEGER)
return buf; return 0;
return (int)interp->stack[index]->value;
} }
variable *interpreter_getvar(interpreter *interp, const char *line) float igetarg_float(interpreter *interp, uint32_t index)
{ {
for (uint16_t i = 0; i < interp->vcount; i++) { if (index >= interp->stidx)
if (namencmp(interp->names[i], line)) return 0;
return &interp->vars[i]; if (interp->stack[index]->valtype != FLOAT)
}
return 0; return 0;
return (float)interp->stack[index]->value;
} }
int interpreter_doline(interpreter *interp, const char *line) /*char *iget_string(interpreter *, const char *)
{ {
variable *bits[16];
uint16_t offset = 0, boffset = 0;
// check for var/func set or usage
int end;
getvar:
for (end = 0; isname(line[end]); end++);
variable *var = interpreter_getvar(interp, line);
if (var != 0) {
bits[boffset++] = var;
} else {
// defining new variable
interpreter_define_value(interp, copysubstr(line, end), 0);
goto getvar; // try again
}
// skip whitespace/name
offset += end;
offset += spacecount(line + offset);
if (boffset == 0 && line[offset] != '=')
return -1; // variable not found
// find operator
if (line[offset] == '\0') {
// print value
return -99;
} else if (line[offset] == '=') {
// assignment/expression
offset++;
offset += spacecount(line + offset);
bits[0]->value = (uint32_t)copystr(line + offset, '\0');
} else if (line[offset] == '(') {
// function call
offset++;
if (bits[0]->type != FUNCTION && bits[0]->type != CFUNCTION)
return -2;
offset += spacecount(line + offset);
// collect arg offsets }
uint16_t offsets[8];
uint8_t ooffset = 0;
while (line[offset] != ')' && line[offset] != '\0') {
offsets[ooffset] = offset;
offset += spacecount(line + offset);
uint8_t isvn = 1;
do {
if (line[offset] == ' ' || line[offset] == '\t') {
offset += spacecount(line + offset);
isvn = 0;
}
if (line[offset] == ',') {
offset++;
ooffset++;
break;
} else if (line[offset] == ')') {
ooffset++;
break;
} else if (isvn == 0) {
return -3;
}
} while (++offset);
}
// populate stack int iget_integer(interpreter *, const char *)
for (uint8_t i = 0; i < ooffset; i++) { {
uint16_t j;
for (j = offsets[i]; line[j] != ' ' && line[j] != '\t' &&
line[j] != ',' && line[j] != ')'; j++);
j -= offsets[i];
variable *var = interpreter_getvar(interp, line + offsets[i]); }
if (var != 0)
interp->stack[i] = copystr((char *)var->value, '\0');
else
interp->stack[i] = copysubstr(line + offsets[i], j);
}
((func_t)bits[0]->value)(interp->stack); float iget_float(interpreter *, const char *)
} else { {
return -2; // invalid operation
}
return 0; }*/
}

@ -3,29 +3,32 @@
#include <variable.h> #include <variable.h>
typedef void *stack_t; typedef variable *stack_t;
typedef struct { typedef struct {
uint16_t status;
uint16_t vcount;
variable *vars; variable *vars;
char **names; char **vnames;
stack_t *stack; stack_t *stack;
uint32_t stidx;
} interpreter; } interpreter;
enum status { typedef void (*func_t)(interpreter *);
READY = 0
};
typedef void (*func_t)(stack_t *); void iinit(interpreter *);
void interpreter_init(interpreter *); void inew_string(interpreter *, const char *, char *);
void inew_integer(interpreter *, const char *, int32_t);
void inew_float(interpreter *, const char *, float);
void inew_cfunc(interpreter *, const char *, func_t);
void interpreter_define_value(interpreter *, const char *, int32_t); int idoline(interpreter *, const char *);
void interpreter_define_cfunc(interpreter *, const char *, func_t);
int32_t interpreter_get_value(interpreter *, const char *); char *igetarg_string(interpreter *, uint32_t);
int igetarg_integer(interpreter *, uint32_t);
float igetarg_float(interpreter *, uint32_t);
int interpreter_doline(interpreter *, const char *); char *iget_string(interpreter *, const char *);
int iget_integer(interpreter *, const char *);
float iget_float(interpreter *, const char *);
#endif // PARSER_H_ #endif // PARSER_H_

@ -1,26 +1,42 @@
#include <parser.h> #include <parser.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
void test(stack_t *stack) void test(interpreter *it)
{ {
printf("%s\n", stack[0]); char *s = igetarg_string(it, 0);
if (s == 0)
s = "(null)";
printf("%s\n", s);
} }
int main(int argc, char *argv[]) void quit(interpreter *it)
{
(void)it;
exit(0);
}
int main()
{ {
interpreter interp; interpreter interp;
interpreter_init(&interp); iinit(&interp);
interpreter_define_value(&interp, "answer", "42"); inew_integer(&interp, "answer", 42);
interpreter_define_cfunc(&interp, "test", test); inew_cfunc(&interp, "put", test);
inew_cfunc(&interp, "exit", quit);
if (argc > 1) {
for (int i = 1; i < argc; i++) { char *line = 0;
int result = interpreter_doline(&interp, argv[i]); unsigned int size;
int result;
while (1) {
getline(&line, &size, stdin);
*strchr(line, '\n') = '\0';
result = idoline(&interp, line);
if (result != 0) if (result != 0)
printf("%d\n", result); printf("Error: %d\n", result);
}
} }
return 0; return 0;

@ -1,24 +1,20 @@
#ifndef TOKEN_H_ #ifndef VARIABLE_H_
#define TOKEN_H_ #define VARIABLE_H_
#include <stdint.h> #include <stdint.h>
typedef struct { typedef struct {
uint16_t nameidx; uint8_t used :1;
uint8_t type; uint8_t fromc :1;
uint8_t info; uint8_t valtype :2;
uint32_t value; uint32_t value;
} variable; } variable;
#define INFO_ARGS(x) ((x) & 0x07) enum valtype {
#define INFO_RET (1 << 3) STRING = 0,
INTEGER,
enum vartype { FLOAT,
VALUE = 0, FUNC
VARIABLE,
OPERATOR,
FUNCTION,
CFUNCTION
}; };
#endif // TOKEN_H_ #endif // VARIABLE_H_

Loading…
Cancel
Save