From cd3bce0aa977ba31a95de84bee455adced01bb79 Mon Sep 17 00:00:00 2001 From: MineGame159 Date: Sun, 28 Jan 2024 11:33:38 +0100 Subject: [PATCH] CORE: Fix parsing of struct initializer's type, now can include namespaces --- core/cst/expressions.go | 77 ++++++++++++++++++++++++++--------- tests/src/namespaces.fb | 13 ++++++ tests/src/namespaces_child.fb | 3 ++ 3 files changed, 73 insertions(+), 20 deletions(-) create mode 100644 tests/src/namespaces.fb create mode 100644 tests/src/namespaces_child.fb diff --git a/core/cst/expressions.go b/core/cst/expressions.go index 1f99640..131d781 100644 --- a/core/cst/expressions.go +++ b/core/cst/expressions.go @@ -2,6 +2,7 @@ package cst import ( "fireball/core/scanner" + "fireball/core/utils" ) var canStartExpr = []scanner.TokenKind{ @@ -114,24 +115,6 @@ func parsePrefixExprPratt(p *parser) Node { return p.end() } - if p.peek2() == scanner.LeftBrace { - p.begin(StructExprNode) - - p.begin(IdentifierTypeNode) - p.advanceAddChild() - p.childAdd(p.end()) - - p.advanceAddChild() - if p.repeatSeparated(parseStructFieldExpr, canStartStructFieldExpr, scanner.Comma) { - return p.end() - } - if p.consume(scanner.RightBrace) { - return p.end() - } - - return p.end() - } - return p.advanceGetLeaf() case scanner.LeftParen: @@ -277,6 +260,24 @@ func parsePostfixExprPratt(p *parser, op scanner.TokenKind, lhs Node) Node { return p.end() + case scanner.LeftBrace: + p.begin(StructExprNode) + + if p.childAdd(convertExprToIdentifierType(p, lhs)) { + return p.end() + } + if p.consume(scanner.LeftBrace) { + return p.end() + } + if p.repeatSeparated(parseStructFieldExpr, canStartStructFieldExpr, scanner.Comma) { + return p.end() + } + if p.consume(scanner.RightBrace) { + return p.end() + } + + return p.end() + default: p.begin(UnaryExprNode) @@ -287,6 +288,42 @@ func parsePostfixExprPratt(p *parser, op scanner.TokenKind, lhs Node) Node { } } +func convertExprToIdentifierType(p *parser, node Node) Node { + p.begin(IdentifierTypeNode) + + convertExprToIdentifierTypePart(p, node) + + return p.end() +} + +func convertExprToIdentifierTypePart(p *parser, node Node) { + //goland:noinspection GoSwitchMissingCasesForIotaConsts + switch node.Kind { + case IdentifierNode: + p.childAdd(node) + return + + case BinaryExprNode: + if node.Contains(scanner.Dot) { + convertExprToIdentifierTypePart(p, node.Children[0]) + + p.childAdd(node.Children[1]) + + if len(node.Children) == 3 { + convertExprToIdentifierTypePart(p, node.Children[2]) + } + + return + } + } + + p.reporter.Report(utils.Diagnostic{ + Kind: utils.ErrorKind, + Range: node.Range, + Message: "Invalid type", + }) +} + // Powers type tokenPowers struct { @@ -338,8 +375,8 @@ func init() { prefix(scanner.Minus, scanner.Bang, scanner.PlusPlus, scanner.MinusMinus, scanner.Ampersand, scanner.Star, scanner.FuncPtr) // x++, x-- postfix(scanner.PlusPlus, scanner.MinusMinus) - // x[], x() - postfix(scanner.LeftBracket, scanner.LeftParen) + // x[], x(), x {} + postfix(scanner.LeftBracket, scanner.LeftParen, scanner.LeftBrace) // x.y infix(false, scanner.Dot) } diff --git a/tests/src/namespaces.fb b/tests/src/namespaces.fb new file mode 100644 index 0000000..3c58dae --- /dev/null +++ b/tests/src/namespaces.fb @@ -0,0 +1,13 @@ +namespace Tests.Namespaces; + +#[Test] +func typeSimple() bool { + var _ Child.Foo; + return true; +} + +#[Test] +func typeStructInit() bool { + var _ = Child.Foo {}; + return true; +} diff --git a/tests/src/namespaces_child.fb b/tests/src/namespaces_child.fb new file mode 100644 index 0000000..7fcb658 --- /dev/null +++ b/tests/src/namespaces_child.fb @@ -0,0 +1,3 @@ +namespace Tests.Namespaces.Child; + +struct Foo {}