diff --git a/src/parser/parser.c b/src/parser/parser.c index 68150ae..0752f12 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -1673,6 +1673,145 @@ static inline ResultType(Nothing, charptr) parseCloseParen(SolsParser* parser) { return Error(Nothing, charptr, "Extra closing parentheses"); } +static inline ResultType(Nothing, charptr) parseStruct(SolsParser* parser) { + // Get struct name + SolsNode structNode = ({ + ResultType(SolsNode, charptr) _result = createSolsNode(SNT_STRUCT); + if (_result.error) { + return Error(Nothing, charptr, _result.as.error); + } + _result.as.success; + }); + ResultType(SolsToken, Nothing) nameTok = parserConsume(parser); + if (nameTok.error || nameTok.as.success.type != STT_IDENTIFIER) { + return Error(Nothing, charptr, "Expecting identifier after 'struct'"); + } + structNode.as.idName = nameTok.as.success.as.idName; + ResultType(SolsToken, Nothing) openCurly = parserConsume(parser); + if (openCurly.error || openCurly.as.success.type != STT_OPEN_CURLY) { + return Error(Nothing, charptr, "Expecting '{' after struct identifier"); + } + // Ignore new lines between struct and opening curly brace + for (;;) { + ResultType(SolsToken, Nothing) token = parserPeek(parser, 0); + if (token.error) { + return Error(Nothing, charptr, "Expecting '{' after 'struct'"); + } + if (token.as.success.type == STT_LINE_END) { + parserConsume(parser); + } else { + break; + } + } + for (;;) { + bool done = false; + // Skip newlines between struct values + for (;;) { + ResultType(SolsToken, Nothing) token = parserPeek(parser, 0); + if (token.error) { + return Error(Nothing, charptr, "Expecting '}' to end struct"); + } + if (token.as.success.type == STT_LINE_END) { + parserConsume(parser); + } + else if (token.as.success.type == STT_CLOSE_CURLY) { + done = true; + break; + } else { + break; + } + } + parserConsume(parser); + if (done) break; + + // key = value\n + SolsToken keyTok = ({ + ResultType(SolsToken, Nothing) _result = parserConsume(parser); + if (_result.error) { + return Error(Nothing, charptr, "Expecting struct key"); + } + _result.as.success; + }); + if (keyTok.type != STT_IDENTIFIER) { + return Error(Nothing, charptr, "Expecting struct key"); + } + SolsToken setTok = ({ + ResultType(SolsToken, Nothing) _result = parserConsume(parser); + if (_result.error) { + return Error(Nothing, charptr, "Expecting '=' after struct key"); + } + _result.as.success; + }); + if (setTok.type != STT_OP_SET) { + return Error(Nothing, charptr, "Expecting '=' after struct key"); + } + parserConsume(parser); + SolsTokens tokens = ({ + ResultType(SolsTokens, charptr) _result = createSolsTokens(); + if (_result.error) { + return Error(Nothing, charptr, _result.as.error); + } + _result.as.success; + }); + // Collect tokens for value + if (parserPeek(parser, 0).error) { + return Error(Nothing, charptr, "Expecting value after '='"); + } + for (;;) { + ResultType(SolsToken, Nothing) token = parserPeek(parser, 0); + if (token.error) { + break; + } + if (getPrecedence(&token.as.success) <= STP_NEWLINE) { + break; + } + addTokenToSolsTokens(&tokens, token.as.success); + parserConsume(parser); + } + // Parse value + SolsParser newParser = ({ + ResultType(SolsParser, charptr) _result = createSolsParser(&tokens); + if (_result.error) { + return Error(Nothing, charptr, _result.as.error); + } + _result.as.success; + }); + newParser.currentParent = &newParser.output; + ResultType(Nothing, charptr) parsed = parse(&newParser); + if (parsed.error) { + addToParserErrors(parser, parsed.as.error); + } + // Construct set node + SolsNode setNode = ({ + ResultType(SolsNode, charptr) _result = createSolsNode(SNT_OP_SET); + if (_result.error) { + return Error(Nothing, charptr, _result.as.error); + } + _result.as.success; + }); + addChildToSolsNode(&setNode, ({ + ResultType(SolsNode, charptr) _result = createSolsNode(SNT_IDENTIFIER, keyTok.as.idName); + if (_result.error) { + return Error(Nothing, charptr, _result.as.error); + } + _result.as.success; + })); + addChildToSolsNode(&setNode, newParser.output.children.at[0]); + + // Add set node to struct node + addChildToSolsNode(&structNode, setNode); + + // Consume newline + ResultType(SolsToken, Nothing) newline = parserConsume(parser); + if (newline.error) { + return Error(Nothing, charptr, "Expecting newline after struct value"); + } + } + // Add struct node to parent + addChildToSolsNode(parser->currentParent, structNode); + return Success(Nothing, charptr, {}); +} + ResultType(Nothing, charptr) parse(SolsParser* parser) { parser->currentParent = &parser->output; for (;;) { @@ -1689,6 +1828,7 @@ ResultType(Nothing, charptr) parse(SolsParser* parser) { case STT_KW_GROUND: PARSER_HANDLE(InlineGround); case STT_KW_LAMBDA: PARSER_HANDLE(Lambda); case STT_KW_RETURN: PARSER_HANDLE(Return); + case STT_KW_STRUCT: PARSER_HANDLE(Struct); case STT_KW_USE: PARSER_HANDLE(Use); case STT_KW_DEF: PARSER_HANDLE(Def); case STT_OP_SET: PARSER_HANDLE(Set);