feat(parser): add support for type-initiated expressions

Signed-off-by: erick-alcachofa <erick@artichoke.dev>

Implement TypeExpression AST node to allow types to be used within
expressions, enabling the parsing of anonymous slice and array
initializers like `[]Type { ... }`.

- Register `[` as a prefix-style token (NUD) in the Pratt parser.
- Add `TypeExpression` node to AST and expression variants.
- Update `toDot` and `toString` visitors for AST visualization.
- Update frontend to open source files directly to fix issues at opening
  paths.
This commit is contained in:
erick-alcachofa 2025-12-28 10:21:24 -06:00
parent f024334da5
commit c2f37d5702
Signed by: me
GPG Key ID: 6FA5F8643444BAFA
6 changed files with 54 additions and 2 deletions

View File

@ -41,7 +41,7 @@ int main(int argc, char **argv) {
}
std::ifstream file;
file.open(sanitizePath(argv[1]));
file.open(argv[1]);
if (! file.is_open()) {
std::println("Failed to open file {}", argv[1]);

View File

@ -47,6 +47,7 @@ namespace arti::lang::ast {
struct SliceCreationExpression;
struct SliceLengthExpression;
struct SlicePtrExpression;
struct TypeExpression;
} // namespace nodes
@ -67,6 +68,7 @@ namespace arti::lang::ast {
using SliceCreationExprNode = Ptr<nodes::SliceCreationExpression>;
using SliceLengthExprNode = Ptr<nodes::SliceLengthExpression>;
using SlicePtrExprNode = Ptr<nodes::SlicePtrExpression>;
using TypeExprNode = Ptr<nodes::TypeExpression>;
/* Variant nodes */
using ExpressionNode = Variant<
@ -92,7 +94,8 @@ namespace arti::lang::ast {
SliceCreationExprNode,
SliceLengthExprNode,
SlicePtrExprNode,
ReflectionExprNode
ReflectionExprNode,
TypeExprNode
>;
/* Node definitions */
@ -232,5 +235,11 @@ namespace arti::lang::ast {
Optional<ObjectLtrlInitializerNode> initializer;
};
struct nodes::TypeExpression {
SourceLocation location;
TypeNode type;
};
} // namespace arti::lang::ast

View File

@ -223,6 +223,7 @@ namespace arti::lang::ast {
std::string emit(const ElseBranchNode &, GraphBuilder &);
std::string emit(const DeferableNode &, GraphBuilder &);
std::string emit(const PreLoopStmtNode &, GraphBuilder &);
std::string emit(const TypeExprNode &, GraphBuilder &);
// Helpers for making leaf nodes with backticked values
inline std::string makeLeaf(GraphBuilder &g, std::string_view value) {
@ -766,6 +767,7 @@ namespace arti::lang::ast {
[&g](const SlicePtrExprNode &n) { return emit(n, g); },
[&g](const ReflectionExprNode &n) { return emit(n, g); },
[&g](const GenericExprNode &n) { return emit(n, g); },
[&g](const TypeExprNode &n) { return emit(n, g); },
};
return std::visit(visitor, node);
}
@ -1019,6 +1021,12 @@ namespace arti::lang::ast {
return std::visit(visitor, node);
}
std::string emit(const TypeExprNode &node, GraphBuilder &g) {
auto id = g.makeNode("TypeExpression");
g.addEdge(id, emit(node->type, g), "Type");
return id;
}
} // namespace
// Public API

View File

@ -98,6 +98,7 @@ namespace arti::lang::ast {
std::string toString(const ElseBranchNode &, std::string);
std::string toString(const DeferableNode &, std::string);
std::string toString(const PreLoopStmtNode &, std::string);
std::string toString(const TypeExprNode &, std::string);
std::string toString(PrefixOperator op);
std::string toString(InfixOperator op);
std::string toString(CompoundAssignOperator op);
@ -976,6 +977,9 @@ namespace arti::lang::ast {
[padding](const GenericExprNode &node) -> std::string {
return toString(node, padding);
},
[padding](const TypeExprNode &node) -> std::string {
return toString(node, padding);
},
};
return std::visit(visitor, node);
@ -1457,6 +1461,13 @@ namespace arti::lang::ast {
return std::visit(visitor, node);
}
std::string toString(const TypeExprNode &node, std::string prefix) {
std::stringstream ss;
ss << "TypeÉxpression";
appendItem(ss, prefix, node->type, true);
return ss.str();
}
std::string toString(PrefixOperator op) {
using enum PrefixOperator;

View File

@ -49,6 +49,29 @@ namespace arti::lang {
lhs = std::move(lhsExpr).value();
}
}
else if (peekToken->value == TokenV::opLBracket) {
if (auto close = match(TokenV::opRBracket, 1); ! close) {
return Unexpected<>{ std::move(close).error() };
}
else if (! close.value()) {
return langException<ExceptCode::ecUnexpectedToken>(
peekToken->line,
peekToken->column,
toString(*peekToken),
"']'"
);
}
if (auto type = parseType(); ! type) {
return Unexpected<>{ std::move(type).error() };
}
else {
auto node = ast::MakeNode<ast::TypeExprNode>();
node->location = type.value()->location;
node->type = std::move(type).value();
lhs = std::move(node);
}
}
else if (pratt::isPrefixOperator(peekToken->value)) {
if (auto newLhs = parsePrefixExpression(); ! newLhs) {
return Unexpected<>{ std::move(newLhs).error() };

View File

@ -34,6 +34,7 @@ namespace arti::lang::pratt {
case opTilde:
case opAnd:
case opLParen:
case opLBracket:
case kwNot:
return true;