diff --git a/clang-tools-extra/pseudo/gen/Main.cpp b/clang-tools-extra/pseudo/gen/Main.cpp --- a/clang-tools-extra/pseudo/gen/Main.cpp +++ b/clang-tools-extra/pseudo/gen/Main.cpp @@ -58,6 +58,50 @@ } } // namespace +namespace clang { +namespace pseudo { +namespace { + +// Mangles a symbol name into a valid identifier. +// +// These follow names in the grammar fairly closely: +// nonterminal: `ptr-declartor` becomes `ptr_declarator`; +// punctuator: `,` becomes `COMMA`; +// keyword: `INT` becomes `INT`; +// terminal: `IDENTIFIER` becomes `IDENTIFIER`; +std::string mangleSymbol(SymbolID SID, const Grammar &G) { + static std::string *TokNames = new std::string[]{ +#define TOK(X) llvm::StringRef(#X).upper(), +#define KEYWORD(Keyword, Condition) llvm::StringRef(#Keyword).upper(), +#include "clang/Basic/TokenKinds.def" + }; + if (isToken(SID)) + return TokNames[symbolToToken(SID)]; + std::string Name = G.symbolName(SID).str(); + // translation-unit -> translation_unit + std::replace(Name.begin(), Name.end(), '-', '_'); + return Name; +} + +// Mangles the RHS of a rule definition into a valid identifier. +// +// These are unique only for a fixed LHS. +// e.g. for the grammar rule `ptr-declarator := ptr-operator ptr-declarator`, +// it is `ptr_operator__ptr_declarator`. +std::string mangleRule(RuleID RID, const Grammar &G) { + const auto &R = G.lookupRule(RID); + std::string MangleName = mangleSymbol(R.seq().front(), G); + for (SymbolID S : R.seq().drop_front()) { + MangleName.append("__"); + MangleName.append(mangleSymbol(S, G)); + } + return MangleName; +} + +} // namespace +} // namespace pseudo +} // namespace clang + int main(int argc, char *argv[]) { llvm::cl::ParseCommandLineOptions(argc, argv, ""); @@ -81,21 +125,26 @@ case EmitSymbolList: Out.os() << R"cpp( #ifndef NONTERMINAL -#define NONTERMINAL(X, Y) +#define NONTERMINAL(NAME, ID) #endif #ifndef RULE -#define RULE(X, Y) +#define RULE(LHS, RHS, ID) #endif #ifndef EXTENSION -#define EXTENSION(X, Y) +#define EXTENSION(NAME, ID) #endif )cpp"; for (clang::pseudo::SymbolID ID = 0; ID < G.table().Nonterminals.size(); - ++ID) - Out.os() << llvm::formatv("NONTERMINAL({0}, {1})\n", G.mangleSymbol(ID), - ID); - for (clang::pseudo::RuleID RID = 0; RID < G.table().Rules.size(); ++RID) - Out.os() << llvm::formatv("RULE({0}, {1})\n", G.mangleRule(RID), RID); + ++ID) { + Out.os() << llvm::formatv("NONTERMINAL({0}, {1})\n", + clang::pseudo::mangleSymbol(ID, G), ID); + for (const clang::pseudo::Rule &R : G.rulesFor(ID)) { + clang::pseudo::RuleID RID = &R - G.table().Rules.data(); + Out.os() << llvm::formatv("RULE({0}, {1}, {2})\n", + clang::pseudo::mangleSymbol(R.Target, G), + clang::pseudo::mangleRule(RID, G), RID); + } + } for (clang::pseudo::ExtensionID EID = 1 /*skip the sentinel 0 value*/; EID < G.table().AttributeValues.size(); ++EID) { llvm::StringRef Name = G.table().AttributeValues[EID]; diff --git a/clang-tools-extra/pseudo/include/clang-pseudo/cxx/CXX.h b/clang-tools-extra/pseudo/include/clang-pseudo/cxx/CXX.h --- a/clang-tools-extra/pseudo/include/clang-pseudo/cxx/CXX.h +++ b/clang-tools-extra/pseudo/include/clang-pseudo/cxx/CXX.h @@ -29,25 +29,56 @@ namespace clang { namespace pseudo { namespace cxx { -// Symbol represents nonterminal symbols in the C++ grammar. -// It provides a simple uniform way to access a particular nonterminal. -enum class Symbol : SymbolID { + +// We want enums to be scoped but implicitly convertible to RuleID etc. +// So create regular (unscoped) enums inside subnamespaces of `detail`. +// Then add aliases for them outside `detail`. +namespace detail { +namespace symbols { +enum Symbol : SymbolID { #define NONTERMINAL(X, Y) X = Y, #include "CXXSymbols.inc" #undef NONTERMINAL }; +} // namespace symbols -enum class Rule : RuleID { -#define RULE(X, Y) X = Y, +namespace extensions { +enum Extension : ExtensionID { +#define EXTENSION(X, Y) X = Y, #include "CXXSymbols.inc" -#undef RULE +#undef EXTENSION }; +} // namespace extensions -enum class Extension : ExtensionID { -#define EXTENSION(X, Y) X = Y, +namespace rules { +// For each symbol we close the last symbol's enum+namespace and open new ones. +// We need a dummy namespace+enum so that this works for the first rule. +namespace dummy { +enum Rule { +//clang-format off +#define NONTERMINAL(NAME, ID) \ +}; \ +} \ +namespace NAME { \ +enum Rule : RuleID { +//clang-format on +#define RULE(LHS, RHS, ID) RHS = ID, #include "CXXSymbols.inc" -#undef EXTENSION }; +} +} // namespace rules +} // namespace detail + +// Symbol represents nonterminal symbols in the C++ grammar. +// It provides a simple uniform way to access a particular nonterminal. +using Symbol = detail::symbols::Symbol; + +using Extension = detail::extensions::Extension; + +namespace rule { +#define NONTERMINAL(NAME, ID) using NAME = detail::rules::NAME::Rule; +#include "CXXSymbols.inc" +} // namespace rule // Returns the Language for the cxx.bnf grammar. const Language &getLanguage(); diff --git a/clang-tools-extra/pseudo/include/clang-pseudo/grammar/Grammar.h b/clang-tools-extra/pseudo/include/clang-pseudo/grammar/Grammar.h --- a/clang-tools-extra/pseudo/include/clang-pseudo/grammar/Grammar.h +++ b/clang-tools-extra/pseudo/include/clang-pseudo/grammar/Grammar.h @@ -162,21 +162,6 @@ // Terminals have names like "," (kw_comma) or "OPERATOR" (kw_operator). llvm::StringRef symbolName(SymbolID) const; - // Gets the mangled name for a terminal/nonterminal. - // Compared to names in the grammar, - // nonterminals `ptr-declartor` becomes `ptr_declarator`; - // terminal `,` becomes `comma`; - // terminal `IDENTIFIER` becomes `identifier`; - // terminal `INT` becomes `int`; - // NOTE: for nonterminals, the mangled name is the same as the cxx::Symbol - // enum class; for terminals, we deliberately stripped the `kw_` prefix in - // favor of the simplicity. - std::string mangleSymbol(SymbolID) const; - // Gets the mangled name for the rule. - // E.g. for the grammar rule `ptr-declarator := ptr-operator ptr-declarator`, - // it is `ptr_declarator_0ptr_operator_1ptr_declarator`. - std::string mangleRule(RuleID) const; - // Lookup the SymbolID of the nonterminal symbol by Name. llvm::Optional findNonterminal(llvm::StringRef Name) const; diff --git a/clang-tools-extra/pseudo/lib/cxx/CXX.cpp b/clang-tools-extra/pseudo/lib/cxx/CXX.cpp --- a/clang-tools-extra/pseudo/lib/cxx/CXX.cpp +++ b/clang-tools-extra/pseudo/lib/cxx/CXX.cpp @@ -111,42 +111,41 @@ } bool isFunctionDeclarator(const ForestNode *Declarator) { - assert(Declarator->symbol() == (SymbolID)(cxx::Symbol::declarator)); + assert(Declarator->symbol() == cxx::Symbol::declarator); bool IsFunction = false; - using cxx::Rule; while (true) { // not well-formed code, return the best guess. if (Declarator->kind() != ForestNode::Sequence) return IsFunction; - switch ((cxx::Rule)Declarator->rule()) { - case Rule::noptr_declarator_0declarator_id: // reached the bottom + switch (Declarator->rule()) { + case rule::noptr_declarator::declarator_id: // reached the bottom return IsFunction; // *X is a nonfunction (unless X is a function). - case Rule::ptr_declarator_0ptr_operator_1ptr_declarator: + case rule::ptr_declarator::ptr_operator__ptr_declarator: Declarator = Declarator->elements()[1]; IsFunction = false; continue; // X() is a function (unless X is a pointer or similar). - case Rule:: - declarator_0noptr_declarator_1parameters_and_qualifiers_2trailing_return_type: - case Rule::noptr_declarator_0noptr_declarator_1parameters_and_qualifiers: + case rule::declarator:: + noptr_declarator__parameters_and_qualifiers__trailing_return_type: + case rule::noptr_declarator::noptr_declarator__parameters_and_qualifiers: Declarator = Declarator->elements()[0]; IsFunction = true; continue; // X[] is an array (unless X is a pointer or function). - case Rule:: - noptr_declarator_0noptr_declarator_1l_square_2constant_expression_3r_square: - case Rule::noptr_declarator_0noptr_declarator_1l_square_2r_square: + case rule::noptr_declarator:: + noptr_declarator__l_square__constant_expression__r_square: + case rule::noptr_declarator::noptr_declarator__l_square__r_square: Declarator = Declarator->elements()[0]; IsFunction = false; continue; // (X) is whatever X is. - case Rule::noptr_declarator_0l_paren_1ptr_declarator_2r_paren: + case rule::noptr_declarator::l_paren__ptr_declarator__r_paren: Declarator = Declarator->elements()[1]; continue; - case Rule::ptr_declarator_0noptr_declarator: - case Rule::declarator_0ptr_declarator: + case rule::ptr_declarator::noptr_declarator: + case rule::declarator::ptr_declarator: Declarator = Declarator->elements()[0]; continue; @@ -173,13 +172,13 @@ // FIXME: every time we apply this check, we walk the whole subtree. // Add per-node caching instead. while (true) { - assert(N->symbol() == (SymbolID)Symbol::decl_specifier_seq || - N->symbol() == (SymbolID)Symbol::type_specifier_seq || - N->symbol() == (SymbolID)Symbol::defining_type_specifier_seq || - N->symbol() == (SymbolID)Symbol::decl_specifier || - N->symbol() == (SymbolID)Symbol::type_specifier || - N->symbol() == (SymbolID)Symbol::defining_type_specifier || - N->symbol() == (SymbolID)Symbol::simple_type_specifier); + assert(N->symbol() == Symbol::decl_specifier_seq || + N->symbol() == Symbol::type_specifier_seq || + N->symbol() == Symbol::defining_type_specifier_seq || + N->symbol() == Symbol::decl_specifier || + N->symbol() == Symbol::type_specifier || + N->symbol() == Symbol::defining_type_specifier || + N->symbol() == Symbol::simple_type_specifier); if (N->kind() == ForestNode::Opaque) return false; // conservative if (N->kind() == ForestNode::Ambiguous) @@ -188,66 +187,66 @@ assert(N->kind() == ForestNode::Sequence); switch (N->rule()) { // seq := element seq: check element then continue into seq - case (RuleID)Rule::decl_specifier_seq_0decl_specifier_1decl_specifier_seq: - case (RuleID)Rule::defining_type_specifier_seq_0defining_type_specifier_1defining_type_specifier_seq: - case (RuleID)Rule::type_specifier_seq_0type_specifier_1type_specifier_seq: + case rule::decl_specifier_seq::decl_specifier__decl_specifier_seq: + case rule::defining_type_specifier_seq::defining_type_specifier__defining_type_specifier_seq: + case rule::type_specifier_seq::type_specifier__type_specifier_seq: if (hasExclusiveType(N->children()[0])) return true; N = N->children()[1]; continue; // seq := element: continue into element - case (RuleID)Rule::decl_specifier_seq_0decl_specifier: - case (RuleID)Rule::type_specifier_seq_0type_specifier: - case (RuleID)Rule::defining_type_specifier_seq_0defining_type_specifier: + case rule::decl_specifier_seq::decl_specifier: + case rule::type_specifier_seq::type_specifier: + case rule::defining_type_specifier_seq::defining_type_specifier: N = N->children()[0]; continue; // defining-type-specifier - case (RuleID)Rule::defining_type_specifier_0type_specifier: + case rule::defining_type_specifier::type_specifier: N = N->children()[0]; continue; - case (RuleID)Rule::defining_type_specifier_0class_specifier: - case (RuleID)Rule::defining_type_specifier_0enum_specifier: + case rule::defining_type_specifier::class_specifier: + case rule::defining_type_specifier::enum_specifier: return true; // decl-specifier - case (RuleID)Rule::decl_specifier_0defining_type_specifier: + case rule::decl_specifier::defining_type_specifier: N = N->children()[0]; continue; - case (RuleID)Rule::decl_specifier_0consteval: - case (RuleID)Rule::decl_specifier_0constexpr: - case (RuleID)Rule::decl_specifier_0constinit: - case (RuleID)Rule::decl_specifier_0inline: - case (RuleID)Rule::decl_specifier_0friend: - case (RuleID)Rule::decl_specifier_0storage_class_specifier: - case (RuleID)Rule::decl_specifier_0typedef: - case (RuleID)Rule::decl_specifier_0function_specifier: + case rule::decl_specifier::CONSTEVAL: + case rule::decl_specifier::CONSTEXPR: + case rule::decl_specifier::CONSTINIT: + case rule::decl_specifier::INLINE: + case rule::decl_specifier::FRIEND: + case rule::decl_specifier::storage_class_specifier: + case rule::decl_specifier::TYPEDEF: + case rule::decl_specifier::function_specifier: return false; // type-specifier - case (RuleID)Rule::type_specifier_0elaborated_type_specifier: - case (RuleID)Rule::type_specifier_0typename_specifier: + case rule::type_specifier::elaborated_type_specifier: + case rule::type_specifier::typename_specifier: return true; - case (RuleID)Rule::type_specifier_0simple_type_specifier: + case rule::type_specifier::simple_type_specifier: N = N->children()[0]; continue; - case (RuleID)Rule::type_specifier_0cv_qualifier: + case rule::type_specifier::cv_qualifier: return false; // simple-type-specifier - case (RuleID)Rule::simple_type_specifier_0type_name: - case (RuleID)Rule::simple_type_specifier_0template_name: - case (RuleID)Rule::simple_type_specifier_0builtin_type: - case (RuleID)Rule::simple_type_specifier_0nested_name_specifier_1template_2simple_template_id: - case (RuleID)Rule::simple_type_specifier_0nested_name_specifier_1template_name: - case (RuleID)Rule::simple_type_specifier_0nested_name_specifier_1type_name: - case (RuleID)Rule::simple_type_specifier_0decltype_specifier: - case (RuleID)Rule::simple_type_specifier_0placeholder_type_specifier: + case rule::simple_type_specifier::type_name: + case rule::simple_type_specifier::template_name: + case rule::simple_type_specifier::builtin_type: + case rule::simple_type_specifier::nested_name_specifier__TEMPLATE__simple_template_id: + case rule::simple_type_specifier::nested_name_specifier__template_name: + case rule::simple_type_specifier::nested_name_specifier__type_name: + case rule::simple_type_specifier::decltype_specifier: + case rule::simple_type_specifier::placeholder_type_specifier: return true; - case (RuleID)Rule::simple_type_specifier_0long: - case (RuleID)Rule::simple_type_specifier_0short: - case (RuleID)Rule::simple_type_specifier_0signed: - case (RuleID)Rule::simple_type_specifier_0unsigned: + case rule::simple_type_specifier::LONG: + case rule::simple_type_specifier::SHORT: + case rule::simple_type_specifier::SIGNED: + case rule::simple_type_specifier::UNSIGNED: return false; default: @@ -269,96 +268,95 @@ } #define SYMBOL_GUARD(kind, cond) \ [](const GuardParams& P) { \ - const ForestNode &N = onlySymbol((SymbolID)Symbol::kind, P.RHS, P.Tokens); \ + const ForestNode &N = onlySymbol(Symbol::kind, P.RHS, P.Tokens); \ return cond; \ } return { - {(RuleID)Rule::function_declarator_0declarator, + {rule::function_declarator::declarator, SYMBOL_GUARD(declarator, isFunctionDeclarator(&N))}, - {(RuleID)Rule::non_function_declarator_0declarator, + {rule::non_function_declarator::declarator, SYMBOL_GUARD(declarator, !isFunctionDeclarator(&N))}, // A {decl,type,defining-type}-specifier-sequence cannot have multiple // "exclusive" types (like class names): a value has only one type. - {(RuleID)Rule:: - defining_type_specifier_seq_0defining_type_specifier_1defining_type_specifier_seq, + {rule::defining_type_specifier_seq:: + defining_type_specifier__defining_type_specifier_seq, GUARD(!hasExclusiveType(P.RHS[0]) || !hasExclusiveType(P.RHS[1]))}, - {(RuleID)Rule::type_specifier_seq_0type_specifier_1type_specifier_seq, + {rule::type_specifier_seq::type_specifier__type_specifier_seq, GUARD(!hasExclusiveType(P.RHS[0]) || !hasExclusiveType(P.RHS[1]))}, - {(RuleID)Rule::decl_specifier_seq_0decl_specifier_1decl_specifier_seq, + {rule::decl_specifier_seq::decl_specifier__decl_specifier_seq, GUARD(!hasExclusiveType(P.RHS[0]) || !hasExclusiveType(P.RHS[1]))}, - {(RuleID)Rule::contextual_override_0identifier, + {rule::contextual_override::identifier, TOKEN_GUARD(identifier, Tok.text() == "override")}, - {(RuleID)Rule::contextual_final_0identifier, + {rule::contextual_final::identifier, TOKEN_GUARD(identifier, Tok.text() == "final")}, - {(RuleID)Rule::import_keyword_0identifier, + {rule::import_keyword::identifier, TOKEN_GUARD(identifier, Tok.text() == "import")}, - {(RuleID)Rule::export_keyword_0identifier, + {rule::export_keyword::identifier, TOKEN_GUARD(identifier, Tok.text() == "export")}, - {(RuleID)Rule::module_keyword_0identifier, + {rule::module_keyword::identifier, TOKEN_GUARD(identifier, Tok.text() == "module")}, - {(RuleID)Rule::contextual_zero_0numeric_constant, + {rule::contextual_zero::numeric_constant, TOKEN_GUARD(numeric_constant, Tok.text() == "0")}, - {(RuleID)Rule:: - selection_statement_0if_1l_paren_2condition_3r_paren_4statement, + {rule::selection_statement::IF__l_paren__condition__r_paren__statement, guardNextTokenNotElse}, - {(RuleID)Rule:: - selection_statement_0if_1constexpr_2l_paren_3condition_4r_paren_5statement, + {rule::selection_statement:: + IF__CONSTEXPR__l_paren__condition__r_paren__statement, guardNextTokenNotElse}, // The grammar distinguishes (only) user-defined vs plain string literals, // where the clang lexer distinguishes (only) encoding types. - {(RuleID)Rule::user_defined_string_literal_chunk_0string_literal, + {rule::user_defined_string_literal_chunk::string_literal, TOKEN_GUARD(string_literal, isStringUserDefined(Tok))}, - {(RuleID)Rule::user_defined_string_literal_chunk_0utf8_string_literal, + {rule::user_defined_string_literal_chunk::utf8_string_literal, TOKEN_GUARD(utf8_string_literal, isStringUserDefined(Tok))}, - {(RuleID)Rule::user_defined_string_literal_chunk_0utf16_string_literal, + {rule::user_defined_string_literal_chunk::utf16_string_literal, TOKEN_GUARD(utf16_string_literal, isStringUserDefined(Tok))}, - {(RuleID)Rule::user_defined_string_literal_chunk_0utf32_string_literal, + {rule::user_defined_string_literal_chunk::utf32_string_literal, TOKEN_GUARD(utf32_string_literal, isStringUserDefined(Tok))}, - {(RuleID)Rule::user_defined_string_literal_chunk_0wide_string_literal, + {rule::user_defined_string_literal_chunk::wide_string_literal, TOKEN_GUARD(wide_string_literal, isStringUserDefined(Tok))}, - {(RuleID)Rule::string_literal_chunk_0string_literal, + {rule::string_literal_chunk::string_literal, TOKEN_GUARD(string_literal, !isStringUserDefined(Tok))}, - {(RuleID)Rule::string_literal_chunk_0utf8_string_literal, + {rule::string_literal_chunk::utf8_string_literal, TOKEN_GUARD(utf8_string_literal, !isStringUserDefined(Tok))}, - {(RuleID)Rule::string_literal_chunk_0utf16_string_literal, + {rule::string_literal_chunk::utf16_string_literal, TOKEN_GUARD(utf16_string_literal, !isStringUserDefined(Tok))}, - {(RuleID)Rule::string_literal_chunk_0utf32_string_literal, + {rule::string_literal_chunk::utf32_string_literal, TOKEN_GUARD(utf32_string_literal, !isStringUserDefined(Tok))}, - {(RuleID)Rule::string_literal_chunk_0wide_string_literal, + {rule::string_literal_chunk::wide_string_literal, TOKEN_GUARD(wide_string_literal, !isStringUserDefined(Tok))}, // And the same for chars. - {(RuleID)Rule::user_defined_character_literal_0char_constant, + {rule::user_defined_character_literal::char_constant, TOKEN_GUARD(char_constant, isCharUserDefined(Tok))}, - {(RuleID)Rule::user_defined_character_literal_0utf8_char_constant, + {rule::user_defined_character_literal::utf8_char_constant, TOKEN_GUARD(utf8_char_constant, isCharUserDefined(Tok))}, - {(RuleID)Rule::user_defined_character_literal_0utf16_char_constant, + {rule::user_defined_character_literal::utf16_char_constant, TOKEN_GUARD(utf16_char_constant, isCharUserDefined(Tok))}, - {(RuleID)Rule::user_defined_character_literal_0utf32_char_constant, + {rule::user_defined_character_literal::utf32_char_constant, TOKEN_GUARD(utf32_char_constant, isCharUserDefined(Tok))}, - {(RuleID)Rule::user_defined_character_literal_0wide_char_constant, + {rule::user_defined_character_literal::wide_char_constant, TOKEN_GUARD(wide_char_constant, isCharUserDefined(Tok))}, - {(RuleID)Rule::character_literal_0char_constant, + {rule::character_literal::char_constant, TOKEN_GUARD(char_constant, !isCharUserDefined(Tok))}, - {(RuleID)Rule::character_literal_0utf8_char_constant, + {rule::character_literal::utf8_char_constant, TOKEN_GUARD(utf8_char_constant, !isCharUserDefined(Tok))}, - {(RuleID)Rule::character_literal_0utf16_char_constant, + {rule::character_literal::utf16_char_constant, TOKEN_GUARD(utf16_char_constant, !isCharUserDefined(Tok))}, - {(RuleID)Rule::character_literal_0utf32_char_constant, + {rule::character_literal::utf32_char_constant, TOKEN_GUARD(utf32_char_constant, !isCharUserDefined(Tok))}, - {(RuleID)Rule::character_literal_0wide_char_constant, + {rule::character_literal::wide_char_constant, TOKEN_GUARD(wide_char_constant, !isCharUserDefined(Tok))}, // clang just has one NUMERIC_CONSTANT token for {ud,plain}x{float,int} - {(RuleID)Rule::user_defined_integer_literal_0numeric_constant, + {rule::user_defined_integer_literal::numeric_constant, TOKEN_GUARD(numeric_constant, numKind(Tok) == (Integer | UserDefined))}, - {(RuleID)Rule::user_defined_floating_point_literal_0numeric_constant, + {rule::user_defined_floating_point_literal::numeric_constant, TOKEN_GUARD(numeric_constant, numKind(Tok) == (Floating | UserDefined))}, - {(RuleID)Rule::integer_literal_0numeric_constant, + {rule::integer_literal::numeric_constant, TOKEN_GUARD(numeric_constant, numKind(Tok) == Integer)}, - {(RuleID)Rule::floating_point_literal_0numeric_constant, + {rule::floating_point_literal::numeric_constant, TOKEN_GUARD(numeric_constant, numKind(Tok) == Floating)}, }; #undef TOKEN_GUARD @@ -379,7 +377,7 @@ llvm::DenseMap buildRecoveryStrategies() { return { - {(ExtensionID)Extension::Brackets, recoverBrackets}, + {Extension::Brackets, recoverBrackets}, }; } diff --git a/clang-tools-extra/pseudo/lib/grammar/Grammar.cpp b/clang-tools-extra/pseudo/lib/grammar/Grammar.cpp --- a/clang-tools-extra/pseudo/lib/grammar/Grammar.cpp +++ b/clang-tools-extra/pseudo/lib/grammar/Grammar.cpp @@ -45,28 +45,6 @@ return T->Nonterminals[SID].Name; } -std::string Grammar::mangleSymbol(SymbolID SID) const { - static const char *const TokNames[] = { -#define TOK(X) #X, -#define KEYWORD(X, Y) #X, -#include "clang/Basic/TokenKinds.def" - nullptr}; - if (clang::pseudo::isToken(SID)) - return TokNames[clang::pseudo::symbolToToken(SID)]; - std::string Name = symbolName(SID).str(); - // translation-unit -> translation_unit - std::replace(Name.begin(), Name.end(), '-', '_'); - return Name; -} - -std::string Grammar::mangleRule(RuleID RID) const { - const auto &R = lookupRule(RID); - std::string MangleName = mangleSymbol(R.Target); - for (size_t I = 0; I < R.seq().size(); ++I) - MangleName += llvm::formatv("_{0}{1}", I, mangleSymbol(R.seq()[I])); - return MangleName; -} - llvm::Optional Grammar::findNonterminal(llvm::StringRef Name) const { auto It = llvm::partition_point( T->Nonterminals, diff --git a/clang-tools-extra/pseudo/unittests/GrammarTest.cpp b/clang-tools-extra/pseudo/unittests/GrammarTest.cpp --- a/clang-tools-extra/pseudo/unittests/GrammarTest.cpp +++ b/clang-tools-extra/pseudo/unittests/GrammarTest.cpp @@ -113,15 +113,16 @@ build(R"bnf( _ := declaration - declaration := ptr-declarator ; + declaration := cv-qualifier ptr-declarator ; ptr-declarator := * IDENTIFIER + cv-qualifier := CONST )bnf"); ASSERT_TRUE(Diags.empty()); EXPECT_EQ(G.mangleRule(ruleFor("declaration")), - "declaration_0ptr_declarator_1semi"); - EXPECT_EQ(G.mangleRule(ruleFor("ptr-declarator")), - "ptr_declarator_0star_1identifier"); + "cv_qualifier__ptr_declarator__semi"); + EXPECT_EQ(G.mangleRule(ruleFor("ptr-declarator")), "star__identifier"); + EXPECT_EQ(G.mangleRule(ruleFor("cv-qualifier")), "CONST"); } TEST_F(GrammarTest, Diagnostics) {