decl_introducer_state.h 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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::Last) + 1] =
  27. {Parse::NodeId::None, Parse::NodeId::None, Parse::NodeId::None,
  28. Parse::NodeId::None, Parse::NodeId::None};
  29. // Invariant: contains just the modifiers represented by `saw_*_modifier`.
  30. KeywordModifierSet modifier_set = KeywordModifierSet();
  31. // If there's an `extern library` in use, the library name.
  32. SemIR::LibraryNameId extern_library = SemIR::LibraryNameId::None;
  33. };
  34. // Stack of `DeclIntroducerState` values, representing all the declaration
  35. // introducers we are currently nested within. Commonly size 0 or 1, as nested
  36. // introducers are rare.
  37. class DeclIntroducerStateStack {
  38. private:
  39. // Returns true for introducer tokens. Supports Push/Pop `requires`.
  40. template <Lex::TokenKind::RawEnumType Kind>
  41. static constexpr auto IsDeclIntroducer() -> bool {
  42. switch (Kind) {
  43. #define CARBON_TOKEN(...)
  44. #define CARBON_DECL_INTRODUCER_TOKEN(Name, ...) case Lex::TokenKind::Name:
  45. #include "toolchain/lex/token_kind.def"
  46. return true;
  47. default:
  48. return false;
  49. }
  50. }
  51. public:
  52. // Begins a declaration introducer `Kind`.
  53. template <Lex::TokenKind::RawEnumType Kind>
  54. requires(IsDeclIntroducer<Kind>())
  55. auto Push() -> void {
  56. stack_.push_back({.kind = Lex::TokenKind::Make(Kind)});
  57. }
  58. // Gets the state of declaration at the top of the stack -- the innermost
  59. // declaration currently being processed.
  60. auto innermost() -> DeclIntroducerState& { return stack_.back(); }
  61. // Finishes a declaration introducer `Kind` and returns the produced state.
  62. template <Lex::TokenKind::RawEnumType Kind>
  63. requires(IsDeclIntroducer<Kind>())
  64. auto Pop() -> DeclIntroducerState {
  65. CARBON_CHECK(stack_.back().kind == Kind, "Found: {0} expected: {1}",
  66. stack_.back().kind, Lex::TokenKind::Make(Kind));
  67. return stack_.pop_back_val();
  68. }
  69. // Runs verification that the processing cleanly finished.
  70. auto VerifyOnFinish() const -> void {
  71. CARBON_CHECK(stack_.empty(),
  72. "decl_introduce_state_stack still has {0} entries",
  73. stack_.size());
  74. }
  75. private:
  76. llvm::SmallVector<DeclIntroducerState> stack_;
  77. };
  78. } // namespace Carbon::Check
  79. #endif // CARBON_TOOLCHAIN_CHECK_DECL_INTRODUCER_STATE_H_