Browse Source

Added while loops!

- Added TOKEN_WHILE and NODE_STATE_WHILE
- Also added UASTWhileNode
remotes/origin/HEAD
Seth Stubbs 5 months ago
parent
commit
c21d4e6b42
  1. 10
      src/main.c
  2. 24
      src/uasm.c
  3. 1
      src/ulex.c
  4. 1
      src/ulex.h
  5. 21
      src/uparse.c
  6. 6
      src/uparse.h

10
src/main.c

@ -3,11 +3,11 @@
int main() {
UASTRootNode *tree = UP_parseSource(
"int a = 2 * 4;\n"
"if (a == 9)\n"
"prntint 0xFFFF;\n"
"else\n"
"prntint a;"
"int i = 0;\n"
"while (i != 10) {\n"
" prntint i;"
" i = i + 1;\n"
"}\n"
);
UA_genTal(tree, fopen("bin/out.tal", "w"));

24
src/uasm.c

@ -414,6 +414,29 @@ void compileIf(UCompState *state, UASTNode *node) {
fprintf(state->out, "@jmp%d\n", jmpID);
}
void compileWhile(UCompState *state, UASTNode *node) {
UASTWhileNode *ifNode = (UASTWhileNode*)node;
int loopStart = state->jmpID++;
int jmpID = state->jmpID++;
/* compile conditional */
fprintf(state->out, "@loop%d\n", loopStart);
UVarType type = compileExpression(state, node->left);
if (!tryTypeCast(state, type, TYPE_BOOL))
cErrorNode(state, (UASTNode*)ifNode, "Cannot cast type '%s' to type '%s'", getTypeName(type), getTypeName(TYPE_BOOL));
/* write comparison jump, if the flag is not equal to true, skip the true statements */
fprintf(state->out, "#01 NEQ ;jmp%d JCN2\n", jmpID);
state->pushed -= SIZE_BOOL;
compileAST(state, ifNode->block);
fprintf(state->out, ";loop%d JMP2\n", loopStart);
fprintf(state->out, "@jmp%d\n", jmpID);
}
void compileAST(UCompState *state, UASTNode *node) {
/* STATE nodes hold the expression in node->left, and the next expression in node->right */
while (node) {
@ -424,6 +447,7 @@ void compileAST(UCompState *state, UASTNode *node) {
case NODE_STATE_EXPR: compileExpression(state, node->left); break;
case NODE_STATE_SCOPE: compileScope(state, node); break;
case NODE_STATE_IF: compileIf(state, node); break;
case NODE_STATE_WHILE: compileWhile(state, node); break;
default:
cError(state, "unknown statement node!! [%d]\n", node->type);
}

1
src/ulex.c

@ -12,6 +12,7 @@ UReservedWord reservedWords[] = {
{TOKEN_INT, "int", 3},
{TOKEN_VOID, "void", 4},
{TOKEN_BOOL, "bool", 4},
{TOKEN_WHILE, "while", 5},
{TOKEN_PRINTINT, "prntint", 7},
{TOKEN_IF, "if", 2},
{TOKEN_ELSE, "else", 4},

1
src/ulex.h

@ -7,6 +7,7 @@ typedef enum {
TOKEN_INT,
TOKEN_VOID,
TOKEN_BOOL,
TOKEN_WHILE,
TOKEN_PRINTINT,
TOKEN_IF,
TOKEN_ELSE,

21
src/uparse.c

@ -223,6 +223,7 @@ ParseRule ruleTable[] = {
{NULL, NULL, PREC_NONE}, /* TOKEN_PRINTINT */
{NULL, NULL, PREC_NONE}, /* TOKEN_IF */
{NULL, NULL, PREC_NONE}, /* TOKEN_ELSE */
{NULL, NULL, PREC_NONE}, /* TOKEN_WHILE */
/* literals */
{identifer, NULL, PREC_LITERAL}, /* TOKEN_IDENT */
@ -356,6 +357,23 @@ UASTNode* ifStatement(UParseState *state) {
return (UASTNode*)node;
}
UASTNode* whileStatement(UParseState *state) {
UASTWhileNode *node = (UASTWhileNode*)newBaseNode(state, state->previous, sizeof(UASTWhileNode), NODE_STATE_WHILE, NULL, NULL);
if (!match(state, TOKEN_LEFT_PAREN))
error(state, "Expected '(' to start while conditional!");
/* set the expression */
node->_node.left = expression(state);
if (!match(state, TOKEN_RIGHT_PAREN))
error(state, "Expected ')' to end while conditional!");
/* parse the true block */
node->block = statement(state);
return (UASTNode*)node;
}
UASTNode* expression(UParseState *state) {
UASTNode *node = parsePrecedence(state, NULL, PREC_ASSIGNMENT);
@ -380,6 +398,8 @@ UASTNode* statement(UParseState *state) {
return scopeStatement(state);
} else if (match(state, TOKEN_IF)) {
return ifStatement(state);
} else if (match(state, TOKEN_WHILE)) {
return whileStatement(state);
} else {
UToken tkn = state->previous;
/* no statement match was found, just parse the expression */
@ -406,6 +426,7 @@ void printNode(UASTNode *node) {
case NODE_STATE_SCOPE: printf("SCPE"); break;
case NODE_STATE_DECLARE_VAR: printf("NVAR"); break;
case NODE_STATE_IF: printf("IF"); break;
case NODE_STATE_WHILE: printf("WHIL"); break;
case NODE_VAR: printf("VAR[%d]", ((UASTVarNode*)node)->var); break;
case NODE_STATE_EXPR: printf("EXPR"); break;
default: break;

6
src/uparse.h

@ -30,6 +30,7 @@ typedef enum {
NODE_STATE_DECLARE_FUNC,
NODE_STATE_EXPR,
NODE_STATE_IF,
NODE_STATE_WHILE,
/* scopes are different, node->left holds the statement tree for the scope, node->right holds the next statement */
NODE_STATE_SCOPE,
} UASTNodeType;
@ -89,6 +90,11 @@ typedef struct {
UASTNode *elseBlock;
} UASTIfNode;
typedef struct {
COMMON_NODE_HEADER;
UASTNode *block;
} UASTWhileNode;
typedef struct {
/* lexer related info */
ULexState lstate;

Loading…
Cancel
Save