text: //------------------------------------------------------------------------------
  // SyntaxFacts.cpp
  // Various syntax-related utility methods
  //
  // File is under the MIT license; see LICENSE for details
  //------------------------------------------------------------------------------
  #include "slang/syntax/SyntaxFacts.h"
  
  #include "slang/syntax/AllSyntax.h"
  
  namespace slang {
  
  string_view SyntaxFacts::getSimpleTypeName(const DataTypeSyntax& syntax) {
      if (syntax.kind == SyntaxKind::NamedType) {
          auto& namedType = syntax.as<NamedTypeSyntax>();
          if (namedType.name->kind == SyntaxKind::IdentifierName)
              return namedType.name->as<IdentifierNameSyntax>().identifier.valueText();
      }
      return "";
  }
  
  // clang-format off
  SyntaxKind SyntaxFacts::getUnaryPrefixExpression(TokenKind kind) {
      switch (kind) {
          case TokenKind::Plus: return SyntaxKind::UnaryPlusExpression;
          case TokenKind::Minus: return SyntaxKind::UnaryMinusExpression;
          case TokenKind::And: return SyntaxKind::UnaryBitwiseAndExpression;
          case TokenKind::TildeAnd: return SyntaxKind::UnaryBitwiseNandExpression;
          case TokenKind::Or: return SyntaxKind::UnaryBitwiseOrExpression;
          case TokenKind::TildeOr: return SyntaxKind::UnaryBitwiseNorExpression;
          case TokenKind::Xor: return SyntaxKind::UnaryBitwiseXorExpression;
          case TokenKind::XorTilde:
          case TokenKind::TildeXor:
              return SyntaxKind::UnaryBitwiseXnorExpression;
          case TokenKind::DoublePlus: return SyntaxKind::UnaryPreincrementExpression;
          case TokenKind::DoubleMinus: return SyntaxKind::UnaryPredecrementExpression;
          case TokenKind::Tilde: return SyntaxKind::UnaryBitwiseNotExpression;
          case TokenKind::Exclamation: return SyntaxKind::UnaryLogicalNotExpression;
          default:
              return SyntaxKind::Unknown;
      }
  }
  
  SyntaxKind SyntaxFacts::getUnaryPostfixExpression(TokenKind kind) {
      switch (kind) {
          case TokenKind::DoublePlus: return SyntaxKind::PostincrementExpression;
          case TokenKind::DoubleMinus: return SyntaxKind::PostdecrementExpression;
          default: return SyntaxKind::Unknown;
      }
  }
  
  SyntaxKind SyntaxFacts::getLiteralExpression(TokenKind kind) {
      switch (kind) {
          case TokenKind::StringLiteral: return SyntaxKind::StringLiteralExpression;
          case TokenKind::IntegerLiteral: return SyntaxKind::IntegerLiteralExpression;
          case TokenKind::UnbasedUnsizedLiteral: return SyntaxKind::UnbasedUnsizedLiteralExpression;
          case TokenKind::RealLiteral: return SyntaxKind::RealLiteralExpression;
          case TokenKind::TimeLiteral: return SyntaxKind::TimeLiteralExpression;
          case TokenKind::NullKeyword: return SyntaxKind::NullLiteralExpression;
          case TokenKind::Dollar: return SyntaxKind::WildcardLiteralExpression;
          default: return SyntaxKind::Unknown;
      }
  }
  
  SyntaxKind SyntaxFacts::getBinaryExpression(TokenKind kind) {
      switch (kind) {
          case TokenKind::Plus: return SyntaxKind::AddExpression;
          case TokenKind::Minus: return SyntaxKind::SubtractExpression;
          case TokenKind::Star: return SyntaxKind::MultiplyExpression;
          case TokenKind::Slash: return SyntaxKind::DivideExpression;
          case TokenKind::Percent: return SyntaxKind::ModExpression;
          case TokenKind::DoubleStar: return SyntaxKind::PowerExpression;
          case TokenKind::DoubleEquals: return SyntaxKind::EqualityExpression;
          case TokenKind::ExclamationEquals: return SyntaxKind::InequalityExpression;
          case TokenKind::TripleEquals: return SyntaxKind::CaseEqualityExpression;
          case TokenKind::ExclamationDoubleEquals: return SyntaxKind::CaseInequalityExpression;
          case TokenKind::DoubleEqualsQuestion: return SyntaxKind::WildcardEqualityExpression;
          case TokenKind::ExclamationEqualsQuestion: return SyntaxKind::WildcardInequalityExpression;
          case TokenKind::DoubleAnd: return SyntaxKind::LogicalAndExpression;
          case TokenKind::DoubleOr: return SyntaxKind::LogicalOrExpression;
          case TokenKind::MinusArrow: return SyntaxKind::LogicalImplicationExpression;
          case TokenKind::LessThanMinusArrow: return SyntaxKind::LogicalEquivalenceExpression;
          case TokenKind::LessThan: return SyntaxKind::LessThanExpression;
          case TokenKind::LessThanEquals: return SyntaxKind::LessThanEqualExpression;
          case TokenKind::GreaterThan: return SyntaxKind::GreaterThanExpression;
          case TokenKind::GreaterThanEquals: return SyntaxKind::GreaterThanEqualExpression;
          case TokenKind::And: return SyntaxKind::BinaryAndExpression;
          case TokenKind::Or: return SyntaxKind::BinaryOrExpression;
          case TokenKind::Xor: return SyntaxKind::BinaryXorExpression;
          case TokenKind::XorTilde: return SyntaxKind::BinaryXnorExpression;
          case TokenKind::TildeXor: return SyntaxKind::BinaryXnorExpression;
          case TokenKind::RightShift: return SyntaxKind::LogicalShiftRightExpression;
          case TokenKind::TripleRightShift: return SyntaxKind::ArithmeticShiftRightExpression;
          case TokenKind::LeftShift: return SyntaxKind::LogicalShiftLeftExpression;
          case TokenKind::TripleLeftShift: return SyntaxKind::ArithmeticShiftLeftExpression;
          case TokenKind::InsideKeyword: return SyntaxKind::InsideExpression;
          case TokenKind::Equals: return SyntaxKind::AssignmentExpression;
          case TokenKind::PlusEqual: return SyntaxKind::AddAssignmentExpression;
          case TokenKind::MinusEqual: return SyntaxKind::SubtractAssignmentExpression;
          case TokenKind::StarEqual: return SyntaxKind::MultiplyAssignmentExpression;
          case TokenKind::SlashEqual: return SyntaxKind::DivideAssignmentExpression;
          case TokenKind::PercentEqual: return SyntaxKind::ModAssignmentExpression;
          case TokenKind::AndEqual: return SyntaxKind::AndAssignmentExpression;
          case TokenKind::OrEqual: return SyntaxKind::OrAssignmentExpression;
          case TokenKind::XorEqual: return SyntaxKind::XorAssignmentExpression;
          case TokenKind::LeftShiftEqual: return SyntaxKind::LogicalLeftShiftAssignmentExpression;
          case TokenKind::TripleLeftShiftEqual: return SyntaxKind::ArithmeticLeftShiftAssignmentExpression;
          case TokenKind::RightShiftEqual: return SyntaxKind::LogicalRightShiftAssignmentExpression;
          case TokenKind::TripleRightShiftEqual: return SyntaxKind::ArithmeticRightShiftAssignmentExpression;
          default: return SyntaxKind::Unknown;
      }
  }
  
  SyntaxKind SyntaxFacts::getBinarySequenceExpr(TokenKind kind) {
      switch (kind) {
          case TokenKind::AndKeyword: return SyntaxKind::AndSequenceExpr;
          case TokenKind::OrKeyword: return SyntaxKind::OrSequenceExpr;
          case TokenKind::IntersectKeyword: return SyntaxKind::IntersectSequenceExpr;
          case TokenKind::ThroughoutKeyword: return SyntaxKind::ThroughoutSequenceExpr;
          case TokenKind::WithinKeyword: return SyntaxKind::WithinSequenceExpr;
          default: return SyntaxKind::Unknown;
      }
  }
  
  SyntaxKind SyntaxFacts::getBinaryPropertyExpr(TokenKind kind) {
      switch (kind) {
          case TokenKind::AndKeyword: return SyntaxKind::AndPropertyExpr;
          case TokenKind::OrKeyword: return SyntaxKind::OrPropertyExpr;
          case TokenKind::IffKeyword: return SyntaxKind::IffPropertyExpr;
          case TokenKind::UntilKeyword: return SyntaxKind::UntilPropertyExpr;
          case TokenKind::SUntilKeyword: return SyntaxKind::SUntilPropertyExpr;
          case TokenKind::UntilWithKeyword: return SyntaxKind::UntilWithPropertyExpr;
          case TokenKind::SUntilWithKeyword: return SyntaxKind::SUntilWithPropertyExpr;
          case TokenKind::ImpliesKeyword: return SyntaxKind::ImpliesPropertyExpr;
          case TokenKind::OrMinusArrow: return SyntaxKind::ImplicationPropertyExpr;
          case TokenKind::OrEqualsArrow: return SyntaxKind::ImplicationPropertyExpr;
          case TokenKind::HashMinusHash: return SyntaxKind::FollowedByPropertyExpr;
          case TokenKind::HashEqualsHash: return SyntaxKind::FollowedByPropertyExpr;
          default: return SyntaxKind::Unknown;
      }
  }
  
  SyntaxKind SyntaxFacts::getKeywordNameExpression(TokenKind kind) {
      switch (kind) {
          case TokenKind::UnitSystemName: return SyntaxKind::UnitScope;
          case TokenKind::RootSystemName: return SyntaxKind::RootScope;
          case TokenKind::LocalKeyword: return SyntaxKind::LocalScope;
          case TokenKind::ThisKeyword: return SyntaxKind::ThisHandle;
          case TokenKind::SuperKeyword: return SyntaxKind::SuperHandle;
          case TokenKind::UniqueKeyword: return SyntaxKind::ArrayUniqueMethod;
          case TokenKind::AndKeyword: return SyntaxKind::ArrayAndMethod;
          case TokenKind::OrKeyword: return SyntaxKind::ArrayOrMethod;
          case TokenKind::XorKeyword: return SyntaxKind::ArrayXorMethod;
          case TokenKind::NewKeyword: return SyntaxKind::ConstructorName;
          default: return SyntaxKind::Unknown;
      }
  }
  
  bool SyntaxFacts::isSpecialMethodName(SyntaxKind kind) {
      switch (kind) {
          case SyntaxKind::ArrayUniqueMethod:
          case SyntaxKind::ArrayAndMethod:
          case SyntaxKind::ArrayOrMethod:
          case SyntaxKind::ArrayXorMethod:
              return true;
          default:
              return false;
          }
      }
  
  int SyntaxFacts::getPrecedence(SyntaxKind kind) {
      switch (kind) {
          case SyntaxKind::AssignmentExpression:
          case SyntaxKind::AddAssignmentExpression:
          case SyntaxKind::SubtractAssignmentExpression:
          case SyntaxKind::MultiplyAssignmentExpression:
          case SyntaxKind::DivideAssignmentExpression:
          case SyntaxKind::ModAssignmentExpression:
          case SyntaxKind::AndAssignmentExpression:
          case SyntaxKind::OrAssignmentExpression:
          case SyntaxKind::XorAssignmentExpression:
          case SyntaxKind::LogicalLeftShiftAssignmentExpression:
          case SyntaxKind::LogicalRightShiftAssignmentExpression:
          case SyntaxKind::ArithmeticLeftShiftAssignmentExpression:
          case SyntaxKind::ArithmeticRightShiftAssignmentExpression:
          case SyntaxKind::NonblockingAssignmentExpression:
          case SyntaxKind::ImplicationPropertyExpr:
          case SyntaxKind::FollowedByPropertyExpr:
              return 1;
          case SyntaxKind::LogicalImplicationExpression:
          case SyntaxKind::LogicalEquivalenceExpression:
          case SyntaxKind::UntilPropertyExpr:
          case SyntaxKind::SUntilPropertyExpr:
          case SyntaxKind::UntilWithPropertyExpr:
          case SyntaxKind::SUntilWithPropertyExpr:
          case SyntaxKind::ImpliesPropertyExpr:
              return 2;
          case SyntaxKind::LogicalOrExpression:
          case SyntaxKind::IffPropertyExpr:
              return 3;
          case SyntaxKind::LogicalAndExpression:
          case SyntaxKind::OrPropertyExpr:
          case SyntaxKind::OrSequenceExpr:
              return 4;
          case SyntaxKind::BinaryOrExpression:
          case SyntaxKind::AndPropertyExpr:
          case SyntaxKind::AndSequenceExpr:
              return 5;
          case SyntaxKind::BinaryXorExpression:
          case SyntaxKind::BinaryXnorExpression:
          case SyntaxKind::IntersectSequenceExpr:
              return 6;
          case SyntaxKind::BinaryAndExpression:
          case SyntaxKind::WithinSequenceExpr:
              return 7;
          case SyntaxKind::EqualityExpression:
          case SyntaxKind::InequalityExpression:
          case SyntaxKind::CaseEqualityExpression:
          case SyntaxKind::CaseInequalityExpression:
          case SyntaxKind::WildcardEqualityExpression:
          case SyntaxKind::WildcardInequalityExpression:
          case SyntaxKind::ThroughoutSequenceExpr:
              return 8;
          case SyntaxKind::LessThanExpression:
          case SyntaxKind::LessThanEqualExpression:
          case SyntaxKind::GreaterThanExpression:
          case SyntaxKind::GreaterThanEqualExpression:
          case SyntaxKind::InsideExpression:
              return 9;
          case SyntaxKind::LogicalShiftLeftExpression:
          case SyntaxKind::LogicalShiftRightExpression:
          case SyntaxKind::ArithmeticShiftLeftExpression:
          case SyntaxKind::ArithmeticShiftRightExpression:
              return 10;
          case SyntaxKind::AddExpression:
          case SyntaxKind::SubtractExpression:
              return 11;
          case SyntaxKind::MultiplyExpression:
          case SyntaxKind::DivideExpression:
          case SyntaxKind::ModExpression:
              return 12;
          case SyntaxKind::PowerExpression:
              return 13;
          case SyntaxKind::UnaryPlusExpression:
          case SyntaxKind::UnaryMinusExpression:
          case SyntaxKind::UnaryLogicalNotExpression:
          case SyntaxKind::UnaryBitwiseNotExpression:
          case SyntaxKind::UnaryBitwiseAndExpression:
          case SyntaxKind::UnaryBitwiseNandExpression:
          case SyntaxKind::UnaryBitwiseOrExpression:
          case SyntaxKind::UnaryBitwiseNorExpression:
          case SyntaxKind::UnaryBitwiseXorExpression:
          case SyntaxKind::UnaryBitwiseXnorExpression:
          case SyntaxKind::UnaryPreincrementExpression:
          case SyntaxKind::UnaryPredecrementExpression:
              return 14;
          default:
              return 0;
      }
  }
  
  bool SyntaxFacts::isRightAssociative(SyntaxKind kind) {
      switch (kind) {
          case SyntaxKind::LogicalImplicationExpression:
          case SyntaxKind::LogicalEquivalenceExpression:
          case SyntaxKind::ThroughoutSequenceExpr:
          case SyntaxKind::IffPropertyExpr:
          case SyntaxKind::UntilPropertyExpr:
          case SyntaxKind::SUntilPropertyExpr:
          case SyntaxKind::UntilWithPropertyExpr:
          case SyntaxKind::SUntilWithPropertyExpr:
          case SyntaxKind::ImpliesPropertyExpr:
          case SyntaxKind::ImplicationPropertyExpr:
          case SyntaxKind::FollowedByPropertyExpr:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isPossibleDataType(TokenKind kind) {
      switch (kind) {
          case TokenKind::BitKeyword:
          case TokenKind::LogicKeyword:
          case TokenKind::RegKeyword:
          case TokenKind::ByteKeyword:
          case TokenKind::ShortIntKeyword:
          case TokenKind::IntKeyword:
          case TokenKind::LongIntKeyword:
          case TokenKind::IntegerKeyword:
          case TokenKind::TimeKeyword:
          case TokenKind::ShortRealKeyword:
          case TokenKind::RealKeyword:
          case TokenKind::RealTimeKeyword:
          case TokenKind::StringKeyword:
          case TokenKind::ConstKeyword:
          case TokenKind::SignedKeyword:
          case TokenKind::UnsignedKeyword:
          case TokenKind::StructKeyword:
          case TokenKind::UnionKeyword:
          case TokenKind::EnumKeyword:
          case TokenKind::CHandleKeyword:
          case TokenKind::VirtualKeyword:
          case TokenKind::EventKeyword:
          case TokenKind::TypeKeyword:
          case TokenKind::VoidKeyword:
          case TokenKind::Identifier:
          case TokenKind::UnitSystemName:
          case TokenKind::OpenBracket:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isPossibleExpression(TokenKind kind) {
      switch (kind) {
          case TokenKind::TaggedKeyword:
          case TokenKind::StringLiteral:
          case TokenKind::IntegerLiteral:
          case TokenKind::UnbasedUnsizedLiteral:
          case TokenKind::IntegerBase:
          case TokenKind::RealLiteral:
          case TokenKind::TimeLiteral:
          case TokenKind::NullKeyword:
          case TokenKind::Dollar:
          case TokenKind::LocalKeyword:
          case TokenKind::OpenParenthesis:
          case TokenKind::OpenBrace:
          case TokenKind::OpenBracket:
          case TokenKind::UnitSystemName:
          case TokenKind::ThisKeyword:
          case TokenKind::SuperKeyword:
          case TokenKind::Identifier:
          case TokenKind::SystemIdentifier:
          case TokenKind::RootSystemName:
          case TokenKind::Hash:
          case TokenKind::DoubleHash:
          case TokenKind::At:
          case TokenKind::RepeatKeyword:
          case TokenKind::TypeKeyword:
          case TokenKind::ApostropheOpenBrace:
              // expressions can't actually start with these, but we'll allow it
              // to provide good error handling
          case TokenKind::DoubleColon:
          case TokenKind::Question:
          case TokenKind::MatchesKeyword:
          case TokenKind::TripleAnd:
          case TokenKind::InsideKeyword:
          case TokenKind::DistKeyword:
              return true;
          default:
              break;
      }
  
      if (isPossibleDataType(kind))
          return true;
  
      SyntaxKind opKind = getUnaryPrefixExpression(kind);
      if (opKind != SyntaxKind::Unknown)
          return true;
  
      opKind = getBinaryExpression(kind);
      if (opKind != SyntaxKind::Unknown)
          return true;
  
      return false;
  }
  
  bool SyntaxFacts::isPossibleStatement(TokenKind kind) {
      switch (kind) {
          case TokenKind::Identifier:
          case TokenKind::SystemIdentifier:
          case TokenKind::ThisKeyword:
          case TokenKind::SuperKeyword:
          case TokenKind::UnitSystemName:
          case TokenKind::RootSystemName:
          case TokenKind::OpenBrace:
          case TokenKind::ApostropheOpenBrace:
          case TokenKind::AssignKeyword:
          case TokenKind::DeassignKeyword:
          case TokenKind::ForceKeyword:
          case TokenKind::ReleaseKeyword:
          case TokenKind::UniqueKeyword:
          case TokenKind::Unique0Keyword:
          case TokenKind::PriorityKeyword:
          case TokenKind::CaseKeyword:
          case TokenKind::CaseXKeyword:
          case TokenKind::CaseZKeyword:
          case TokenKind::IfKeyword:
          case TokenKind::DoublePlus:
          case TokenKind::DoubleMinus:
          case TokenKind::VoidKeyword:
          case TokenKind::TypeKeyword:
          case TokenKind::DisableKeyword:
          case TokenKind::MinusArrow:
          case TokenKind::MinusDoubleArrow:
          case TokenKind::ForeverKeyword:
          case TokenKind::RepeatKeyword:
          case TokenKind::WhileKeyword:
          case TokenKind::ForKeyword:
          case TokenKind::DoKeyword:
          case TokenKind::ForeachKeyword:
          case TokenKind::ReturnKeyword:
          case TokenKind::BreakKeyword:
          case TokenKind::ContinueKeyword:
          case TokenKind::ForkKeyword:
          case TokenKind::Hash:
          case TokenKind::DoubleHash:
          case TokenKind::At:
          case TokenKind::BeginKeyword:
          case TokenKind::WaitKeyword:
          case TokenKind::WaitOrderKeyword:
          case TokenKind::AssertKeyword:
          case TokenKind::AssumeKeyword:
          case TokenKind::CoverKeyword:
          case TokenKind::RestrictKeyword:
          case TokenKind::RandSequenceKeyword:
          case TokenKind::RandCaseKeyword:
          case TokenKind::ExpectKeyword:
          case TokenKind::OpenParenthesisStar:
          case TokenKind::Semicolon:
              return true;
          default:
              return false;
      }
  }
  
  SyntaxKind SyntaxFacts::getIntegerType(TokenKind kind) {
      switch (kind) {
          case TokenKind::BitKeyword: return SyntaxKind::BitType;
          case TokenKind::LogicKeyword: return SyntaxKind::LogicType;
          case TokenKind::RegKeyword: return SyntaxKind::RegType;
          case TokenKind::ByteKeyword: return SyntaxKind::ByteType;
          case TokenKind::ShortIntKeyword: return SyntaxKind::ShortIntType;
          case TokenKind::IntKeyword: return SyntaxKind::IntType;
          case TokenKind::LongIntKeyword: return SyntaxKind::LongIntType;
          case TokenKind::IntegerKeyword: return SyntaxKind::IntegerType;
          case TokenKind::TimeKeyword: return SyntaxKind::TimeType;
          default: return SyntaxKind::Unknown;
      }
  }
  
  SyntaxKind SyntaxFacts::getKeywordType(TokenKind kind) {
      switch (kind) {
          case TokenKind::ShortRealKeyword: return SyntaxKind::ShortRealType;
          case TokenKind::RealKeyword: return SyntaxKind::RealType;
          case TokenKind::RealTimeKeyword: return SyntaxKind::RealTimeType;
          case TokenKind::StringKeyword: return SyntaxKind::StringType;
          case TokenKind::CHandleKeyword: return SyntaxKind::CHandleType;
          case TokenKind::EventKeyword: return SyntaxKind::EventType;
          case TokenKind::VoidKeyword: return SyntaxKind::VoidType;
          default: return SyntaxKind::Unknown;
      }
  }
  
  SyntaxKind SyntaxFacts::getProceduralBlockKind(TokenKind kind) {
      switch (kind) {
          case TokenKind::InitialKeyword: return SyntaxKind::InitialBlock;
          case TokenKind::FinalKeyword: return SyntaxKind::FinalBlock;
          case TokenKind::AlwaysKeyword: return SyntaxKind::AlwaysBlock;
          case TokenKind::AlwaysCombKeyword: return SyntaxKind::AlwaysCombBlock;
          case TokenKind::AlwaysFFKeyword: return SyntaxKind::AlwaysFFBlock;
          case TokenKind::AlwaysLatchKeyword: return SyntaxKind::AlwaysLatchBlock;
          default: return SyntaxKind::Unknown;
      }
  }
  
  SyntaxKind SyntaxFacts::getModuleHeaderKind(TokenKind kind) {
      switch (kind) {
          case TokenKind::ModuleKeyword: return SyntaxKind::ModuleHeader;
          case TokenKind::MacromoduleKeyword: return SyntaxKind::ModuleHeader;
          case TokenKind::ProgramKeyword: return SyntaxKind::ProgramHeader;
          case TokenKind::InterfaceKeyword: return SyntaxKind::InterfaceHeader;
          case TokenKind::PackageKeyword: return SyntaxKind::PackageHeader;
          default: return SyntaxKind::Unknown;
      }
  }
  
  SyntaxKind SyntaxFacts::getModuleDeclarationKind(TokenKind kind) {
      switch (kind) {
          case TokenKind::ModuleKeyword: return SyntaxKind::ModuleDeclaration;
          case TokenKind::MacromoduleKeyword: return SyntaxKind::ModuleDeclaration;
          case TokenKind::ProgramKeyword: return SyntaxKind::ProgramDeclaration;
          case TokenKind::InterfaceKeyword: return SyntaxKind::InterfaceDeclaration;
          case TokenKind::PackageKeyword: return SyntaxKind::PackageDeclaration;
          default: return SyntaxKind::Unknown;
      }
  }
  
  TokenKind SyntaxFacts::getModuleEndKind(TokenKind kind) {
      switch (kind) {
          case TokenKind::ModuleKeyword: return TokenKind::EndModuleKeyword;
          case TokenKind::MacromoduleKeyword: return TokenKind::EndModuleKeyword;
          case TokenKind::ProgramKeyword: return TokenKind::EndProgramKeyword;
          case TokenKind::InterfaceKeyword: return TokenKind::EndInterfaceKeyword;
          case TokenKind::PackageKeyword: return TokenKind::EndPackageKeyword;
          default: return TokenKind::Unknown;
      }
  }
  
  TokenKind SyntaxFacts::getDelimCloseKind(TokenKind kind) {
      switch (kind) {
          case TokenKind::OpenParenthesis: return TokenKind::CloseParenthesis;
          case TokenKind::OpenBrace: return TokenKind::CloseBrace;
          case TokenKind::OpenBracket: return TokenKind::CloseBracket;
          case TokenKind::ApostropheOpenBrace: return TokenKind::CloseBrace;
          case TokenKind::OpenParenthesisStar: return TokenKind::StarCloseParenthesis;
          default: return TokenKind::Unknown;
      }
  }
  
  TokenKind SyntaxFacts::getSkipToKind(TokenKind kind) {
      switch (kind) {
          case TokenKind::OpenParenthesis: return TokenKind::CloseParenthesis;
          case TokenKind::OpenBrace: return TokenKind::CloseBrace;
          case TokenKind::OpenBracket: return TokenKind::CloseBracket;
          case TokenKind::ApostropheOpenBrace: return TokenKind::CloseBrace;
          case TokenKind::OpenParenthesisStar: return TokenKind::StarCloseParenthesis;
          case TokenKind::BeginKeyword: return TokenKind::EndKeyword;
          case TokenKind::CaseKeyword: return TokenKind::EndCaseKeyword;
          case TokenKind::CheckerKeyword: return TokenKind::EndCheckerKeyword;
          case TokenKind::ClassKeyword: return TokenKind::EndClassKeyword;
          case TokenKind::ClockingKeyword: return TokenKind::EndClockingKeyword;
          case TokenKind::ConfigKeyword: return TokenKind::EndConfigKeyword;
          case TokenKind::ForkKeyword: return TokenKind::JoinKeyword;
          case TokenKind::FunctionKeyword: return TokenKind::EndFunctionKeyword;
          case TokenKind::GenerateKeyword: return TokenKind::EndGenerateKeyword;
          case TokenKind::CoverGroupKeyword: return TokenKind::EndGroupKeyword;
          case TokenKind::InterfaceKeyword: return TokenKind::EndInterfaceKeyword;
          case TokenKind::ModuleKeyword: return TokenKind::EndModuleKeyword;
          case TokenKind::MacromoduleKeyword: return TokenKind::EndModuleKeyword;
          case TokenKind::PackageKeyword: return TokenKind::EndPackageKeyword;
          case TokenKind::PrimitiveKeyword: return TokenKind::EndPrimitiveKeyword;
          case TokenKind::ProgramKeyword: return TokenKind::EndProgramKeyword;
          case TokenKind::PropertyKeyword: return TokenKind::EndPropertyKeyword;
          case TokenKind::SpecifyKeyword: return TokenKind::EndSpecifyKeyword;
          case TokenKind::SequenceKeyword: return TokenKind::EndSequenceKeyword;
          case TokenKind::TableKeyword: return TokenKind::EndTableKeyword;
          case TokenKind::TaskKeyword: return TokenKind::EndTaskKeyword;
          default:
              return TokenKind::Unknown;
      }
  }
  
  bool SyntaxFacts::isNetType(TokenKind kind) {
      switch (kind) {
          case TokenKind::Supply0Keyword:
          case TokenKind::Supply1Keyword:
          case TokenKind::TriKeyword:
          case TokenKind::TriAndKeyword:
          case TokenKind::TriOrKeyword:
          case TokenKind::TriRegKeyword:
          case TokenKind::Tri0Keyword:
          case TokenKind::Tri1Keyword:
          case TokenKind::UWireKeyword:
          case TokenKind::WireKeyword:
          case TokenKind::WAndKeyword:
          case TokenKind::WOrKeyword:
          case TokenKind::InterconnectKeyword:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isPortDirection(TokenKind kind) {
      switch (kind) {
          case TokenKind::InputKeyword:
          case TokenKind::OutputKeyword:
          case TokenKind::InOutKeyword:
          case TokenKind::RefKeyword:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isPossibleArgument(TokenKind kind) {
      // allow a comma here to handle cases like:  foo(, 3);
      switch (kind) {
          case TokenKind::Dot:
          case TokenKind::Comma:
              return true;
          default:
              return isPossibleExpression(kind);
      }
  }
  
  bool SyntaxFacts::isPossibleParamAssignment(TokenKind kind) {
      // allow a comma here to handle cases like:  foo #(, 3);
      switch (kind) {
          case TokenKind::Dot:
          case TokenKind::Comma:
              return true;
          default:
              return isPossibleExpression(kind);
      }
  }
  
  bool SyntaxFacts::isPossibleNonAnsiPort(TokenKind kind) {
      switch (kind) {
          case TokenKind::Dot:
          case TokenKind::Comma:
          case TokenKind::Identifier:
          case TokenKind::OpenBrace:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isPossibleAnsiPort(TokenKind kind) {
      switch (kind) {
          case TokenKind::InterfaceKeyword:
          case TokenKind::Identifier:
          case TokenKind::Dot:
          case TokenKind::Comma:
          case TokenKind::InputKeyword:
          case TokenKind::OutputKeyword:
          case TokenKind::InOutKeyword:
          case TokenKind::RefKeyword:
          case TokenKind::VarKeyword:
          case TokenKind::OpenParenthesisStar:
              return true;
          default:
              return isNetType(kind) || isPossibleDataType(kind);
      }
  }
  
  bool SyntaxFacts::isPossibleUdpPort(TokenKind kind) {
      switch (kind) {
          case TokenKind::Identifier:
          case TokenKind::InputKeyword:
          case TokenKind::OutputKeyword:
          case TokenKind::RegKeyword:
          case TokenKind::Comma:
          case TokenKind::OpenParenthesisStar:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isPossibleModportPort(TokenKind kind) {
      switch (kind) {
          case TokenKind::OpenParenthesisStar:
          case TokenKind::InputKeyword:
          case TokenKind::OutputKeyword:
          case TokenKind::InOutKeyword:
          case TokenKind::RefKeyword:
          case TokenKind::ClockingKeyword:
          case TokenKind::ImportKeyword:
          case TokenKind::ExportKeyword:
          case TokenKind::Comma:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isPossibleFunctionPort(TokenKind kind) {
      switch (kind) {
          case TokenKind::Identifier:
          case TokenKind::Comma:
          case TokenKind::InputKeyword:
          case TokenKind::OutputKeyword:
          case TokenKind::InOutKeyword:
          case TokenKind::RefKeyword:
          case TokenKind::VarKeyword:
          case TokenKind::ConstKeyword:
          case TokenKind::OpenParenthesisStar:
              return true;
          default:
              return isPossibleDataType(kind);
      }
  }
  
  bool SyntaxFacts::isComma(TokenKind kind) {
      return kind == TokenKind::Comma;
  }
  
  bool SyntaxFacts::isSemicolon(TokenKind kind) {
      return kind == TokenKind::Semicolon;
  }
  
  bool SyntaxFacts::isCloseBrace(TokenKind kind) {
      return kind == TokenKind::CloseBrace;
  }
  
  bool SyntaxFacts::isIdentifierOrComma(TokenKind kind) {
      return kind == TokenKind::Identifier || kind == TokenKind::Comma;
  }
  
  bool SyntaxFacts::isNotIdOrComma(TokenKind kind) {
      return kind != TokenKind::Identifier && kind != TokenKind::Comma;
  }
  
  bool SyntaxFacts::isPossibleExpressionOrComma(TokenKind kind) {
      return kind == TokenKind::Comma || isPossibleExpression(kind);
  }
  
  bool SyntaxFacts::isPossibleExpressionOrCommaOrDefault(TokenKind kind) {
      return kind == TokenKind::Comma || kind == TokenKind::DefaultKeyword || isPossibleExpression(kind);
  }
  
  bool SyntaxFacts::isPossibleExpressionOrTripleAnd(TokenKind kind) {
      return kind == TokenKind::TripleAnd || isPossibleExpression(kind);
  }
  
  bool SyntaxFacts::isPossibleExpressionOrEquals(TokenKind kind) {
      return kind == TokenKind::Equals || isPossibleExpression(kind);
  }
  
  bool SyntaxFacts::isPossibleForInitializer(TokenKind kind) {
      return kind == TokenKind::Comma || kind == TokenKind::VarKeyword || isPossibleExpression(kind);
  }
  
  bool SyntaxFacts::isPossibleOpenRangeElement(TokenKind kind) {
      switch (kind) {
          case TokenKind::OpenBracket:
          case TokenKind::Comma:
              return true;
          default:
              return isPossibleExpression(kind);
      }
  }
  
  bool SyntaxFacts::isPossiblePattern(TokenKind kind) {
      switch (kind) {
          case TokenKind::Dot:
          case TokenKind::DotStar:
          case TokenKind::ApostropheOpenBrace:
              return true;
          default:
              return isPossibleExpression(kind);
      }
  }
  
  bool SyntaxFacts::isPossibleDelayOrEventControl(TokenKind kind) {
      switch (kind) {
          case TokenKind::Hash:
          case TokenKind::DoubleHash:
          case TokenKind::At:
          case TokenKind::RepeatKeyword:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isPossibleInstance(TokenKind kind) {
      switch (kind) {
          case TokenKind::Identifier:
          case TokenKind::OpenParenthesis:
          case TokenKind::Comma:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isPossibleUdpEntry(TokenKind kind) {
      switch (kind) {
          case TokenKind::IntegerLiteral:
          case TokenKind::IntegerBase:
          case TokenKind::Question:
          case TokenKind::Colon:
          case TokenKind::Semicolon:
          case TokenKind::Star:
          case TokenKind::Minus:
          case TokenKind::OpenParenthesis:
          case TokenKind::Identifier:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isPossibleRsRule(TokenKind kind) {
      switch (kind) {
          case TokenKind::OpenBrace:
          case TokenKind::IfKeyword:
          case TokenKind::RepeatKeyword:
          case TokenKind::CaseKeyword:
          case TokenKind::Identifier:
          case TokenKind::RandKeyword:
          case TokenKind::Or:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isPossibleParameter(TokenKind kind) {
      switch (kind) {
          case TokenKind::ParameterKeyword:
          case TokenKind::LocalParamKeyword:
          case TokenKind::TypeKeyword:
          case TokenKind::Comma:
              return true;
          default:
              return isPossibleDataType(kind);
      }
  }
  
  bool SyntaxFacts::isPossiblePortConnection(TokenKind kind) {
      switch (kind) {
          case TokenKind::OpenParenthesisStar:
          case TokenKind::DotStar:
          case TokenKind::Dot:
          case TokenKind::Comma:
              return true;
          default:
              return isPossibleExpression(kind);
      }
  }
  
  bool SyntaxFacts::isPossibleVectorDigit(TokenKind kind) {
      switch (kind) {
          case TokenKind::IntegerLiteral:
          case TokenKind::Question:
          case TokenKind::RealLiteral:
          case TokenKind::Identifier:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isEndKeyword(TokenKind kind) {
      switch (kind) {
          case TokenKind::EndKeyword:
          case TokenKind::EndCaseKeyword:
          case TokenKind::EndCheckerKeyword:
          case TokenKind::EndClassKeyword:
          case TokenKind::EndClockingKeyword:
          case TokenKind::EndConfigKeyword:
          case TokenKind::EndFunctionKeyword:
          case TokenKind::EndGenerateKeyword:
          case TokenKind::EndGroupKeyword:
          case TokenKind::EndInterfaceKeyword:
          case TokenKind::EndModuleKeyword:
          case TokenKind::EndPackageKeyword:
          case TokenKind::EndPrimitiveKeyword:
          case TokenKind::EndProgramKeyword:
          case TokenKind::EndPropertyKeyword:
          case TokenKind::EndSpecifyKeyword:
          case TokenKind::EndSequenceKeyword:
          case TokenKind::EndTableKeyword:
          case TokenKind::EndTaskKeyword:
          case TokenKind::JoinAnyKeyword:
          case TokenKind::JoinKeyword:
          case TokenKind::JoinNoneKeyword:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isOpenDelimOrKeyword(TokenKind kind) {
      return getSkipToKind(kind) != TokenKind::Unknown;
  }
  
  bool SyntaxFacts::isCloseDelimOrKeyword(TokenKind kind) {
      switch (kind) {
          case TokenKind::CloseBrace:
          case TokenKind::CloseBracket:
          case TokenKind::CloseParenthesis:
          case TokenKind::StarCloseParenthesis:
              return true;
          default:
              return isEndKeyword(kind);
      }
  }
  
  bool SyntaxFacts::isMatchingDelims(TokenKind openKind, TokenKind closeKind) {
      if (getSkipToKind(openKind) == closeKind)
          return true;
  
      if (openKind == TokenKind::ForkKeyword) {
          switch (closeKind) {
              case TokenKind::JoinKeyword:
              case TokenKind::JoinAnyKeyword:
              case TokenKind::JoinNoneKeyword:
                  return true;
              default:
                  break;
          }
      }
  
      return false;
  }
  
  bool SyntaxFacts::isDeclarationModifier(TokenKind kind) {
      switch (kind) {
          case TokenKind::ConstKeyword:
          case TokenKind::VarKeyword:
          case TokenKind::StaticKeyword:
          case TokenKind::AutomaticKeyword:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isLifetimeModifier(TokenKind kind) {
      switch (kind) {
          case TokenKind::StaticKeyword:
          case TokenKind::AutomaticKeyword:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isMemberQualifier(TokenKind kind) {
      switch (kind) {
          case TokenKind::ConstKeyword:
          case TokenKind::RandKeyword:
          case TokenKind::RandCKeyword:
          case TokenKind::PureKeyword:
          case TokenKind::VirtualKeyword:
          case TokenKind::ExternKeyword:
          case TokenKind::StaticKeyword:
          case TokenKind::LocalKeyword:
          case TokenKind::ProtectedKeyword:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isMethodQualifier(TokenKind kind) {
      switch (kind) {
          case TokenKind::PureKeyword:
          case TokenKind::VirtualKeyword:
          case TokenKind::ExternKeyword:
          case TokenKind::StaticKeyword:
          case TokenKind::LocalKeyword:
          case TokenKind::ProtectedKeyword:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isPropertyQualifier(TokenKind kind) {
      switch (kind) {
          case TokenKind::ConstKeyword:
          case TokenKind::RandKeyword:
          case TokenKind::RandCKeyword:
          case TokenKind::StaticKeyword:
          case TokenKind::LocalKeyword:
          case TokenKind::ProtectedKeyword:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isConstraintQualifier(TokenKind kind) {
      switch (kind) {
          case TokenKind::StaticKeyword:
          case TokenKind::PureKeyword:
          case TokenKind::ExternKeyword:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isDriveStrength(TokenKind kind) {
      switch (kind) {
          case TokenKind::Supply0Keyword:
          case TokenKind::Strong0Keyword:
          case TokenKind::Pull0Keyword:
          case TokenKind::Weak0Keyword:
          case TokenKind::HighZ0Keyword:
          case TokenKind::Supply1Keyword:
          case TokenKind::Strong1Keyword:
          case TokenKind::Pull1Keyword:
          case TokenKind::Weak1Keyword:
          case TokenKind::HighZ1Keyword:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isChargeStrength(TokenKind kind) {
      switch (kind) {
          case TokenKind::SmallKeyword:
          case TokenKind::MediumKeyword:
          case TokenKind::LargeKeyword:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isGateType(TokenKind kind) {
      switch (kind) {
          case TokenKind::CmosKeyword:
          case TokenKind::RcmosKeyword:
          case TokenKind::NmosKeyword:
          case TokenKind::PmosKeyword:
          case TokenKind::RnmosKeyword:
          case TokenKind::RpmosKeyword:
          case TokenKind::BufIf0Keyword:
          case TokenKind::BufIf1Keyword:
          case TokenKind::NotIf0Keyword:
          case TokenKind::NotIf1Keyword:
          case TokenKind::AndKeyword:
          case TokenKind::NandKeyword:
          case TokenKind::OrKeyword:
          case TokenKind::NorKeyword:
          case TokenKind::XorKeyword:
          case TokenKind::XnorKeyword:
          case TokenKind::BufKeyword:
          case TokenKind::NotKeyword:
          case TokenKind::TranIf0Keyword:
          case TokenKind::TranIf1Keyword:
          case TokenKind::RtranIf0Keyword:
          case TokenKind::RtranIf1Keyword:
          case TokenKind::TranKeyword:
          case TokenKind::RtranKeyword:
          case TokenKind::PullDownKeyword:
          case TokenKind::PullUpKeyword:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isEndOfParenList(TokenKind kind) {
      return kind == TokenKind::CloseParenthesis || kind == TokenKind::Semicolon;
  }
  
  bool SyntaxFacts::isEndOfBracedList(TokenKind kind) {
      return kind == TokenKind::CloseBrace || kind == TokenKind::Semicolon;
  }
  
  bool SyntaxFacts::isEndOfBracketedList(TokenKind kind) {
      return kind == TokenKind::CloseBracket || kind == TokenKind::Semicolon;
  }
  
  bool SyntaxFacts::isEndOfCaseItem(TokenKind kind) {
      return kind == TokenKind::Colon || kind == TokenKind::Semicolon;
  }
  
  bool SyntaxFacts::isEndOfConditionalPredicate(TokenKind kind) {
      return kind == TokenKind::Question || kind == TokenKind::CloseParenthesis ||
          kind == TokenKind::BeginKeyword || kind == TokenKind::Semicolon;
  }
  
  bool SyntaxFacts::isEndOfAttribute(TokenKind kind) {
      switch (kind) {
          case TokenKind::StarCloseParenthesis:
              // these indicate a missing *) somewhere
          case TokenKind::Semicolon:
          case TokenKind::PrimitiveKeyword:
          case TokenKind::ProgramKeyword:
          case TokenKind::InterfaceKeyword:
          case TokenKind::PackageKeyword:
          case TokenKind::CheckerKeyword:
          case TokenKind::GenerateKeyword:
          case TokenKind::ModuleKeyword:
          case TokenKind::ClassKeyword:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isEndOfParameterList(TokenKind kind) {
      return kind == TokenKind::CloseParenthesis || kind == TokenKind::OpenParenthesis || kind == TokenKind::Semicolon;
  }
  
  bool SyntaxFacts::isEndOfTransSet(TokenKind kind) {
      switch (kind) {
          case TokenKind::Semicolon:
          case TokenKind::CloseParenthesis:
          case TokenKind::BinsKeyword:
          case TokenKind::IllegalBinsKeyword:
          case TokenKind::IgnoreBinsKeyword:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isNotInType(TokenKind kind) {
      switch (kind) {
          case TokenKind::Semicolon:
          case TokenKind::EndOfFile:
              return true;
          default:
              return isEndKeyword(kind);
      }
  }
  
  bool SyntaxFacts::isNotInPortReference(TokenKind kind) {
      return kind == TokenKind::Semicolon || kind == TokenKind::EndOfFile;
  }
  
  bool SyntaxFacts::isNotInConcatenationExpr(TokenKind kind) {
      switch (kind) {
          case TokenKind::Semicolon:
          case TokenKind::EndOfFile:
          case TokenKind::IfKeyword:
          case TokenKind::ForeachKeyword:
          case TokenKind::SoftKeyword:
          case TokenKind::UniqueKeyword:
          case TokenKind::DistKeyword:
          case TokenKind::DisableKeyword:
          case TokenKind::MinusArrow:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isPossibleLetPortItem(TokenKind kind) {
      return kind == TokenKind::OpenParenthesisStar || kind == TokenKind::UntypedKeyword || isPossibleDataType(kind);
  }
  
  bool SyntaxFacts::isNotInParameterList(TokenKind kind) {
      return kind == TokenKind::OpenParenthesis || kind == TokenKind::Semicolon || kind == TokenKind::EndOfFile;
  }
  
  bool SyntaxFacts::isPossiblePropertyPortItem(TokenKind kind) {
      switch (kind) {
          case TokenKind::OpenParenthesisStar:
          case TokenKind::LocalKeyword:
          case TokenKind::PropertyKeyword:
          case TokenKind::SequenceKeyword:
          case TokenKind::Comma:
          case TokenKind::InputKeyword:
          case TokenKind::OutputKeyword:
          case TokenKind::InOutKeyword:
          case TokenKind::RefKeyword:
              return true;
          default:
              return isPossibleDataType(kind);
      }
  }
  
  bool SyntaxFacts::isPossibleTransSet(TokenKind kind) {
      switch (kind) {
          case TokenKind::OpenParenthesis:
          case TokenKind::Comma:
          case TokenKind::EqualsArrow:
          case TokenKind::OpenBracket:
              return true;
          default:
              return isPossibleExpression(kind);
      }
  }
  
  bool SyntaxFacts::isPossibleTimingCheckArg(TokenKind kind) {
      switch (kind) {
          case TokenKind::PosEdgeKeyword:
          case TokenKind::NegEdgeKeyword:
          case TokenKind::EdgeKeyword:
          case TokenKind::Comma:
              return true;
          default:
              return isPossibleExpression(kind);
      }
  }
  
  bool SyntaxFacts::isPossibleEdgeDescriptor(TokenKind kind) {
      switch (kind) {
          case TokenKind::IntegerLiteral:
          case TokenKind::Identifier:
          case TokenKind::Comma:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isBeforeOrSemicolon(TokenKind kind) {
      return kind == TokenKind::Semicolon || kind == TokenKind::BeforeKeyword;
  }
  
  bool SyntaxFacts::isModifierAllowedAfter(TokenKind mod, TokenKind prev) {
      switch (mod) {
          case TokenKind::ConstKeyword: return false;
          case TokenKind::VarKeyword: return prev == TokenKind::ConstKeyword;
          case TokenKind::StaticKeyword:
          case TokenKind::AutomaticKeyword:
              return prev == TokenKind::VarKeyword || prev == TokenKind::ConstKeyword;
          default:
              return false;
      }
  }
  
  static bool isModuleOrPackageDecl(SyntaxKind kind) {
      switch (kind) {
          case SyntaxKind::NetDeclaration:
          case SyntaxKind::UserDefinedNetDeclaration:
          case SyntaxKind::NetTypeDeclaration:
          case SyntaxKind::TypedefDeclaration:
          case SyntaxKind::ForwardTypedefDeclaration:
          case SyntaxKind::ForwardInterfaceClassTypedefDeclaration:
          case SyntaxKind::PackageImportDeclaration:
          case SyntaxKind::DataDeclaration:
          case SyntaxKind::TaskDeclaration:
          case SyntaxKind::FunctionDeclaration:
          case SyntaxKind::DPIImport:
          case SyntaxKind::DPIExport:
          case SyntaxKind::ClassDeclaration:
          case SyntaxKind::ParameterDeclarationStatement:
          case SyntaxKind::CovergroupDeclaration:
          case SyntaxKind::EmptyMember:
          case SyntaxKind::PropertyDeclaration:
          case SyntaxKind::SequenceDeclaration:
          case SyntaxKind::LetDeclaration:
          case SyntaxKind::ConstraintDeclaration:
          case SyntaxKind::CheckerDeclaration:
              return true;
          default:
              return false;
      }
  }
  
  static bool isModuleCommonDecl(SyntaxKind kind) {
      switch (kind) {
          case SyntaxKind::GenvarDeclaration:
          case SyntaxKind::ClockingDeclaration:
          case SyntaxKind::DefaultClockingReference:
          case SyntaxKind::DefaultDisableDeclaration:
              return true;
          default:
              return isModuleOrPackageDecl(kind);
      }
  }
  
  static bool isModuleCommonItem(SyntaxKind kind) {
      switch (kind) {
          case SyntaxKind::HierarchyInstantiation:
          case SyntaxKind::ImmediateAssertionMember:
          case SyntaxKind::ConcurrentAssertionMember:
          case SyntaxKind::ContinuousAssign:
          case SyntaxKind::NetAlias:
          case SyntaxKind::InitialBlock:
          case SyntaxKind::FinalBlock:
          case SyntaxKind::AlwaysBlock:
          case SyntaxKind::AlwaysCombBlock:
          case SyntaxKind::AlwaysFFBlock:
          case SyntaxKind::AlwaysLatchBlock:
          case SyntaxKind::LoopGenerate:
          case SyntaxKind::CaseGenerate:
          case SyntaxKind::IfGenerate:
          case SyntaxKind::GenerateBlock:
          case SyntaxKind::ElabSystemTask:
          case SyntaxKind::BindDirective:
              return true;
          default:
              return isModuleCommonDecl(kind);
      }
  }
  
  bool SyntaxFacts::isAllowedInCompilationUnit(SyntaxKind kind) {
      switch (kind) {
          case SyntaxKind::TimeUnitsDeclaration:
          case SyntaxKind::ModuleDeclaration:
          case SyntaxKind::InterfaceDeclaration:
          case SyntaxKind::ProgramDeclaration:
          case SyntaxKind::PackageDeclaration:
          case SyntaxKind::BindDirective:
          case SyntaxKind::UdpDeclaration:
              return true;
          default:
              return isAllowedInPackage(kind);
      }
  }
  
  bool SyntaxFacts::isAllowedInGenerate(SyntaxKind kind) {
      switch (kind) {
          case SyntaxKind::DefParam:
          case SyntaxKind::PrimitiveInstantiation:
              return true;
          default:
              return isModuleCommonItem(kind);
      }
  }
  
  bool SyntaxFacts::isAllowedInModule(SyntaxKind kind) {
      switch (kind) {
          case SyntaxKind::PortDeclaration:
          case SyntaxKind::GenerateRegion:
          case SyntaxKind::ModuleDeclaration:
          case SyntaxKind::InterfaceDeclaration:
          case SyntaxKind::ProgramDeclaration:
          case SyntaxKind::TimeUnitsDeclaration:
          case SyntaxKind::SpecparamDeclaration:
          case SyntaxKind::SpecifyBlock:
              return true;
          default:
              return isAllowedInGenerate(kind);
      }
  }
  
  bool SyntaxFacts::isAllowedInInterface(SyntaxKind kind) {
      switch (kind) {
          case SyntaxKind::PortDeclaration:
          case SyntaxKind::GenerateRegion:
          case SyntaxKind::ModportDeclaration:
          case SyntaxKind::InterfaceDeclaration:
          case SyntaxKind::ProgramDeclaration:
          case SyntaxKind::TimeUnitsDeclaration:
              return true;
          default:
              return isModuleCommonItem(kind);
      }
  }
  
  bool SyntaxFacts::isAllowedInProgram(SyntaxKind kind) {
      switch (kind) {
          case SyntaxKind::PortDeclaration:
          case SyntaxKind::ContinuousAssign:
          case SyntaxKind::InitialBlock:
          case SyntaxKind::FinalBlock:
          case SyntaxKind::ConcurrentAssertionMember:
          case SyntaxKind::TimeUnitsDeclaration:
          case SyntaxKind::LoopGenerate:
          case SyntaxKind::CaseGenerate:
          case SyntaxKind::IfGenerate:
          case SyntaxKind::GenerateRegion:
          case SyntaxKind::GenerateBlock:
          case SyntaxKind::ElabSystemTask:
              return true;
          default:
              return isModuleCommonDecl(kind);
      }
  }
  
  bool SyntaxFacts::isAllowedInPackage(SyntaxKind kind) {
      switch (kind) {
          case SyntaxKind::TimeUnitsDeclaration:
          case SyntaxKind::PackageExportDeclaration:
          case SyntaxKind::PackageExportAllDeclaration:
              return true;
          default:
              return isModuleOrPackageDecl(kind);
      }
  }
  
  bool SyntaxFacts::isAllowedInClocking(SyntaxKind kind) {
      switch (kind) {
          case SyntaxKind::PropertyDeclaration:
          case SyntaxKind::SequenceDeclaration:
          case SyntaxKind::LetDeclaration:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isAllowedInChecker(SyntaxKind kind) {
      switch (kind) {
          case SyntaxKind::InitialBlock:
          case SyntaxKind::FinalBlock:
          case SyntaxKind::AlwaysBlock:
          case SyntaxKind::AlwaysCombBlock:
          case SyntaxKind::AlwaysFFBlock:
          case SyntaxKind::AlwaysLatchBlock:
          case SyntaxKind::ImmediateAssertionMember:
          case SyntaxKind::ConcurrentAssertionMember:
          case SyntaxKind::ContinuousAssign:
          case SyntaxKind::LoopGenerate:
          case SyntaxKind::CaseGenerate:
          case SyntaxKind::IfGenerate:
          case SyntaxKind::GenerateBlock:
          case SyntaxKind::GenerateRegion:
          case SyntaxKind::ElabSystemTask:
          case SyntaxKind::ParameterDeclarationStatement:
          case SyntaxKind::CovergroupDeclaration:
          case SyntaxKind::EmptyMember:
          case SyntaxKind::PropertyDeclaration:
          case SyntaxKind::SequenceDeclaration:
          case SyntaxKind::LetDeclaration:
          case SyntaxKind::GenvarDeclaration:
          case SyntaxKind::ClockingDeclaration:
          case SyntaxKind::DefaultClockingReference:
          case SyntaxKind::DefaultDisableDeclaration:
          case SyntaxKind::NetTypeDeclaration:
          case SyntaxKind::TypedefDeclaration:
          case SyntaxKind::ForwardTypedefDeclaration:
          case SyntaxKind::ForwardInterfaceClassTypedefDeclaration:
          case SyntaxKind::PackageImportDeclaration:
          case SyntaxKind::DataDeclaration:
          case SyntaxKind::TaskDeclaration:
          case SyntaxKind::CheckerDeclaration:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isStrength0(TokenKind kind) {
      switch (kind) {
          case TokenKind::Strong0Keyword:
          case TokenKind::Weak0Keyword:
          case TokenKind::Pull0Keyword:
          case TokenKind::Supply0Keyword:
          case TokenKind::HighZ0Keyword:
              return true;
          default:
              return false;
      }
  }
  
  bool SyntaxFacts::isStrength1(TokenKind kind) {
      switch (kind) {
          case TokenKind::Strong1Keyword:
          case TokenKind::Weak1Keyword:
          case TokenKind::Pull1Keyword:
          case TokenKind::Supply1Keyword:
          case TokenKind::HighZ1Keyword:
              return true;
          default:
              return false;
      }
  }
  
  // clang-format on
  
  } // namespace slang
  