diff --git a/src/main.c b/src/main.c index d5a9f07..ae4ba1e 100644 --- a/src/main.c +++ b/src/main.c @@ -1,11 +1,42 @@ #include // for now -#include "lexer.h" +// #include "lexer.h" +#include "parser.h" + +void tab(noom_uint_t amount) { + amount *= 2; + for (noom_uint_t i = 0; i < amount; i++) { + putchar(' '); + } +} + +void print_node(noomP_Node* node, noom_uint_t depth) { + tab(depth); + printf("{\n"); + + tab(depth+1); + printf("type: %d\n", node->type); + + tab(depth+1); + printf("location: %lld\n", node->source_offset); + + tab(depth+1); + printf("subnodes:\n"); + + for (noom_uint_t i = 0; i < node->subnodec; i++) { + print_node(node->subnodes[i], depth + 1); + } + + tab(depth); + printf("}\n"); +} int main(int argc, char** argv) { // uhh uhhh uhhhhh - const char* code = "local a = 5;"; + const char* code = "local a = 5"; noom_uint_t pos = 0; + printf("LEX OUTPUT:\n"); + noomL_Token token; while (1) { noomL_lex(code, pos, &token); @@ -18,7 +49,16 @@ int main(int argc, char** argv) { if (token.type == NOOML_TOKEN_EOF) break; } - + + // time for parser testing + printf("\nPARSE OUTPUT:\n"); + + noomP_Node *program; + + int success = noomP_parse(code, "shitass", &program); + if (success != 0) return success; + + print_node(program, 0); return 0; } diff --git a/src/parser.c b/src/parser.c index 2b17e9d..f72d150 100644 --- a/src/parser.c +++ b/src/parser.c @@ -4,8 +4,8 @@ int noomP_peek(noomP_Parser* parser, noomL_Token* token) { while (1) { int success = noomL_lex(parser->code, parser->lex_offset, token); - if (!success) return -1; // TODO: proper error propogation and stuff - + if (success != 0) return -1; // TODO: proper error propogation and stuff + if (token->type == NOOML_TOKEN_WHITESPACE) { // peek changes state, but only if it's one of these useless tokens anyway. parser->lex_offset += token->length; @@ -54,7 +54,95 @@ int noomP_addSubnode(noomP_Node* node, noomP_Node* subnode) { return 0; } +noomP_Node* noomP_parseExpression(noomP_Parser* parser) { + noomL_Token token; + noomP_peek(parser, &token); + + if (token.type == NOOML_TOKEN_NUMBER) { + // uhh figure it out, future me! + noomP_skip(parser, &token); + + noomP_Node* numNode = noomP_allocNode(parser); + if (numNode == 0) return 0; + + numNode->type = NOOMP_NODE_NUMBERLITERAL; + numNode->source_offset = token.offset; + + return numNode; + } + + return 0; +} + noomP_Node* noomP_parseStatement(noomP_Parser* parser) { + noomL_Token token; + noomP_peek(parser, &token); + + if (token.type == NOOML_TOKEN_KEYWORD) { + if (noom_streql(parser->code + token.offset, token.length, "local", 5)) { + noomP_skip(parser, &token); + + noomP_Node* localNode = noomP_allocNode(parser); + if (localNode == 0) return 0; // no memory :( + + localNode->source_offset = token.offset; + localNode->type = NOOMP_NODE_LOCALDECLARATION; + + while (1) { + noomP_peek(parser, &token); + + if (token.type != NOOML_TOKEN_IDENTIFIER) return 0; + noomP_skip(parser, &token); + + noomP_Node* varname = noomP_allocNode(parser); + if (varname == 0) return 0; + + varname->type = NOOMP_NODE_VARNAME; + varname->source_offset = token.offset; + + noomP_addSubnode(localNode, varname); + + noomP_peek(parser, &token); + + if (token.type == NOOML_TOKEN_SYMBOL) { + if (noom_streql(parser->code + token.offset, token.length, "=", 1)) { + noomP_skip(parser, &token); + break; + } else if (noom_streql(parser->code + token.offset, token.length, ",", 1)) { + noomP_skip(parser, &token); + } else { + return 0; // unexpected token + } + } else { + return 0; // unexpected token + } + } + + // equals has already been eaten by loop (thank you loop) + + while (1) { + noomP_Node *expr = noomP_parseExpression(parser); + if (expr == 0) return 0; + + noomP_addSubnode(localNode, expr); + + noomP_peek(parser, &token); + + if (token.type == NOOML_TOKEN_SYMBOL) { + if (noom_streql(parser->code + token.offset, token.length, ",", 1)) { + noomP_skip(parser, &token); + } else { + break; + } + } else { + break; + } + } + + return localNode; + } + } + return 0; } @@ -64,7 +152,9 @@ int noomP_parse(const char* code, const char* filename, noomP_Node** outpointer) noomL_Token token; noomP_Node* node = noomP_allocNode(&parser); + if (node == 0) return -1; + node->source_offset = parser.lex_offset; node->type = NOOMP_NODE_PROGRAM; while (1) { @@ -77,8 +167,7 @@ int noomP_parse(const char* code, const char* filename, noomP_Node** outpointer) noomP_addSubnode(node, child); } - node->type = NOOMP_NODE_PROGRAM; - node->subnodec = 0; + *outpointer = node; return 0; } diff --git a/src/parser.h b/src/parser.h index 8bb75ed..f02887a 100644 --- a/src/parser.h +++ b/src/parser.h @@ -3,10 +3,14 @@ typedef enum noomP_NodeType { NOOMP_NODE_PROGRAM, + NOOMP_NODE_VARNAME, + NOOMP_NODE_NUMBERLITERAL, + NOOMP_NODE_LOCALDECLARATION, } noomP_NodeType; - typedef struct noomP_Node { noomP_NodeType type; + + noom_uint_t source_offset; noom_uint_t subnodec; noom_uint_t subnode_cap; @@ -29,6 +33,8 @@ void noomP_skip(noomP_Parser* parser, noomL_Token* token); noomP_Node* noomP_allocNode(noomP_Parser* parser); noomP_Node* noomP_parseStatement(noomP_Parser* parser); +noomP_Node* noomP_parseExpression(noomP_Parser* parser); + int noomP_parse(const char* code, const char* filename, noomP_Node** outpointer); int noomP_initParser(noomP_Parser* parser, const char* code, const char* filename); diff --git a/src/types.h b/src/types.h index 7f4f68c..2ed5b1b 100644 --- a/src/types.h +++ b/src/types.h @@ -1 +1,2 @@ typedef unsigned long long int noom_uint_t; +typedef signed long long int noom_int_t;