diff --git a/src/main.c b/src/main.c index 1171d27..679778a 100644 --- a/src/main.c +++ b/src/main.c @@ -33,7 +33,7 @@ void print_node(noomP_Node* node, noom_uint_t depth) { int main(int argc, char** argv) { // uhh uhhh uhhhhh - const char* code = "local a = [=[Hello, world!]]lol]==]]]=]"; + const char* code = "local a = a.b[\"hi\"](5, 2)"; noom_uint_t pos = 0; printf("LEX OUTPUT:\n"); diff --git a/src/parser.c b/src/parser.c index a08f926..71f64f2 100644 --- a/src/parser.c +++ b/src/parser.c @@ -31,6 +31,14 @@ const char *noomP_formatNodeType(noomP_NodeType node_type) { return "unary operator"; case NOOMP_NODE_BINARYOPERATOR: return "binary operator"; + case NOOMP_NODE_GETFIELD: + return "get field"; + case NOOMP_NODE_INDEX: + return "index"; + case NOOMP_NODE_CALL: + return "call"; + case NOOMP_NODE_FIELDNAME: + return "fieldname"; default: return "unknown"; } @@ -89,6 +97,110 @@ int noomP_addSubnode(noomP_Node* node, noomP_Node* subnode) { return 0; } +noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode) { + noomP_Node* node = snode; + noomL_Token token; + + while (1) { + noomP_peek(parser, &token); + + if (token.type == NOOML_TOKEN_SYMBOL) { + if (noom_streql(parser->code + token.offset, token.length, ".", 1)) { // field + noomP_skip(parser, &token); // skip the . + noom_uint_t dotLoc = token.offset; + + noomP_peek(parser, &token); + if (token.type != NOOML_TOKEN_IDENTIFIER) return 0; + noomP_skip(parser, &token); // skip the field name + + noomP_Node* new = noomP_allocNode(parser); + if (new == 0) return 0; + + new->source_offset = dotLoc; + new->type = NOOMP_NODE_GETFIELD; + + noomP_Node* fname = noomP_allocNode(parser); + if (new == 0) return 0; + + fname->source_offset = token.offset; + fname->type = NOOMP_NODE_FIELDNAME; + + noomP_addSubnode(new, node); + noomP_addSubnode(new, fname); + + node = new; + } else if (noom_streql(parser->code + token.offset, token.length, "[", 1)) { // index + noomP_skip(parser, &token); // skip the [ + noom_uint_t brackLoc = token.offset; + + noomP_Node* expr = noomP_parseExpression(parser); + if (expr == 0) return 0; + + noomP_peek(parser, &token); // look for ] + if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, "]", 1))) { + // damn it :( + return 0; + } + noomP_skip(parser, &token); // skip ] + + noomP_Node* new = noomP_allocNode(parser); + if (new == 0) return 0; + + new->type = NOOMP_NODE_INDEX; + new->source_offset = brackLoc; + + noomP_addSubnode(new, node); + noomP_addSubnode(new, expr); + + node = new; + } else if (noom_streql(parser->code + token.offset, token.length, "(", 1)) { + noomP_skip(parser, &token); // bye ( + noom_uint_t parenLoc = token.offset; + + noomP_Node* new = noomP_allocNode(parser); + if (new == 0) return 0; + + noomP_addSubnode(new, node); + + new->source_offset = parenLoc; + new->type = NOOMP_NODE_CALL; + + noomP_peek(parser, &token); + + if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, ")", 1))) { + while (1) { + noomP_Node* expr = noomP_parseExpression(parser); + if (expr == 0) return 0; + + noomP_addSubnode(new, expr); + + noomP_peek(parser, &token); + if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, ",", 1))) { + break; + } + noomP_skip(parser, &token); + } + } + + // check for ) + noomP_peek(parser, &token); + if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, ")", 1))) { + return 0; + } + + noomP_skip(parser, &token); + + node = new; + + } else { // TODO: method call + return node; // done + } + } else { + return node; // done + } + } +} + noomP_Node* noomP_parseRawExpression(noomP_Parser* parser) { noomL_Token token; noomP_peek(parser, &token); @@ -122,6 +234,9 @@ noomP_Node* noomP_parseRawExpression(noomP_Parser* parser) { varNode->type = NOOMP_NODE_VARIABLE; varNode->source_offset = token.offset; + varNode = noomP_parseComplexExpression(parser, varNode); // complexify + if (varNode == 0) return 0; + return varNode; } else if (token.type == NOOML_TOKEN_KEYWORD) { if (noom_streql(parser->code + token.offset, token.length, "true", 4)) { diff --git a/src/parser.h b/src/parser.h index d430749..e52b8d5 100644 --- a/src/parser.h +++ b/src/parser.h @@ -22,6 +22,12 @@ typedef enum noomP_NodeType { NOOMP_NODE_UNARYOPERATOR, NOOMP_NODE_BINARYOPERATOR, + NOOMP_NODE_GETFIELD, + NOOMP_NODE_INDEX, + NOOMP_NODE_CALL, + + NOOMP_NODE_FIELDNAME, + NOOMP_NODE_NCOUNT, } noomP_NodeType;