forked from NeoFlock/noom
parser: things
This commit is contained in:
281
src/parser.c
281
src/parser.c
@@ -21,6 +21,8 @@ const char *noomP_formatNodeType(noomP_NodeType node_type) {
|
||||
return "repeat loop";
|
||||
case NOOMP_NODE_BLOCK:
|
||||
return "block";
|
||||
case NOOMP_NODE_DOBLOCK:
|
||||
return "do block";
|
||||
case NOOMP_NODE_ATTRIBUTE:
|
||||
return "attribute";
|
||||
case NOOMP_NODE_BREAK:
|
||||
@@ -35,6 +37,10 @@ const char *noomP_formatNodeType(noomP_NodeType node_type) {
|
||||
return "nil literal";
|
||||
case NOOMP_NODE_STRINGLITERAL:
|
||||
return "string literal";
|
||||
case NOOMP_NODE_TABLELITERAL:
|
||||
return "table literal";
|
||||
case NOOMP_NODE_TABLEENTRY:
|
||||
return "table entry";
|
||||
case NOOMP_NODE_UNARYOPERATOR:
|
||||
return "unary operator";
|
||||
case NOOMP_NODE_BINARYOPERATOR:
|
||||
@@ -47,6 +53,14 @@ const char *noomP_formatNodeType(noomP_NodeType node_type) {
|
||||
return "call";
|
||||
case NOOMP_NODE_METHODCALL:
|
||||
return "method call";
|
||||
case NOOMP_NODE_STRINGCALL:
|
||||
return "string call";
|
||||
case NOOMP_NODE_TABLECALL:
|
||||
return "table call";
|
||||
case NOOMP_NODE_STRINGMETHODCALL:
|
||||
return "string method call";
|
||||
case NOOMP_NODE_TABLEMETHODCALL:
|
||||
return "table method call";
|
||||
case NOOMP_NODE_LAMBDAFUNCTIONLITERAL:
|
||||
return "lambda function literal";
|
||||
case NOOMP_NODE_FUNCTIONDECLARATION:
|
||||
@@ -133,6 +147,128 @@ int noomP_addSubnode(noomP_Node* node, noomP_Node* subnode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
noomP_Node* noomP_parseTableLiteral(noomP_Parser* parser) {
|
||||
noomL_Token token;
|
||||
|
||||
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);
|
||||
|
||||
noomP_Node* table = noomP_allocNode(parser);
|
||||
if (table == 0) return 0;
|
||||
|
||||
table->type = NOOMP_NODE_TABLELITERAL;
|
||||
table->source_offset = token.offset;
|
||||
|
||||
// oh boy, oh boy!
|
||||
while (1) {
|
||||
noomP_peek(parser, &token);
|
||||
|
||||
if (token.type == NOOML_TOKEN_SYMBOL && noom_streql(parser->code + token.offset, token.length, "}", 1)) {
|
||||
// noomP_skip(parser, &token);
|
||||
break;
|
||||
}
|
||||
|
||||
noomP_peek(parser, &token);
|
||||
|
||||
if (token.type == NOOML_TOKEN_SYMBOL && noom_streql(parser->code + token.offset, token.length, "[", 1)) {
|
||||
noomP_skip(parser, &token);
|
||||
noom_uint_t bloc = token.offset;
|
||||
|
||||
noomP_Node* idx = noomP_parseExpression(parser);
|
||||
if (idx == 0) return 0;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
noomP_Node* val = noomP_parseExpression(parser);
|
||||
if (val == 0) return 0;
|
||||
|
||||
noomP_Node* entry = noomP_allocNode(parser);
|
||||
if (entry == 0) return 0;
|
||||
|
||||
entry->type = NOOMP_NODE_TABLEENTRY;
|
||||
entry->source_offset = bloc;
|
||||
|
||||
noomP_addSubnode(entry, idx);
|
||||
noomP_addSubnode(entry, val);
|
||||
|
||||
noomP_addSubnode(table, entry);
|
||||
} else {
|
||||
int exprcheck = 1;
|
||||
if (token.type == NOOML_TOKEN_IDENTIFIER) { // maybe `Name = ...`
|
||||
noom_uint_t opos = parser->lex_offset;
|
||||
noomP_skip(parser, &token);
|
||||
|
||||
noomP_peek(parser, &token);
|
||||
if (token.type == NOOML_TOKEN_SYMBOL && noom_streql(parser->code + token.offset, token.length, "=", 1)) {
|
||||
noomP_skip(parser, &token);
|
||||
|
||||
// conveniently opos is also the thingamajig
|
||||
noomP_Node* val = noomP_parseExpression(parser);
|
||||
if (val == 0) return 0;
|
||||
|
||||
noomP_Node* idx = noomP_allocNode(parser);
|
||||
if (idx == 0) return 0;
|
||||
|
||||
idx->type = NOOMP_NODE_FIELDNAME;
|
||||
idx->source_offset = opos;
|
||||
|
||||
noomP_Node* entry = noomP_allocNode(parser);
|
||||
if (entry == 0) return 0;
|
||||
|
||||
entry->type = NOOMP_NODE_TABLEENTRY;
|
||||
entry->source_offset = opos;
|
||||
|
||||
noomP_addSubnode(entry, idx);
|
||||
noomP_addSubnode(entry, val);
|
||||
|
||||
noomP_addSubnode(table, entry);
|
||||
exprcheck = 0;
|
||||
} else {
|
||||
/// fuuuuuuuu
|
||||
parser->lex_offset = opos; // evil hack!!1!!
|
||||
}
|
||||
}
|
||||
if (exprcheck) {
|
||||
noomP_Node* val = noomP_parseExpression(parser);
|
||||
if (val == 0) return 0;
|
||||
|
||||
// ehhhh this doesn't need an entry; it's not my problem anyway.
|
||||
// to lex: sorry, not sorry
|
||||
noomP_addSubnode(table, val);
|
||||
}
|
||||
}
|
||||
|
||||
// check for ,
|
||||
noomP_peek(parser, &token);
|
||||
if (token.type == NOOML_TOKEN_SYMBOL && noom_streql(parser->code + token.offset, token.length, ",", 1)) {
|
||||
noomP_skip(parser, &token);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode) {
|
||||
noomP_Node* node = snode;
|
||||
noomL_Token token;
|
||||
@@ -226,6 +362,20 @@ noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode
|
||||
|
||||
noomP_skip(parser, &token);
|
||||
|
||||
node = new;
|
||||
} else if (noom_streql(parser->code + token.offset, token.length, "{", 1)) { // table call
|
||||
noomP_Node* new = noomP_allocNode(parser);
|
||||
if (new == 0) return 0;
|
||||
|
||||
new->type = NOOMP_NODE_TABLECALL;
|
||||
new->source_offset = token.offset;
|
||||
|
||||
noomP_Node* table = noomP_parseTableLiteral(parser);
|
||||
if (table == 0) return 0;
|
||||
|
||||
noomP_addSubnode(new, node);
|
||||
noomP_addSubnode(new, table);
|
||||
|
||||
node = new;
|
||||
} else if (noom_streql(parser->code + token.offset, token.length, ":", 1)) { // method call
|
||||
noomP_skip(parser, &token);
|
||||
@@ -238,6 +388,7 @@ noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode
|
||||
noomP_Node* new = noomP_allocNode(parser);
|
||||
if (new == 0) return 0;
|
||||
|
||||
new->type = 0;
|
||||
new->type = NOOMP_NODE_METHODCALL;
|
||||
new->source_offset = sym_loc;
|
||||
|
||||
@@ -251,39 +402,71 @@ noomP_Node* noomP_parseComplexExpression(noomP_Parser* parser, noomP_Node* snode
|
||||
noomP_addSubnode(new, method_node);
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
if (token.type == NOOML_TOKEN_SYMBOL && noom_streql(parser->code + token.offset, token.length, "(", 1)) {
|
||||
noomP_skip(parser, &token);
|
||||
// new->type = NOOMP_NODE_METHODCALL;
|
||||
|
||||
noomP_addSubnode(new, expr);
|
||||
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_peek(parser, &token);
|
||||
if (token.type != NOOML_TOKEN_SYMBOL || (!noom_streql(parser->code + token.offset, token.length, ",", 1))) {
|
||||
break;
|
||||
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);
|
||||
}
|
||||
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);
|
||||
} else if (token.type == NOOML_TOKEN_SYMBOL && noom_streql(parser->code + token.offset, token.length, "{", 1)) {
|
||||
noomP_Node* table = noomP_parseTableLiteral(parser);
|
||||
if (table == 0) return 0;
|
||||
|
||||
// new->type = NOOMP_NODE_TABLEMETHODCALL;
|
||||
|
||||
noomP_addSubnode(new, table);
|
||||
} else if (token.type == NOOML_TOKEN_STRING) {
|
||||
noomP_skip(parser, &token);
|
||||
new->type = NOOMP_NODE_STRINGMETHODCALL;
|
||||
|
||||
noomP_Node* str = noomP_allocNode(parser);
|
||||
if (str == 0) return 0;
|
||||
str->type = NOOMP_NODE_STRINGLITERAL;
|
||||
str->source_offset = token.offset;
|
||||
|
||||
noomP_addSubnode(new, str);
|
||||
} else {
|
||||
return 0; // unexpected :(
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return node; // done
|
||||
}
|
||||
} else if (token.type == NOOML_TOKEN_STRING) {
|
||||
noomP_skip(parser, &token);
|
||||
// string call
|
||||
noomP_Node* new = noomP_allocNode(parser);
|
||||
if (new == 0) return 0;
|
||||
|
||||
new->type = NOOMP_NODE_STRINGCALL;
|
||||
new->source_offset = token.offset;
|
||||
|
||||
noomP_addSubnode(new, node);
|
||||
|
||||
node = new;
|
||||
} else {
|
||||
return node; // done
|
||||
}
|
||||
@@ -409,6 +592,11 @@ noomP_Node* noomP_parseRawExpression(noomP_Parser* parser) {
|
||||
// buttt we're not done YET! it could still go :dsg().dsdh():dsh()
|
||||
|
||||
return noomP_parseComplexExpression(parser, paren); // thank you for being a function :heart:
|
||||
} else if (noom_streql(parser->code + token.offset, token.length, "{", 1)) {
|
||||
noomP_Node* table = noomP_parseTableLiteral(parser);
|
||||
if (table == 0) return 0;
|
||||
|
||||
return table;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,6 +622,10 @@ int noomP_infixOperatorBP(noomP_Parser* parser, noomL_Token* token, noom_uint_t*
|
||||
*a = 110;
|
||||
*b = 120;
|
||||
return 1;
|
||||
} else if (parser->version >= NOOM_VERSION_53 && noom_streql(parser->code + token->offset, token->length, "//", 2)) {
|
||||
*a = 110;
|
||||
*b = 120;
|
||||
return 1;
|
||||
} else if (noom_streql(parser->code + token->offset, token->length, "%", 1)) {
|
||||
*a = 110;
|
||||
*b = 120;
|
||||
@@ -449,6 +641,28 @@ int noomP_infixOperatorBP(noomP_Parser* parser, noomL_Token* token, noom_uint_t*
|
||||
*b = 70; // right ass.
|
||||
return 1;
|
||||
|
||||
} else if (parser->version >= NOOM_VERSION_53 && noom_streql(parser->code + token->offset, token->length, ">>", 2)) {
|
||||
*a = 68;
|
||||
*b = 69;
|
||||
return 1;
|
||||
} else if (parser->version >= NOOM_VERSION_53 && noom_streql(parser->code + token->offset, token->length, "<<", 2)) {
|
||||
*a = 68;
|
||||
*b = 69;
|
||||
return 1;
|
||||
|
||||
} else if (parser->version >= NOOM_VERSION_53 && noom_streql(parser->code + token->offset, token->length, "&", 1)) {
|
||||
*a = 66;
|
||||
*b = 67;
|
||||
return 1;
|
||||
} else if (parser->version >= NOOM_VERSION_53 && noom_streql(parser->code + token->offset, token->length, "~", 1)) {
|
||||
*a = 64;
|
||||
*b = 65;
|
||||
return 1;
|
||||
} else if (parser->version >= NOOM_VERSION_53 && noom_streql(parser->code + token->offset, token->length, "|", 1)) {
|
||||
*a = 62;
|
||||
*b = 63;
|
||||
return 1;
|
||||
|
||||
|
||||
// oh boy.
|
||||
} else if (noom_streql(parser->code + token->offset, token->length, "<", 1)) {
|
||||
@@ -497,7 +711,7 @@ noom_uint_t noomP_prefixOperatorBP(noomP_Parser* parser, noomL_Token* token) { /
|
||||
return 125;
|
||||
} else if (noom_streql(parser->code + token->offset, token->length, "#", 1)) {
|
||||
return 125;
|
||||
} else if (noom_streql(parser->code + token->offset, token->length, "~", 1)) {
|
||||
} else if (parser->version >= NOOM_VERSION_53 && noom_streql(parser->code + token->offset, token->length, "~", 1)) {
|
||||
return 125;
|
||||
}
|
||||
} else if (token->type == NOOML_TOKEN_KEYWORD) {
|
||||
@@ -1285,6 +1499,27 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) {
|
||||
noomP_addSubnode(repeat, condition);
|
||||
|
||||
return repeat;
|
||||
} else if (noom_streql(parser->code + token.offset, token.length, "do", 2)) {
|
||||
noomP_skip(parser, &token);
|
||||
|
||||
noomP_Node* doblock = noomP_allocNode(parser);
|
||||
if (doblock == 0) return 0;
|
||||
|
||||
doblock->type = NOOMP_NODE_DOBLOCK;
|
||||
doblock->source_offset = token.offset;
|
||||
|
||||
noomP_Node* block = noomP_parseBlock(parser);
|
||||
if (block == 0) return 0;
|
||||
|
||||
noomP_addSubnode(doblock, block);
|
||||
|
||||
noomP_peek(parser, &token);
|
||||
if (token.type != NOOML_TOKEN_KEYWORD || !noom_streql(parser->code + token.offset, token.length, "end", 3)) {
|
||||
return 0;
|
||||
}
|
||||
noomP_skip(parser, &token);
|
||||
|
||||
return doblock;
|
||||
}
|
||||
} else if (token.type == NOOML_TOKEN_SYMBOL) {
|
||||
if (noom_streql(parser->code + token.offset, token.length, "::", 2)) { // symbol doesn't exist on wrong versions
|
||||
@@ -1402,7 +1637,7 @@ noomP_Node* noomP_parseRawStatement(noomP_Parser* parser) {
|
||||
}
|
||||
|
||||
return assignment;
|
||||
} else if (base->type == NOOMP_NODE_CALL || base->type == NOOMP_NODE_METHODCALL) {
|
||||
} else if (base->type == NOOMP_NODE_CALL || base->type == NOOMP_NODE_METHODCALL || base->type == NOOMP_NODE_STRINGCALL || base->type == NOOMP_NODE_STRINGMETHODCALL || base->type == NOOMP_NODE_TABLECALL || base->type == NOOMP_NODE_TABLEMETHODCALL) {
|
||||
// this expression is now a statement.
|
||||
return base; // no need to eat any more.
|
||||
} else {
|
||||
|
||||
10
src/parser.h
10
src/parser.h
@@ -13,6 +13,7 @@ typedef enum noomP_NodeType {
|
||||
NOOMP_NODE_FORLOOPIN,
|
||||
NOOMP_NODE_REPEAT,
|
||||
NOOMP_NODE_BLOCK,
|
||||
NOOMP_NODE_DOBLOCK, // maybe just use BLOCK for this?
|
||||
|
||||
NOOMP_NODE_ATTRIBUTE,
|
||||
|
||||
@@ -24,6 +25,9 @@ typedef enum noomP_NodeType {
|
||||
NOOMP_NODE_NILLITERAL,
|
||||
NOOMP_NODE_STRINGLITERAL,
|
||||
|
||||
NOOMP_NODE_TABLELITERAL,
|
||||
NOOMP_NODE_TABLEENTRY,
|
||||
|
||||
NOOMP_NODE_UNARYOPERATOR,
|
||||
NOOMP_NODE_BINARYOPERATOR,
|
||||
|
||||
@@ -32,6 +36,12 @@ typedef enum noomP_NodeType {
|
||||
NOOMP_NODE_CALL,
|
||||
NOOMP_NODE_METHODCALL,
|
||||
|
||||
NOOMP_NODE_STRINGCALL,
|
||||
NOOMP_NODE_TABLECALL,
|
||||
|
||||
NOOMP_NODE_STRINGMETHODCALL,
|
||||
NOOMP_NODE_TABLEMETHODCALL,
|
||||
|
||||
NOOMP_NODE_LAMBDAFUNCTIONLITERAL,
|
||||
NOOMP_NODE_FUNCTIONDECLARATION,
|
||||
NOOMP_NODE_LOCALFUNCTIONDECLARATION,
|
||||
|
||||
Reference in New Issue
Block a user