feat(parser): implement object literals to unify struct and slice syntax
Signed-off-by: erick-alcachofa <erick@artichoke.dev>
Implement support for object literals using a unified syntax for both
struct and slice initialization. Since the parser lacks the semantic
context to distinguish between a struct or a slice at this stage, both
are represented by the new `ObjectLiteral` AST node.
initialization within curly braces following a type expression:
* **Named Initializers**: Uses the `.field = value` syntax (e.g.,
`Point { .x = 10, .y = 20 }`).
* **Positional Initializers**: Uses a comma-separated list of
expressions (e.g., `[]i32 { 1, 2, 3 }`).
* Renamed `StructLiteral` and `SliceLiteral` nodes to `ObjectLiteral`.
* Refactored initialization helper nodes (e.g.,
`StructLiteralNamedFieldInit` is now `ObjectLiteralNamedFieldInit`).
* Unified the representation in `Expressions.hpp` and `Literals.hpp` to
use a single `ObjectLiteral` struct containing a `type` and an
optional `initializer`.
* Integrated the opening brace `{` (`opLSquirly`) as a high-precedence
postfix operator (binding power 19).
* Implemented parsing logic in `Expressions.cpp` to handle the
transition from a type expression to an object initializer.
* Updated `toDot` and `toString` visitors to handle the unified
`ObjectLiteral` nodes and their respective initializer variants.
* Improved robustness in `Declarations.cpp` by ensuring list parsing
correctly handles closing braces in specific edge cases.
This commit is contained in:
parent
8dd75e3b8a
commit
3180ca4662
@ -104,6 +104,7 @@ namespace arti::lang::ast {
|
||||
PtrToSlice,
|
||||
SliceToPtr,
|
||||
Reflect,
|
||||
ObjectLiteral,
|
||||
};
|
||||
|
||||
enum class CompoundAssignOperator {
|
||||
|
||||
@ -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<ObjectLtrlNamedFieldInitNode> fields;
|
||||
};
|
||||
|
||||
struct nodes::StructLiteralNamedInitializer {
|
||||
struct nodes::ObjectLiteralPositionalInitializer {
|
||||
SourceLocation location;
|
||||
|
||||
Vector<StructLtrlNamedFieldInitNode> fields;
|
||||
Vector<ExpressionNode> fields;
|
||||
};
|
||||
|
||||
struct nodes::StructLiteralPositionalInitializer {
|
||||
struct nodes::ObjectLiteral {
|
||||
SourceLocation location;
|
||||
|
||||
Vector<StructLtrlPositionalInitNode> fields;
|
||||
};
|
||||
ExpressionNode type;
|
||||
Optional<ObjectLtrlInitializerNode> initializer;
|
||||
};
|
||||
|
||||
} // namespace arti::lang::ast
|
||||
|
||||
|
||||
@ -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<nodes::FloatLiteral>;
|
||||
using IntegerLtrlNode = Ptr<nodes::IntegerLiteral>;
|
||||
using BooleanLtrlNode = Ptr<nodes::BooleanLiteral>;
|
||||
using StructLtrlNode = Ptr<nodes::StructLiteral>;
|
||||
using SliceLtrlNode = Ptr<nodes::SliceLiteral>;
|
||||
using ObjectLtrlNode = Ptr<nodes::ObjectLiteral>;
|
||||
|
||||
using StructLtrlNamedFieldInitNode =
|
||||
Ptr<nodes::StructLiteralNamedFieldInit>;
|
||||
using StructLtrlPositionalInitNode =
|
||||
Ptr<nodes::StructLiteralPositionalInit>;
|
||||
using StructLtrlNamedInitializerNode =
|
||||
Ptr<nodes::StructLiteralNamedInitializer>;
|
||||
using StructLtrlPositionalInitializerNode =
|
||||
Ptr<nodes::StructLiteralPositionalInitializer>;
|
||||
using ObjectLtrlNamedFieldInitNode =
|
||||
Ptr<nodes::ObjectLiteralNamedFieldInit>;
|
||||
using ObjectLtrlNamedInitializerNode =
|
||||
Ptr<nodes::ObjectLiteralNamedInitializer>;
|
||||
using ObjectLtrlPositionalInitializerNode =
|
||||
Ptr<nodes::ObjectLiteralPositionalInitializer>;
|
||||
|
||||
/* 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<StructLtrlInitializerNode> initializer;
|
||||
};
|
||||
|
||||
struct nodes::SliceLiteral {
|
||||
SourceLocation location;
|
||||
|
||||
TypeNode type;
|
||||
Optional<StructLtrlPositionalInitializerNode> initializer;
|
||||
};
|
||||
|
||||
/* INFO: Helper types definitions are on Expressions.hpp
|
||||
* due to dependency in ExpressionNode variant. */
|
||||
|
||||
|
||||
@ -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); },
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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<ast::ObjectLtrlNode>();
|
||||
|
||||
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<ast::ObjectLtrlNamedInitializerNode>();
|
||||
|
||||
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<ast::ObjectLtrlNamedFieldInitNode>();
|
||||
|
||||
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<ExceptCode::ecUnexpectedToken>(
|
||||
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<ast::ObjectLtrlPositionalInitializerNode>();
|
||||
|
||||
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<ExceptCode::ecUnexpectedToken>(
|
||||
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();
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user