big changes; no ints; things work better
parent
0fb67b8d66
commit
952cb2d6db
@ -1,225 +0,0 @@
|
|||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
|||||||
#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_
|
|
@ -1,24 +0,0 @@
|
|||||||
#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,121 +0,0 @@
|
|||||||
#include <parser.h>
|
|
||||||
#include <builtins.h>
|
|
||||||
|
|
||||||
#include "stack.h"
|
|
||||||
|
|
||||||
#include <memory.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
//#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
extern int rand(void);
|
|
||||||
|
|
||||||
int s_put(interpreter *it)
|
|
||||||
{
|
|
||||||
char *s = igetarg_string(it, 0);
|
|
||||||
printf("%s", s);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int s_type(interpreter *it)
|
|
||||||
{
|
|
||||||
variable *v = (variable *)it->stack[0];
|
|
||||||
switch (v->valtype) {
|
|
||||||
case STRING:
|
|
||||||
puts("string");
|
|
||||||
break;
|
|
||||||
case INTEGER:
|
|
||||||
puts("integer");
|
|
||||||
break;
|
|
||||||
case FLOAT:
|
|
||||||
puts("float");
|
|
||||||
break;
|
|
||||||
case FUNC:
|
|
||||||
puts("func");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
puts("unknown");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int input(interpreter *it)
|
|
||||||
{
|
|
||||||
variable *v = igetarg(it, 0);
|
|
||||||
v->valtype = STRING;
|
|
||||||
v->svalue = malloc(128);
|
|
||||||
unsigned int unused;
|
|
||||||
getline(&v->svalue, &unused, stdin);
|
|
||||||
*strchr(v->svalue, '\n') = '\0';
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int concat(interpreter *it)
|
|
||||||
{
|
|
||||||
variable *v = igetarg(it, 0);
|
|
||||||
char *s = igetarg_string(it, 1);
|
|
||||||
char *new = malloc(strlen(v->svalue) + strlen(s) + 1);
|
|
||||||
strcpy(new, v->svalue);
|
|
||||||
strcpy(new + strlen(v->svalue), s);
|
|
||||||
new[strlen(v->svalue) + strlen(s)] = 0;
|
|
||||||
v->svalue = new;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int script_rand(interpreter *it)
|
|
||||||
{
|
|
||||||
static variable v;
|
|
||||||
v.valtype = INTEGER;
|
|
||||||
unsigned int mod = igetarg_integer(it, 0);
|
|
||||||
unsigned int val = rand();
|
|
||||||
INT(&v) = val % mod;
|
|
||||||
isetstr(&v);
|
|
||||||
iret(it, &v);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int line(interpreter *it)
|
|
||||||
{
|
|
||||||
(void)it;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
interpreter interp;
|
|
||||||
|
|
||||||
if (argc != 2) {
|
|
||||||
printf("Usage: %s file\n", argv[0]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *fp = fopen(argv[1], "r");
|
|
||||||
if (fp == 0) {
|
|
||||||
printf("Could not open file: %s\n", argv[1]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
iinit(&interp);
|
|
||||||
inew_cfunc(&interp, "print", s_put);
|
|
||||||
inew_cfunc(&interp, "tp", s_type);
|
|
||||||
inew_cfunc(&interp, "gets", input);
|
|
||||||
inew_cfunc(&interp, "concat", concat);
|
|
||||||
inew_cfunc(&interp, "rand", script_rand);
|
|
||||||
inew_cfunc(&interp, "line", line);
|
|
||||||
|
|
||||||
|
|
||||||
char *line = 0;
|
|
||||||
unsigned int size;
|
|
||||||
int result;
|
|
||||||
while (getline(&line, &size, fp) != -1) {
|
|
||||||
*strchr(line, '\n') = '\0';
|
|
||||||
result = idoline(&interp, line);
|
|
||||||
if (result != 0)
|
|
||||||
printf("Error: %d\n", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
iend(&interp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
Reference in New Issue