decl_introducer_state.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef CARBON_TOOLCHAIN_CHECK_DECL_INTRODUCER_STATE_H_
  5. #define CARBON_TOOLCHAIN_CHECK_DECL_INTRODUCER_STATE_H_
  6. #include "toolchain/check/keyword_modifier_set.h"
  7. #include "toolchain/lex/token_kind.h"
  8. #include "toolchain/parse/node_ids.h"
  9. namespace Carbon::Check {
  10. // State stored for each declaration we are introducing: the kind of
  11. // declaration and the keyword modifiers that apply to that declaration
  12. // introducer.
  13. struct DeclIntroducerState {
  14. auto modifier_node_id(ModifierOrder order) const -> Parse::NodeId {
  15. return ordered_modifier_node_ids[static_cast<int8_t>(order)];
  16. }
  17. auto set_modifier_node_id(ModifierOrder order, Parse::NodeId node_id)
  18. -> void {
  19. ordered_modifier_node_ids[static_cast<int8_t>(order)] = node_id;
  20. }
  21. // The token kind of the introducer.
  22. Lex::TokenKind kind;
  23. // Nodes of modifiers on this declaration, in expected order. `None` if no
  24. // modifier of that kind is present.
  25. Parse::NodeId
  26. ordered_modifier_node_ids[static_cast<int8_t>(ModifierOrder::Decl) + 1] =
  27. {Parse::NodeId::None, Parse::NodeId::None, Parse::NodeId::None};
  28. // Invariant: contains just the modifiers represented by `saw_*_modifier`.
  29. KeywordModifierSet modifier_set = KeywordModifierSet();
  30. // If there's an `extern library` in use, the library name.
  31. SemIR::LibraryNameId extern_library = SemIR::LibraryNameId::None;
  32. };
  33. // Stack of `DeclIntroducerState` values, representing all the declaration
  34. // introducers we are currently nested within. Commonly size 0 or 1, as nested
  35. // introducers are rare.
  36. class DeclIntroducerStateStack {
  37. private:
  38. // Returns true for introducer tokens. Supports Push/Pop `requires`.
  39. template <Lex::TokenKind::RawEnumType Kind>
  40. static constexpr auto IsDeclIntroducer() -> bool {
  41. switch (Kind) {
  42. #define CARBON_TOKEN(...)
  43. #define CARBON_DECL_INTRODUCER_TOKEN(Name, ...) case Lex::TokenKind::Name:
  44. #include "toolchain/lex/token_kind.def"
  45. return true;
  46. default:
  47. return false;
  48. }
  49. }
  50. public:
  51. // Begins a declaration introducer `Kind`.
  52. template <Lex::TokenKind::RawEnumType Kind>
  53. requires(IsDeclIntroducer<Kind>())
  54. auto Push() -> void {
  55. stack_.push_back({.kind = Lex::TokenKind::Make(Kind)});
  56. }
  57. // Gets the state of declaration at the top of the stack -- the innermost
  58. // declaration currently being processed.
  59. auto innermost() -> DeclIntroducerState& { return stack_.back(); }
  60. // Finishes a declaration introducer `Kind` and returns the produced state.
  61. template <Lex::TokenKind::RawEnumType Kind>
  62. requires(IsDeclIntroducer<Kind>())
  63. auto Pop() -> DeclIntroducerState {
  64. CARBON_CHECK(stack_.back().kind == Kind, "Found: {0} expected: {1}",
  65. stack_.back().kind, Lex::TokenKind::Make(Kind));
  66. return stack_.pop_back_val();
  67. }
  68. private:
  69. llvm::SmallVector<DeclIntroducerState> stack_;
  70. };
  71. } // namespace Carbon::Check
  72. #endif // CARBON_TOOLCHAIN_CHECK_DECL_INTRODUCER_STATE_H_