Skip to content

Commit d36a13f

Browse files
authored
chore: Resolve simple enum specifiers
Signed-off-by: GitHub <[email protected]>
1 parent 5e7d18a commit d36a13f

File tree

3 files changed

+78
-15
lines changed

3 files changed

+78
-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: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,44 @@ class Symbol {
150150
SourceLocation location_;
151151
};
152152

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

0 commit comments

Comments
 (0)