Browse Source

Added basic statement support ot uparse.c

- UM_realloc was moved from a macro to an actual function to handle error results
- NODE_STATE nodes have a new value in the node's union, sType which describes the type of statement the node is.
- 'prntint' statements are the only statement avalible for now, they allow printing the value of expressions to the console.
- fixed a bug in ulex.c/identifierType
- main.c was updated to show the prntint statement.
- uparse.c was refactored a bit, including some debugging prints for now
remotes/origin/HEAD
Seth Stubbs 6 months ago
parent
commit
3257ed9041
  1. 3
      .gitignore
  2. 4
      Makefile
  3. 29
      out.tal
  4. 4
      src/main.c
  5. 31
      src/uasm.c
  6. 7
      src/ulex.c
  7. 1
      src/ulex.h
  8. 18
      src/umem.c
  9. 7
      src/umem.h
  10. 80
      src/uparse.c
  11. 7
      src/uparse.h

3
.gitignore

@ -1,2 +1,3 @@
*.o
bin
bin
.vscode

4
Makefile

@ -1,14 +1,16 @@
CC=clang
CFLAGS=-fPIE -Wall -O3 -Isrc -std=c89
CFLAGS=-fPIE -Wall -O2 -Isrc -std=c89
LDFLAGS=-lm #-fsanitize=address
OUT=bin/uxncle
CHDR=\
src/umem.h\
src/ulex.h\
src/uparse.h\
src/uasm.h\
CSRC=\
src/umem.c\
src/ulex.c\
src/uparse.c\
src/uasm.c\

29
out.tal

@ -1,29 +0,0 @@
|10 @Console [ &pad $8 &char $1 &byte $1 &short $2 &string $2 ]
|0000
@number [ &started $1 ]
|0100
#0006 #0002 #0015 MUL2
#0003 #0006 MUL2
ADD2
ADD2
;print-decimal JSR2
BRK
@print-decimal
#00 .number/started STZ
DUP2 #2710 DIV2 DUP2 ,&digit JSR #2710 MUL2 SUB2
DUP2 #03e8 DIV2 DUP2 ,&digit JSR #03e8 MUL2 SUB2
DUP2 #0064 DIV2 DUP2 ,&digit JSR #0064 MUL2 SUB2
DUP2 #000a DIV2 DUP2 ,&digit JSR #000a MUL2 SUB2
,&digit JSR
.number/started LDZ ,&end JCN
LIT '0 .Console/char DEO
&end
JMP2r
&digit
SWP POP
DUP .number/started LDZ ORA #02 JCN
POP JMP2r
LIT '0 ADD .Console/char DEO
#01 .number/started STZ
JMP2r

4
src/main.c

