Skip to content

Commit 3c1b57c

Browse files
committed
chore: Resolve simple class specifiers
Signed-off-by: GitHub <[email protected]>
1 parent 5e7d18a commit 3c1b57c

File tree

3 files changed

+80
-15
lines changed

3 files changed

+80
-15
lines changed

src/parser/cxx/ast.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2999,6 +2999,7 @@ class ElaboratedTypeSpecifierAST final : public SpecifierAST {
29992999
UnqualifiedIdAST* unqualifiedId = nullptr;
30003000
TokenKind classKey = TokenKind::T_EOF_SYMBOL;
30013001
bool isTemplateIntroduced = false;
3002+
Symbol* symbol = nullptr;
30023003

30033004
void accept(ASTVisitor* visitor) override { visitor->visit(this); }
30043005

src/parser/cxx/parser.cc

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <algorithm>
3939
#include <cstring>
4040
#include <format>
41+
#include <ranges>
4142

4243
namespace cxx {
4344

@@ -6568,33 +6569,56 @@ auto Parser::parse_elaborated_type_specifier_helper(
65686569
SourceLocation templateLoc;
65696570
const auto isTemplateIntroduced = match(TokenKind::T_TEMPLATE, templateLoc);
65706571

6571-
UnqualifiedIdAST* unqualifiedId = nullptr;
6572+
auto ast = make_node<ElaboratedTypeSpecifierAST>(pool_);
6573+
yyast = ast;
6574+
6575+
ast->classLoc = classLoc;
6576+
ast->attributeList = attributes;
6577+
ast->nestedNameSpecifier = nestedNameSpecifier;
6578+
ast->templateLoc = templateLoc;
6579+
ast->classKey = unit->tokenKind(classLoc);
6580+
ast->isTemplateIntroduced = isTemplateIntroduced;
6581+
65726582
const auto loc = currentLocation();
65736583

65746584
if (lookat(TokenKind::T_IDENTIFIER, TokenKind::T_LESS)) {
65756585
if (SimpleTemplateIdAST* templateId = nullptr; parse_simple_template_id(
65766586
templateId, nestedNameSpecifier, isTemplateIntroduced)) {
6577-
unqualifiedId = templateId;
6587+
ast->unqualifiedId = templateId;
65786588
} else {
65796589
parse_error(loc, "expected a template-id");
65806590
}
65816591
} else if (NameIdAST* nameId = nullptr; parse_name_id(nameId)) {
6582-
unqualifiedId = nameId;
6592+
ast->unqualifiedId = nameId;
6593+
65836594
auto symbol = Lookup{scope_}(nestedNameSpecifier, nameId->identifier);
6584-
} else {
6585-
parse_error("expected a name");
6586-
}
65876595

6588-
auto ast = make_node<ElaboratedTypeSpecifierAST>(pool_);
6589-
yyast = ast;
6596+
auto class_symbols_view = std::views::filter(&Symbol::isClass);
65906597

6591-
ast->classLoc = classLoc;
6592-
ast->attributeList = attributes;
6593-
ast->nestedNameSpecifier = nestedNameSpecifier;
6594-
ast->templateLoc = templateLoc;
6595-
ast->unqualifiedId = unqualifiedId;
6596-
ast->classKey = unit->tokenKind(classLoc);
6597-
ast->isTemplateIntroduced = isTemplateIntroduced;
6598+
auto enum_symbols_view = std::views::filter([](Symbol* symbol) {
6599+
return symbol->isEnum() || symbol->isScopedEnum();
6600+
});
6601+
6602+
if (ast->classKey == TokenKind::T_CLASS ||
6603+
ast->classKey == TokenKind::T_STRUCT ||
6604+
ast->classKey == TokenKind::T_UNION) {
6605+
for (auto symbol : SymbolChainView(symbol) | class_symbols_view) {
6606+
if (symbol->name() != nameId->identifier) continue;
6607+
ast->symbol = symbol;
6608+
specs.type = symbol->type();
6609+
break;
6610+
}
6611+
} else if (ast->classKey == TokenKind::T_ENUM) {
6612+
for (auto symbol : SymbolChainView(symbol) | enum_symbols_view) {
6613+
if (symbol->name() != nameId->identifier) continue;
6614+
ast->symbol = symbol;
6615+
specs.type = symbol->type();
6616+
break;
6617+
}
6618+
}
6619+
} else {
6620+
parse_error(loc, "expected a name");
6621+
}
65986622

65996623
return true;
66006624
}

src/parser/cxx/symbols.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,46 @@ class Symbol {
150150
SourceLocation location_;
151151
};
152152

153+
class SymbolChainIterator {
154+
public:
155+
using difference_type = std::ptrdiff_t;
156+
using value_type = Symbol*;
157+
158+
SymbolChainIterator() = default;
159+
explicit SymbolChainIterator(Symbol* symbol) : symbol_(symbol) {}
160+
161+
auto operator*() const -> Symbol* { return symbol_; }
162+
163+
auto operator++() -> SymbolChainIterator& {
164+
symbol_ = symbol_->next();
165+
return *this;
166+
}
167+
168+
auto operator++(int) -> SymbolChainIterator {
169+
auto it = *this;
170+
++*this;
171+
return it;
172+
}
173+
174+
auto operator==(const SymbolChainIterator&) const -> bool = default;
175+
176+
private:
177+
Symbol* symbol_ = nullptr;
178+
};
179+
180+
static_assert(std::forward_iterator<SymbolChainIterator>);
181+
182+
class SymbolChainView : public std::ranges::view_interface<SymbolChainView> {
183+
public:
184+
explicit SymbolChainView(Symbol* symbol) : begin_{symbol} {}
185+
186+
auto begin() const -> SymbolChainIterator { return begin_; }
187+
auto end() const -> SymbolChainIterator { return SymbolChainIterator(); }
188+
189+
private:
190+
SymbolChainIterator begin_;
191+
};
192+
153193
class ScopedSymbol : public Symbol {
154194
public:
155195
ScopedSymbol(SymbolKind kind, Scope* enclosingScope);

0 commit comments

Comments
 (0)