blob: cdf1c7f30cb45a92246bbabc5da68cd49dcd7d4c [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "raw_ast.h"
#ifndef TOOLS_FIDL_FIDLC_INCLUDE_FIDL_TREE_VISITOR_H_
#define TOOLS_FIDL_FIDLC_INCLUDE_FIDL_TREE_VISITOR_H_
namespace fidl {
namespace raw {
// A TreeVisitor is an API that walks a FIDL AST. The default implementation
// does nothing but walk the AST. To make it interesting, subclass TreeVisitor
// and override behaviors with the ones you want.
class TreeVisitor {
public:
virtual ~TreeVisitor() = default;
virtual void OnSourceElementStart(const SourceElement& element) {}
virtual void OnSourceElementEnd(const SourceElement& element) {}
virtual void OnIdentifier(std::unique_ptr<Identifier> const& element) { element->Accept(this); }
virtual void OnCompoundIdentifier(std::unique_ptr<CompoundIdentifier> const& element) {
element->Accept(this);
}
virtual void OnLiteral(std::unique_ptr<fidl::raw::Literal> const& element) {
fidl::raw::Literal::Kind kind = element->kind;
switch (kind) {
case Literal::Kind::kString: {
StringLiteral* literal = static_cast<StringLiteral*>(element.get());
OnStringLiteral(*literal);
break;
}
case Literal::Kind::kNumeric: {
NumericLiteral* literal = static_cast<NumericLiteral*>(element.get());
OnNumericLiteral(*literal);
break;
}
case Literal::Kind::kTrue: {
TrueLiteral* literal = static_cast<TrueLiteral*>(element.get());
OnTrueLiteral(*literal);
break;
}
case Literal::Kind::kFalse: {
FalseLiteral* literal = static_cast<FalseLiteral*>(element.get());
OnFalseLiteral(*literal);
break;
}
default:
// Die!
break;
}
}
virtual void OnStringLiteral(StringLiteral& element) { element.Accept(this); }
virtual void OnNumericLiteral(NumericLiteral& element) { element.Accept(this); }
virtual void OnTrueLiteral(TrueLiteral& element) { element.Accept(this); }
virtual void OnFalseLiteral(FalseLiteral& element) { element.Accept(this); }
virtual void OnOrdinal64(Ordinal64& element) { element.Accept(this); }
#ifdef DISPATCH_TO
#error "Cannot define macro DISPATCH_TO: already defined"
#endif
#define DISPATCH_TO(TYPE, SUPERTYPE, ELEMENT) \
do { \
std::unique_ptr<SUPERTYPE>& unconst_element = \
const_cast<std::unique_ptr<SUPERTYPE>&>(element); \
TYPE* ptr = static_cast<TYPE*>(unconst_element.get()); \
std::unique_ptr<TYPE> uptr(ptr); \
On##TYPE(uptr); \
uptr.release(); \
} while (0)
virtual void OnConstant(std::unique_ptr<Constant> const& element) {
Constant::Kind kind = element->kind;
switch (kind) {
case Constant::Kind::kIdentifier: {
DISPATCH_TO(IdentifierConstant, Constant, element);
break;
}
case Constant::Kind::kLiteral: {
DISPATCH_TO(LiteralConstant, Constant, element);
break;
}
case Constant::Kind::kBinaryOperator: {
DISPATCH_TO(BinaryOperatorConstant, Constant, element);
break;
}
}
}
virtual void OnIdentifierConstant(std::unique_ptr<IdentifierConstant> const& element) {
element->Accept(this);
}
virtual void OnLiteralConstant(std::unique_ptr<LiteralConstant> const& element) {
element->Accept(this);
}
virtual void OnBinaryOperatorConstant(std::unique_ptr<BinaryOperatorConstant> const& element) {
element->Accept(this);
}
virtual void OnAttribute(const Attribute& element) { element.Accept(this); }
virtual void OnAttributeList(std::unique_ptr<AttributeList> const& element) {
element->Accept(this);
}
void OnTypeConstructor(TypeConstructor const& element) {
std::visit(
fidl::utils::matchers{
[this](const std::unique_ptr<TypeConstructorOld>& e) { OnTypeConstructorOld(e); },
[this](const std::unique_ptr<TypeConstructorNew>& e) { OnTypeConstructorNew(e); },
},
element);
}
virtual void OnTypeConstructorOld(std::unique_ptr<TypeConstructorOld> const& element) {
element->Accept(this);
}
virtual void OnTypeConstructorNew(std::unique_ptr<TypeConstructorNew> const& element) {
element->Accept(this);
}
virtual void OnAliasDeclaration(std::unique_ptr<AliasDeclaration> const& element) {
element->Accept(this);
}
virtual void OnUsing(std::unique_ptr<Using> const& element) { element->Accept(this); }
virtual void OnConstDeclaration(std::unique_ptr<ConstDeclaration> const& element) {
element->Accept(this);
}
virtual void OnBitsMember(std::unique_ptr<BitsMember> const& element) { element->Accept(this); }
virtual void OnBitsDeclaration(std::unique_ptr<BitsDeclaration> const& element) {
element->Accept(this);
}
virtual void OnEnumMember(std::unique_ptr<EnumMember> const& element) { element->Accept(this); }
virtual void OnEnumDeclaration(std::unique_ptr<EnumDeclaration> const& element) {
element->Accept(this);
}
virtual void OnParameter(std::unique_ptr<Parameter> const& element) { element->Accept(this); }
virtual void OnParameterList(std::unique_ptr<ParameterList> const& element) {
element->Accept(this);
}
virtual void OnProtocolMethod(std::unique_ptr<ProtocolMethod> const& element) {
element->Accept(this);
}
virtual void OnComposeProtocol(std::unique_ptr<ComposeProtocol> const& element) {
element->Accept(this);
}
virtual void OnProtocolDeclaration(std::unique_ptr<ProtocolDeclaration> const& element) {
element->Accept(this);
}
virtual void OnResourceProperty(std::unique_ptr<ResourceProperty> const& element) {
element->Accept(this);
}
virtual void OnResourceDeclaration(std::unique_ptr<ResourceDeclaration> const& element) {
element->Accept(this);
}
virtual void OnServiceMember(std::unique_ptr<ServiceMember> const& element) {
element->Accept(this);
}
virtual void OnServiceDeclaration(std::unique_ptr<ServiceDeclaration> const& element) {
element->Accept(this);
}
virtual void OnStructMember(std::unique_ptr<StructMember> const& element) {
element->Accept(this);
}
virtual void OnStructDeclaration(std::unique_ptr<StructDeclaration> const& element) {
element->Accept(this);
}
virtual void OnTableMember(std::unique_ptr<TableMember> const& element) { element->Accept(this); }
virtual void OnTableDeclaration(std::unique_ptr<TableDeclaration> const& element) {
element->Accept(this);
}
virtual void OnUnionMember(std::unique_ptr<UnionMember> const& element) { element->Accept(this); }
virtual void OnUnionDeclaration(std::unique_ptr<UnionDeclaration> const& element) {
element->Accept(this);
}
virtual void OnFile(std::unique_ptr<File> const& element) { element->Accept(this); }
virtual void OnPrimitiveSubtype(types::PrimitiveSubtype subtype) {}
virtual void OnNullability(types::Nullability nullability) {}
};
#undef DISPATCH_TO
// AST node contents are not stored in declaration order in the tree, so we
// have a special visitor for code that needs to visit in declaration order.
class DeclarationOrderTreeVisitor : public TreeVisitor {
public:
virtual void OnFile(std::unique_ptr<File> const& element) override;
virtual void OnProtocolDeclaration(std::unique_ptr<ProtocolDeclaration> const& element) override;
};
} // namespace raw
} // namespace fidl
#endif // TOOLS_FIDL_FIDLC_INCLUDE_FIDL_TREE_VISITOR_H_