@ -2,8 +2,8 @@
#include "uasm.h"
int main() {
UASTNode *tree = UP_parseSource("6 + 2 * 21 + 3 * 6");
UA_genTal(tree, fopen("out.tal", "w"));
UASTNode *tree = UP_parseSource("prntint 6 + 2 * 21 + 3 * 6; prntint 6 / 2; prntint 24");
UA_genTal(tree, fopen("bin/out.tal", "w"));
/* clean up */
UP_freeTree(tree);

31
src/uasm.c

@ -7,7 +7,7 @@ static const char preamble[] =
"|0100\n";
static const char postamble[] =
"\n;print-decimal JSR2\n"
"\n"
"BRK\n"
"@print-decimal\n"
"\t#00 .number/started STZ\n"
@ -32,12 +32,12 @@ void writeShortLit(FILE *out, int lit) {
fprintf(out, "#%.4x ", lit);
}
void compileAST(FILE *out, UASTNode *node) {
void compileExpression(FILE *out, UASTNode *node) {
/* first, traverse down the AST recusively */
if (node->left)
compileAST(out, node->left);
compileExpression(out, node->left);
if (node->right)
compileAST(out, node->right);
compileExpression(out, node->right);
switch(node->type) {
case NODE_ADD: fwrite("ADD2\n", 5, 1, out); break;
@ -47,7 +47,28 @@ void compileAST(FILE *out, UASTNode *node) {
case NODE_INTLIT: writeShortLit(out, node->num); break;
default:
printf("Compiler error! unknown AST node!! [%d]\n", node->type);
exit(0);
exit(EXIT_FAILURE);
}
}
void compilePrintInt(FILE *out, UASTNode *node) {
compileExpression(out, node->left);
fwrite(";print-decimal JSR2 #20 .Console/char DEO\n", 42, 1, out);
}
void compileAST(FILE *out, UASTNode *node) {
/* STATE nodes hold the expression in node->left, and the next expression in node->right */
while (node && node->type == NODE_STATE) {
switch(node->sType) {
case STATE_PRNT: compilePrintInt(out, node); break;
case STATE_EXPR: compileExpression(out, node->left); break;
default:
printf("Compiler error! unknown Statement node!! [%d]\n", node->sType);
exit(EXIT_FAILURE);
}
/* move to the next statement */
node = node->right;
}
}

7
src/ulex.c

@ -10,7 +10,8 @@ typedef struct {
UReservedWord reservedWords[] = {
{TOKEN_BYTE, "byte", 4},
{TOKEN_SHORT, "short", 5},
{TOKEN_VOID, "void", 4}
{TOKEN_VOID, "void", 4},
{TOKEN_PRINTINT, "prntint", 7}
};
void UL_initLexState(ULexState *state, const char *src) {
@ -80,11 +81,11 @@ void skipWhitespace(ULexState *state) {
UTokenType identifierType(ULexState *state) {
int i;
int len = state->start - state->current;
int len = state->current - state->start;
/* walk through each reserved word and compare it */
for (i = 0; i < sizeof(reservedWords)/sizeof(UReservedWord); i++) {
if (reservedWords[i].len == len && memcmp(state->start, reservedWords[i].word, len))
if (reservedWords[i].len == len && !memcmp(state->start, reservedWords[i].word, len))
return reservedWords[i].type;
}

1
src/ulex.h

@ -6,6 +6,7 @@ typedef enum {
TOKEN_BYTE,
TOKEN_SHORT,
TOKEN_VOID,
TOKEN_PRINTINT,
/* literals */
TOKEN_IDENT,

18
src/umem.c

@ -0,0 +1,18 @@
#include "umem.h"
void* UM_realloc(void *buf, size_t size) {
void *newBuf;
/* if the size is 0, just free it :) */
if (size == 0) {
free(buf);
return NULL;
}
if (!(newBuf = realloc(buf, size))) {
printf("Failed to reallocate memory!\n");
exit(EXIT_FAILURE);
}
return newBuf;
}

7
src/umem.h

@ -5,14 +5,13 @@
#define GROW_FACTOR 2
#define UM_realloc(buf, size) \
realloc(buf, size);
void* UM_realloc(void *buf, size_t size);
#define UM_freearray(buf) \
UM_realloc(buf, NULL);
UM_realloc(buf, 0);
#define UM_free(buf) \
UM_realloc(buf, NULL);
UM_realloc(buf, 0);
#define UM_growarray(type, buf, count, capacity) \
if (count >= capacity || buf == NULL) { \

80
src/uparse.c

@ -51,16 +51,23 @@ UASTNode *newNumNode(UParseState *state, UASTNode *left, UASTNode *right, int nu
return node;
}
UASTNode *newStateNode(UParseState *state, UASTNode *left, UASTNode *right, UStateType type) {
UASTNode *node = newNode(state, NODE_STATE, left, right);
node->sType = type;
return node;
}
void errorAt(UToken *token, int line, const char *fmt, va_list args) {
printf("Syntax error at '%*s' on line %d", token->len, token->str, line);
printf("Syntax error at '%.*s' on line %d\n\t", token->len, token->str, line);
vprintf(fmt, args);
exit(0);
exit(EXIT_FAILURE);
}
void error(UParseState *state, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
errorAt(&state->current, state->lstate.line, fmt, args);
errorAt(&state->previous, state->lstate.line, fmt, args);
va_end(args);
}
@ -68,6 +75,8 @@ void advance(UParseState *state) {
state->previous = state->current;
state->current = UL_scanNext(&state->lstate);
printf("consumed '%.*s', with type %d\n", state->current.len, state->current.str, state->current.type);
if (state->current.type == TOKEN_ERR)
error(state, "unrecognized symbol '%.*s'!", state->current.len, state->current.str);
}
@ -85,6 +94,10 @@ int match(UParseState *state, UTokenType type) {
return 1;
}
int isPEnd(UParseState *state) {
return check(state, TOKEN_ERR) || check(state, TOKEN_EOF);
}
ParseRule* getRule(UTokenType type) {
return &ruleTable[type];
}
@ -93,6 +106,7 @@ ParseRule* getRule(UTokenType type) {
UASTNode* number(UParseState *state, UASTNode *left, Precedence currPrec) {
int num = str2int(state->previous.str, state->previous.len);
printf("got number %d! from token '%.*s' [%d]\n", num, state->previous.len, state->previous.str, state->previous.type);
return newNumNode(state, NULL, NULL, num);
}
@ -121,6 +135,7 @@ ParseRule ruleTable[] = {
{NULL, NULL, PREC_NONE}, /* TOKEN_BYTE */
{NULL, NULL, PREC_NONE}, /* TOKEN_BYTE16 */
{NULL, NULL, PREC_NONE}, /* TOKEN_VOID */
{NULL, NULL, PREC_NONE}, /* TOKEN_PRINTINT */
/* literals */
{NULL, NULL, PREC_NONE}, /* TOKEN_IDENT */
@ -143,6 +158,13 @@ ParseRule ruleTable[] = {
{NULL, NULL, PREC_NONE}, /* TOKEN_ERR */
};
/* ==================================[[ parse statement functions ]]================================== */
UASTNode* printStatement(UParseState *state) {
/* make our statement node & return */
UASTNode *node = expression(state);
return newStateNode(state, node, NULL, STATE_PRNT);
}
UASTNode* parsePrecedence(UParseState *state, UASTNode *left, Precedence prec) {
ParseFunc func;
@ -151,7 +173,7 @@ UASTNode* parsePrecedence(UParseState *state, UASTNode *left, Precedence prec) {
advance(state);
func = getRule(state->previous.type)->prefix;
if (func == NULL) {
error(state, "Illegal syntax!");
error(state, "Illegal syntax! [prefix]");
return NULL;
}
@ -159,7 +181,7 @@ UASTNode* parsePrecedence(UParseState *state, UASTNode *left, Precedence prec) {
while (prec <= getRule(state->current.type)->level) {
func = getRule(state->current.type)->infix;
if (func == NULL) {
error(state, "Illegal syntax!");
error(state, "Illegal syntax! [infix]");
return NULL;
}
advance(state);
@ -170,12 +192,35 @@ UASTNode* parsePrecedence(UParseState *state, UASTNode *left, Precedence prec) {
}
UASTNode* expression(UParseState *state) {
return parsePrecedence(state, NULL, PREC_ASSIGNMENT);
UASTNode *node = parsePrecedence(state, NULL, PREC_ASSIGNMENT);
if (!node)
error(state, "Expected expression!");
return node;
}
UASTNode* statement(UParseState *state) {
/* TODO */
return NULL;
UASTNode *node;
/* find a statement match */
if (match(state, TOKEN_PRINTINT)) {
node = printStatement(state);
} else {
/* no statement match was found, just parse the expression */
node = expression(state);
node = newStateNode(state, node, NULL, STATE_EXPR);
}
return node;
}
void printState(UASTNode *node) {
switch(node->sType) {
case STATE_PRNT: printf("PRNT"); break;
case STATE_EXPR: printf("EXPR"); break;
default: break;
}
}
void printNode(UASTNode *node) {
@ -185,6 +230,7 @@ void printNode(UASTNode *node) {
case NODE_MUL: printf("MUL"); break;
case NODE_DIV: printf("DIV"); break;
case NODE_INTLIT: printf("[%d]", node->num); break;
case NODE_STATE: printState(node); break;
default: break;
}
}
@ -202,14 +248,24 @@ void printTree(UASTNode *node, int indent) {
UASTNode *UP_parseSource(const char *src) {
UParseState state;
UL_initLexState(&state.lstate, src);
UASTNode *root = NULL, *current = NULL;
UL_initLexState(&state.lstate, src);
advance(&state);
UASTNode *tree = expression(&state);
printTree(tree, 16);
do {
if (root == NULL) {
root = statement(&state);
current = root;
} else {
current->right = statement(&state);
current = current->right;
}
} while(match(&state, TOKEN_COLON) && !isPEnd(&state));
printTree(root, 16);
return tree;
return root;
}
void UP_freeTree(UASTNode *tree) {

7
src/uparse.h

@ -8,15 +8,22 @@ typedef enum {
NODE_SUB,
NODE_MUL,
NODE_DIV,
NODE_STATE, /* node->left holds expression tree, node->right holds the next statement */
NODE_INTLIT
} UASTNodeType;
typedef enum {
STATE_PRNT,
STATE_EXPR
} UStateType;
typedef struct s_UASTNode {
UASTNodeType type;
struct s_UASTNode *left;
struct s_UASTNode *right;
union {
int num;
UStateType sType;
};
} UASTNode;

Loading…
Cancel
Save