Browse Source

Added base scope/variable boilerplate stuff to uparse.c

- Also switced to a more modular "struct inheritance" design for UASTNodes
remotes/origin/HEAD
Seth Stubbs 6 months ago
parent
commit
9659675122
  1. 2
      src/uasm.c
  2. 1
      src/ulex.c
  3. 1
      src/ulex.h
  4. 93
      src/uparse.c
  5. 47
      src/uparse.h

2
src/uasm.c

@ -44,7 +44,7 @@ void compileExpression(FILE *out, UASTNode *node) {
case NODE_SUB: fwrite("SUB2\n", 5, 1, out); break;
case NODE_MUL: fwrite("MUL2\n", 5, 1, out); break;
case NODE_DIV: fwrite("DIV2\n", 5, 1, out); break;
case NODE_INTLIT: writeShortLit(out, node->num); break;
case NODE_INTLIT: writeShortLit(out, ((UASTIntNode*)node)->num); break;
default:
printf("Compiler error! unknown AST node!! [%d]\n", node->type);
exit(EXIT_FAILURE);

1
src/ulex.c

@ -127,6 +127,7 @@ UToken UL_scanNext(ULexState *state) {
case '}': return makeToken(state, TOKEN_RIGHT_BRACE);
case '[': return makeToken(state, TOKEN_LEFT_BRACKET);
case ']': return makeToken(state, TOKEN_RIGHT_BRACKET);
case '=': return makeToken(state, TOKEN_EQUAL);
case '+': return makeToken(state, TOKEN_PLUS);
case '-': return makeToken(state, TOKEN_MINUS);
case '/': return makeToken(state, TOKEN_SLASH);

1
src/ulex.h

@ -20,6 +20,7 @@ typedef enum {
TOKEN_RIGHT_BRACKET,
TOKEN_COLON,
TOKEN_POUND,
TOKEN_EQUAL,
TOKEN_PLUS,
TOKEN_MINUS,
TOKEN_SLASH,

93
src/uparse.c

@ -35,8 +35,22 @@ int str2int(char *str, int len) {
/* ==================================[[ generic helper functions ]]================================== */
UASTNode *newNode(UParseState *state, UASTNodeType type, UASTNode *left, UASTNode *right) {
UASTNode *node = UM_realloc(NULL, sizeof(UASTNode));
void errorAt(UToken *token, int line, const char *fmt, va_list args) {
printf("Syntax error at '%.*s' on line %d\n\t", token->len, token->str, line);
vprintf(fmt, args);
printf("\n");
exit(EXIT_FAILURE);
}
void error(UParseState *state, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
errorAt(&state->previous, state->lstate.line, fmt, args);
va_end(args);
}
UASTNode *newBaseNode(UParseState *state, size_t size, UASTNodeType type, UASTNode *left, UASTNode *right) {
UASTNode *node = UM_realloc(NULL, size);
node->type = type;
node->left = left;
node->right = right;
@ -44,25 +58,48 @@ UASTNode *newNode(UParseState *state, UASTNodeType type, UASTNode *left, UASTNod
return node;
}
UASTNode *newNode(UParseState *state, UASTNodeType type, UASTNode *left, UASTNode *right) {
return newBaseNode(state, sizeof(UASTNode), type, left, right);
}
UASTNode *newNumNode(UParseState *state, UASTNode *left, UASTNode *right, int num) {
UASTNode *node = newNode(state, NODE_INTLIT, left, right);
UASTIntNode *node = (UASTIntNode*)newBaseNode(state, sizeof(UASTIntNode), NODE_INTLIT, left, right);
node->num = num;
return (UASTNode*)node;
}
return node;
UASTNode *newScopeNode(UParseState *state, UASTNode *left, UASTNode *right, UScope *scope) {
UASTScopeNode *node = (UASTScopeNode*)newBaseNode(state, sizeof(UASTScopeNode), NODE_STATE_SCOPE, left, right);
node->scope = *scope;
return (UASTNode*)node;
}
void errorAt(UToken *token, int line, const char *fmt, va_list args) {
printf("Syntax error at '%.*s' on line %d\n\t", token->len, token->str, line);
vprintf(fmt, args);
printf("\n");
exit(EXIT_FAILURE);
UScope* newScope(UParseState *state) {
UScope *scope = &state->scopes[state->sCount++];
/* set the scope */
scope->vCount = 0;
return scope;
}
void error(UParseState *state, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
errorAt(&state->previous, state->lstate.line, fmt, args);
va_end(args);
UScope* getScope(UParseState *state) {
return &state->scopes[state->sCount-1];
}
int newVar(UParseState *state, UVarType type, char *name, int length) {
UScope *scope = getScope(state);
UVar *var = &scope->vars[scope->vCount++];
/* sanity check */
if (scope->vCount >= MAX_LOCALS)
error(state, "Max local limit reached, too many locals declared in scope!");
/* set the var and return */
var->type = type;
var->name = name;
var->len = length;
var->declared = 0;
return scope->vCount-1;
}
void advance(UParseState *state) {
@ -143,6 +180,7 @@ ParseRule ruleTable[] = {
{NULL, NULL, PREC_NONE}, /* TOKEN_RIGHT_BRACKET */
{NULL, NULL, PREC_NONE}, /* TOKEN_COLON */
{NULL, NULL, PREC_NONE}, /* TOKEN_POUND */
{NULL, NULL, PREC_NONE}, /* TOKEN_EQUAL */
{NULL, binOperator, PREC_TERM}, /* TOKEN_PLUS */
{NULL, binOperator, PREC_TERM}, /* TOKEN_MINUS */
{NULL, binOperator, PREC_FACTOR}, /* TOKEN_SLASH */
@ -156,8 +194,24 @@ ParseRule ruleTable[] = {
UASTNode* printStatement(UParseState *state) {
/* make our statement node & return */
UASTNode *node = expression(state);
return newNode(state, NODE_STATE_PRNT, node, NULL);
return newNode(state, NODE_STATE_PRNT, expression(state), NULL);
}
UASTNode* shortStatement(UParseState *state) {
UASTVarNode *node;
int var;
/* consume the identifer */
if (!match(state, TOKEN_IDENT))
error(state, "Expected identifer!");
/* define the variable */
var = newVar(state, TYPE_SHORT, state->previous.str, state->previous.len);
/* if it's assigned a value, evaluate the expression & set the left node, if not set it to NULL */
node = (UASTVarNode*)newBaseNode(state, sizeof(UASTVarNode), NODE_STATE_SHORT, (match(state, TOKEN_EQUAL)) ? expression(state) : NULL, NULL);
node->var = var;
return (UASTNode*)node;
}
UASTNode* parsePrecedence(UParseState *state, UASTNode *left, Precedence prec) {
@ -218,8 +272,11 @@ void printNode(UASTNode *node) {
case NODE_SUB: printf("SUB"); break;
case NODE_MUL: printf("MUL"); break;
case NODE_DIV: printf("DIV"); break;
case NODE_INTLIT: printf("[%d]", node->num); break;
case NODE_INTLIT: printf("[%d]", ((UASTIntNode*)node)->num); break;
case NODE_STATE_PRNT: printf("PRNT"); break;
case NODE_STATE_SCOPE: printf("SCPE"); break;
case NODE_STATE_SHORT: printf("SHRT"); break;
case NODE_STATE_VAR: printf("VAR[%d]", ((UASTVarNode*)node)->var); break;
case NODE_STATE_EXPR: printf("EXPR"); break;
default: break;
}
@ -241,6 +298,8 @@ UASTNode *UP_parseSource(const char *src) {
UASTNode *root = NULL, *current = NULL;
int treeIndent = 8;
state.sCount = 1;
UL_initLexState(&state.lstate, src);
advance(&state);

47
src/uparse.h

@ -3,6 +3,11 @@
#include "ulex.h"
#define MAX_SCOPES 32
#define MAX_LOCALS 128
#define COMMON_NODE_HEADER UASTNode _node;
typedef enum {
NODE_ADD,
NODE_SUB,
@ -14,22 +19,58 @@ typedef enum {
node->left holds expression tree, node->right holds the next statement
*/
NODE_STATE_PRNT,
NODE_STATE_SCOPE,
NODE_STATE_SHORT,
NODE_STATE_VAR,
NODE_STATE_EXPR,
} UASTNodeType;
typedef enum {
TYPE_BYTE,
TYPE_SHORT
} UVarType;
typedef struct {
UVarType type;
char *name;
int len;
int declared; /* if the variable can be used yet */
} UVar;
typedef struct {
UVar vars[MAX_LOCALS];
int vCount; /* count of active local variables */
} UScope;
typedef struct s_UASTNode {
UASTNodeType type;
struct s_UASTNode *left;
struct s_UASTNode *right;
union {
int num;
};
} UASTNode;
typedef struct {
COMMON_NODE_HEADER;
int var; /* index of the UVar in the closest scope in the tree */
} UASTVarNode;
typedef struct {
COMMON_NODE_HEADER;
int num;
} UASTIntNode;
typedef struct {
COMMON_NODE_HEADER;
UScope scope;
} UASTScopeNode;
typedef struct {
/* lexer related info */
ULexState lstate;
UToken current;
UToken previous;
/* scopes */
UScope scopes[MAX_SCOPES];
int sCount; /* count of active scopes */
} UParseState;
/* returns the base AST node, or NULL if a syntax error occurred */

Loading…
Cancel
Save