diff --git a/lib/include/artichoke/Parser/AST/Common.hpp b/lib/include/artichoke/Parser/AST/Common.hpp index 1749405..8fbd275 100644 --- a/lib/include/artichoke/Parser/AST/Common.hpp +++ b/lib/include/artichoke/Parser/AST/Common.hpp @@ -104,6 +104,7 @@ namespace arti::lang::ast { PtrToSlice, SliceToPtr, Reflect, + ObjectLiteral, }; enum class CompoundAssignOperator { diff --git a/lib/include/artichoke/Parser/AST/Expressions.hpp b/lib/include/artichoke/Parser/AST/Expressions.hpp index e24679f..4fcfb1f 100644 --- a/lib/include/artichoke/Parser/AST/Expressions.hpp +++ b/lib/include/artichoke/Parser/AST/Expressions.hpp @@ -76,8 +76,7 @@ namespace arti::lang::ast { FloatLtrlNode, IntegerLtrlNode, BooleanLtrlNode, - StructLtrlNode, - SliceLtrlNode, + ObjectLtrlNode, IdentifierExprNode, PrefixExprNode, InfixExprNode, @@ -207,30 +206,31 @@ namespace arti::lang::ast { ExpressionNode object; }; - struct nodes::StructLiteralNamedFieldInit { + struct nodes::ObjectLiteralNamedFieldInit { SourceLocation location; String fieldName; ExpressionNode fieldValue; }; - struct nodes::StructLiteralPositionalInit { + struct nodes::ObjectLiteralNamedInitializer { SourceLocation location; - ExpressionNode fieldValue; + Vector fields; }; - struct nodes::StructLiteralNamedInitializer { + struct nodes::ObjectLiteralPositionalInitializer { SourceLocation location; - Vector fields; + Vector fields; }; - struct nodes::StructLiteralPositionalInitializer { + struct nodes::ObjectLiteral { SourceLocation location; - Vector fields; - }; + ExpressionNode type; + Optional initializer; + }; } // namespace arti::lang::ast diff --git a/lib/include/artichoke/Parser/AST/Literals.hpp b/lib/include/artichoke/Parser/AST/Literals.hpp index e6871b7..74a6aef 100644 --- a/lib/include/artichoke/Parser/AST/Literals.hpp +++ b/lib/include/artichoke/Parser/AST/Literals.hpp @@ -37,14 +37,12 @@ namespace arti::lang::ast { struct FloatLiteral; struct IntegerLiteral; struct BooleanLiteral; - struct StructLiteral; - struct SliceLiteral; + struct ObjectLiteral; /* Helper declaration node types */ - struct StructLiteralNamedFieldInit; - struct StructLiteralPositionalInit; - struct StructLiteralNamedInitializer; - struct StructLiteralPositionalInitializer; + struct ObjectLiteralNamedFieldInit; + struct ObjectLiteralNamedInitializer; + struct ObjectLiteralPositionalInitializer; } // namespace nodes @@ -55,22 +53,19 @@ namespace arti::lang::ast { using FloatLtrlNode = Ptr; using IntegerLtrlNode = Ptr; using BooleanLtrlNode = Ptr; - using StructLtrlNode = Ptr; - using SliceLtrlNode = Ptr; + using ObjectLtrlNode = Ptr; - using StructLtrlNamedFieldInitNode = - Ptr; - using StructLtrlPositionalInitNode = - Ptr; - using StructLtrlNamedInitializerNode = - Ptr; - using StructLtrlPositionalInitializerNode = - Ptr; + using ObjectLtrlNamedFieldInitNode = + Ptr; + using ObjectLtrlNamedInitializerNode = + Ptr; + using ObjectLtrlPositionalInitializerNode = + Ptr; /* Variant nodes */ - using StructLtrlInitializerNode = Variant< - StructLtrlNamedInitializerNode, - StructLtrlPositionalInitializerNode + using ObjectLtrlInitializerNode = Variant< + ObjectLtrlNamedInitializerNode, + ObjectLtrlPositionalInitializerNode >; /* Node definitions */ @@ -109,20 +104,6 @@ namespace arti::lang::ast { Boolean value; }; - struct nodes::StructLiteral { - SourceLocation location; - - TypeNode type; - Optional initializer; - }; - - struct nodes::SliceLiteral { - SourceLocation location; - - TypeNode type; - Optional initializer; - }; - /* INFO: Helper types definitions are on Expressions.hpp * due to dependency in ExpressionNode variant. */ diff --git a/lib/src/Parser/AST/toDot.cpp b/lib/src/Parser/AST/toDot.cpp index 461e756..dccdbd3 100644 --- a/lib/src/Parser/AST/toDot.cpp +++ b/lib/src/Parser/AST/toDot.cpp @@ -178,13 +178,11 @@ namespace arti::lang::ast { std::string emit(const FloatLtrlNode &, GraphBuilder &); std::string emit(const IntegerLtrlNode &, GraphBuilder &); std::string emit(const BooleanLtrlNode &, GraphBuilder &); - std::string emit(const StructLtrlNode &, GraphBuilder &); - std::string emit(const SliceLtrlNode &, GraphBuilder &); - std::string emit(const StructLtrlNamedFieldInitNode &, GraphBuilder &); - std::string emit(const StructLtrlPositionalInitNode &, GraphBuilder &); - std::string emit(const StructLtrlNamedInitializerNode &, GraphBuilder &); - std::string emit(const StructLtrlPositionalInitializerNode&, GraphBuilder&); - std::string emit(const StructLtrlInitializerNode &, GraphBuilder &); + std::string emit(const ObjectLtrlNode &, GraphBuilder &); + std::string emit(const ObjectLtrlNamedFieldInitNode &, GraphBuilder &); + std::string emit(const ObjectLtrlNamedInitializerNode &, GraphBuilder &); + std::string emit(const ObjectLtrlPositionalInitializerNode&, GraphBuilder&); + std::string emit(const ObjectLtrlInitializerNode &, GraphBuilder &); std::string emit(const IdentifierExprNode &, GraphBuilder &); std::string emit(const PrefixExprNode &, GraphBuilder &); std::string emit(const InfixExprNode &, GraphBuilder &); @@ -555,19 +553,8 @@ namespace arti::lang::ast { } // Struct/Slice literals and initializers - std::string emit(const StructLtrlNode &node, GraphBuilder &g) { - auto id = g.makeNode("StructLiteral"); - auto t = emit(node->type, g); - g.addEdge(id, t, "Type"); - if (node->initializer) { - auto cid = emit(*node->initializer, g); - g.addEdge(id, cid, "Elements"); - } - return id; - } - - std::string emit(const SliceLtrlNode &node, GraphBuilder &g) { - auto id = g.makeNode("SliceLiteral"); + std::string emit(const ObjectLtrlNode &node, GraphBuilder &g) { + auto id = g.makeNode("ObjectLiteral"); auto t = emit(node->type, g); g.addEdge(id, t, "Type"); if (node->initializer) { @@ -578,7 +565,7 @@ namespace arti::lang::ast { } std::string - emit(const StructLtrlNamedFieldInitNode &node, GraphBuilder &g) { + emit(const ObjectLtrlNamedFieldInitNode &node, GraphBuilder &g) { auto id = g.makeNode("FieldInitializer"); auto leaf = makeLeaf(g, node->fieldName); g.addEdge(id, leaf, "Field"); @@ -588,15 +575,7 @@ namespace arti::lang::ast { } std::string - emit(const StructLtrlPositionalInitNode &node, GraphBuilder &g) { - auto id = g.makeNode("PositionalInitializer"); - auto val = emit(node->fieldValue, g); - g.addEdge(id, val, "Value"); - return id; - } - - std::string - emit(const StructLtrlNamedInitializerNode &node, GraphBuilder &g) { + emit(const ObjectLtrlNamedInitializerNode &node, GraphBuilder &g) { auto id = g.makeNode("InitializerList"); if (! node->fields.empty()) { emitGroupVec(g, id, "Elements", node->fields, [&](const auto &f) { @@ -607,7 +586,7 @@ namespace arti::lang::ast { } std::string - emit(const StructLtrlPositionalInitializerNode &node, GraphBuilder &g) { + emit(const ObjectLtrlPositionalInitializerNode &node, GraphBuilder &g) { auto id = g.makeNode("InitializerList"); if (! node->fields.empty()) { emitGroupVec(g, id, "Elements", node->fields, [&](const auto &f) { @@ -617,10 +596,10 @@ namespace arti::lang::ast { return id; } - std::string emit(const StructLtrlInitializerNode &node, GraphBuilder &g) { + std::string emit(const ObjectLtrlInitializerNode &node, GraphBuilder &g) { auto visitor = OverloadSet{ - [&g](const StructLtrlNamedInitializerNode &n) { return emit(n, g); }, - [&g](const StructLtrlPositionalInitializerNode &n) { + [&g](const ObjectLtrlNamedInitializerNode &n) { return emit(n, g); }, + [&g](const ObjectLtrlPositionalInitializerNode &n) { return emit(n, g); }, }; @@ -770,8 +749,7 @@ namespace arti::lang::ast { [&g](const FloatLtrlNode &n) { return emit(n, g); }, [&g](const IntegerLtrlNode &n) { return emit(n, g); }, [&g](const BooleanLtrlNode &n) { return emit(n, g); }, - [&g](const StructLtrlNode &n) { return emit(n, g); }, - [&g](const SliceLtrlNode &n) { return emit(n, g); }, + [&g](const ObjectLtrlNode &n) { return emit(n, g); }, [&g](const IdentifierExprNode &n) { return emit(n, g); }, [&g](const PrefixExprNode &n) { return emit(n, g); }, [&g](const InfixExprNode &n) { return emit(n, g); }, diff --git a/lib/src/Parser/AST/toString.cpp b/lib/src/Parser/AST/toString.cpp index 6ec8b31..d39020f 100644 --- a/lib/src/Parser/AST/toString.cpp +++ b/lib/src/Parser/AST/toString.cpp @@ -53,13 +53,11 @@ namespace arti::lang::ast { std::string toString(const FloatLtrlNode &, std::string); std::string toString(const IntegerLtrlNode &, std::string); std::string toString(const BooleanLtrlNode &, std::string); - std::string toString(const StructLtrlNode &, std::string); - std::string toString(const SliceLtrlNode &, std::string); - std::string toString(const StructLtrlNamedFieldInitNode &, std::string); - std::string toString(const StructLtrlPositionalInitNode &, std::string); - std::string toString(const StructLtrlNamedInitializerNode &, std::string); - std::string toString(const StructLtrlPositionalInitializerNode&, std::string); - std::string toString(const StructLtrlInitializerNode &, std::string); + std::string toString(const ObjectLtrlNode &, std::string); + std::string toString(const ObjectLtrlNamedFieldInitNode &, std::string); + std::string toString(const ObjectLtrlNamedInitializerNode &, std::string); + std::string toString(const ObjectLtrlPositionalInitializerNode&, std::string); + std::string toString(const ObjectLtrlInitializerNode &, std::string); std::string toString(const IdentifierExprNode &, std::string); std::string toString(const PrefixExprNode &, std::string); std::string toString(const InfixExprNode &, std::string); @@ -643,30 +641,9 @@ namespace arti::lang::ast { return std::format("BooleanLiteral {}", node->value ? "true" : "false"); } - std::string toString(const StructLtrlNode &node, std::string prefix) { + std::string toString(const ObjectLtrlNode &node, std::string prefix) { std::stringstream ss; - ss << "StructLiteral"; - int total = 1; - if (node->initializer) { - ++total; - } - int emitted = 0; - appendGroupOne(ss, prefix, "Type", node->type, ++emitted == total); - if (node->initializer) { - appendGroupOne( - ss, - prefix, - "Elements", - *node->initializer, - ++emitted == total - ); - } - return ss.str(); - } - - std::string toString(const SliceLtrlNode &node, std::string prefix) { - std::stringstream ss; - ss << "SliceLiteral"; + ss << "ObjectLiteral"; int total = 1; if (node->initializer) { ++total; @@ -686,7 +663,7 @@ namespace arti::lang::ast { } std::string - toString(const StructLtrlNamedFieldInitNode &node, std::string prefix) { + toString(const ObjectLtrlNamedFieldInitNode &node, std::string prefix) { std::stringstream ss; ss << "FieldInitializer"; appendGroupLeaf(ss, prefix, "Field", node->fieldName, false); @@ -695,15 +672,7 @@ namespace arti::lang::ast { } std::string - toString(const StructLtrlPositionalInitNode &node, std::string prefix) { - std::stringstream ss; - ss << "PositionalInitializer"; - appendGroupOne(ss, prefix, "Value", node->fieldValue, true); - return ss.str(); - } - - std::string - toString(const StructLtrlNamedInitializerNode &node, std::string prefix) { + toString(const ObjectLtrlNamedInitializerNode &node, std::string prefix) { std::stringstream ss; ss << "InitializerList"; appendGroupVec(ss, prefix, "Elements", node->fields, true); @@ -711,7 +680,7 @@ namespace arti::lang::ast { } std::string toString( - const StructLtrlPositionalInitializerNode &node, + const ObjectLtrlPositionalInitializerNode &node, std::string prefix ) { std::stringstream ss; @@ -721,12 +690,12 @@ namespace arti::lang::ast { } std::string - toString(const StructLtrlInitializerNode &node, std::string padding) { + toString(const ObjectLtrlInitializerNode &node, std::string padding) { auto visitor = OverloadSet{ - [padding](const StructLtrlNamedInitializerNode &node) -> std::string { + [padding](const ObjectLtrlNamedInitializerNode &node) -> std::string { return toString(node, padding); }, - [padding](const StructLtrlPositionalInitializerNode &node) + [padding](const ObjectLtrlPositionalInitializerNode &node) -> std::string { return toString(node, padding); }, }; @@ -956,10 +925,7 @@ namespace arti::lang::ast { [padding](const BooleanLtrlNode &node) -> std::string { return toString(node, padding); }, - [padding](const StructLtrlNode &node) -> std::string { - return toString(node, padding); - }, - [padding](const SliceLtrlNode &node) -> std::string { + [padding](const ObjectLtrlNode &node) -> std::string { return toString(node, padding); }, [padding](const IdentifierExprNode &node) -> std::string { diff --git a/lib/src/Parser/Declarations.cpp b/lib/src/Parser/Declarations.cpp index fa33f69..ba20620 100644 --- a/lib/src/Parser/Declarations.cpp +++ b/lib/src/Parser/Declarations.cpp @@ -504,6 +504,13 @@ namespace arti::lang { } } } + + if (auto close = match(TokenV::opRSquirly); ! close) { + return Unexpected<>{ std::move(close).error() }; + } + else if (close.value()) { + keepParsing = false; + } } return membersList; @@ -585,6 +592,13 @@ namespace arti::lang { } } } + + if (auto close = match(TokenV::opRSquirly); ! close) { + return Unexpected<>{ std::move(close).error() }; + } + else if (close.value()) { + keepParsing = false; + } } return membersList; diff --git a/lib/src/Parser/Expressions.cpp b/lib/src/Parser/Expressions.cpp index a55fae1..61c6848 100644 --- a/lib/src/Parser/Expressions.cpp +++ b/lib/src/Parser/Expressions.cpp @@ -449,13 +449,6 @@ namespace arti::lang { } } } - - if (auto close = match(TokenV::opRParen); ! close) { - return Unexpected<>{ std::move(close).error() }; - } - else if (close.value()) { - stillParams = false; - } } if (auto close = consume(TokenV::opRParen, "')'"); ! close) { @@ -466,6 +459,155 @@ namespace arti::lang { node = std::move(newNode); } + else if (op == ast::PostfixOperator::ObjectLiteral) { + auto newNode = ast::MakeNode(); + + newNode->location = { + .line = peekToken->line, + .column = peekToken->column + }; + + bool stillParams = true; + + if (auto close = match(TokenV::opRSquirly); ! close) { + return Unexpected<>{ std::move(close).error() }; + } + else if (close.value()) { + stillParams = false; + } + + if (auto isNamed = match(TokenV::opDot); ! isNamed) { + return Unexpected<>{ std::move(isNamed).error() }; + } + else if (isNamed.value()) { + auto initializerNode = + ast::MakeNode(); + + initializerNode->location = newNode->location; + + while (stillParams) { + auto currLocation = ast::SourceLocation{}; + + if (auto dot = consume(TokenV::opDot, "'.'"); ! dot) { + return Unexpected<>{ std::move(dot).error() }; + } + else { + currLocation.line = dot->line; + currLocation.column = dot->column; + } + + if (auto ident = consume(TokenV::tkIdentifier, "identifier"); + ! ident) { + return Unexpected<>{ std::move(ident).error() }; + } + else { + if (auto eq = consume(TokenV::opAssign, "'='"); ! eq) { + return Unexpected<>{ std::move(eq).error() }; + } + + auto value = parseExpression(); + + if (! value) { + return Unexpected<>{ std::move(value).error() }; + } + + auto init = ast::MakeNode(); + + init->location = currLocation; + init->fieldName = ident->strValue; + init->fieldValue = std::move(value).value(); + + initializerNode->fields.push_back(std::move(init)); + + if (auto comma = matchAndConsume(TokenV::opComma); ! comma) { + return Unexpected{ std::move(comma).error() }; + } + else if (! comma.value()) { + if (auto ntok = tokenizer.peek(); ! ntok) { + return Unexpected{ std::move(ntok).error() }; + } + else { + if (ntok->value != TokenV::opRSquirly) { + return langException( + ntok->line, + ntok->column, + toString(*ntok), + "',' or '}'" + ); + } + else { + stillParams = false; + } + } + } + } + + if (auto close = match(TokenV::opRSquirly); ! close) { + return Unexpected<>{ std::move(close).error() }; + } + else if (close.value()) { + stillParams = false; + } + } + + newNode->initializer = std::move(initializerNode); + } + else { + auto initializerNode = + ast::MakeNode(); + + initializerNode->location = newNode->location; + + while (stillParams) { + auto arg = parseExpression(); + + if (! arg) { + return Unexpected<>{ std::move(arg).error() }; + } + + initializerNode->fields.push_back(std::move(arg).value()); + + if (auto comma = matchAndConsume(TokenV::opComma); ! comma) { + return Unexpected{ std::move(comma).error() }; + } + else if (! comma.value()) { + if (auto ntok = tokenizer.peek(); ! ntok) { + return Unexpected{ std::move(ntok).error() }; + } + else { + if (ntok->value != TokenV::opRSquirly) { + return langException( + ntok->line, + ntok->column, + toString(*ntok), + "',' or '}'" + ); + } + else { + stillParams = false; + } + } + } + + if (auto close = match(TokenV::opRSquirly); ! close) { + return Unexpected<>{ std::move(close).error() }; + } + else if (close.value()) { + stillParams = false; + } + } + + newNode->initializer = std::move(initializerNode); + } + + if (auto close = consume(TokenV::opRSquirly, "'}'"); ! close) { + return Unexpected<>{ std::move(close).error() }; + } + + newNode->type = std::move(lhs); + + node = std::move(newNode); + } else if (op == ast::PostfixOperator::SliceAccess) { auto idx = parseExpression(); diff --git a/lib/src/Parser/Operators.cpp b/lib/src/Parser/Operators.cpp index ce9b9a9..92b1992 100644 --- a/lib/src/Parser/Operators.cpp +++ b/lib/src/Parser/Operators.cpp @@ -97,6 +97,7 @@ namespace arti::lang::pratt { case opPtrSlice: case opSlicePtr: case opReflect: + case opLSquirly: return true; default: return false; @@ -223,6 +224,8 @@ namespace arti::lang::pratt { return SliceToPtr; case opReflect: return Reflect; + case opLSquirly: + return ObjectLiteral; default: return Uninitialized; } diff --git a/lib/src/Parser/Pratt.cpp b/lib/src/Parser/Pratt.cpp index 48516fb..2c43b02 100644 --- a/lib/src/Parser/Pratt.cpp +++ b/lib/src/Parser/Pratt.cpp @@ -88,9 +88,10 @@ namespace arti::lang::pratt { case ast::InfixOperator::BoolAndAssignment: case ast::InfixOperator::BoolOrAssignment: case ast::InfixOperator::LShiftAssignment: - case ast::InfixOperator::RShiftAssignment: return { 2, 1 }; - - default: return { 0, 0 }; + case ast::InfixOperator::RShiftAssignment: + return { 2, 1 }; + default: + return { 0, 0 }; } } @@ -103,8 +104,11 @@ namespace arti::lang::pratt { case ast::PostfixOperator::SliceSize: case ast::PostfixOperator::PtrToSlice: case ast::PostfixOperator::SliceToPtr: - case ast::PostfixOperator::Reflect: return 19; - default: return 0; + case ast::PostfixOperator::Reflect: + case ast::PostfixOperator::ObjectLiteral: + return 19; + default: + return 0; } }