2018-02-26 23:22:58 +01:00
|
|
|
#ifndef FORTRAN_PARSER_PARSE_TREE_VISITOR_H_
|
|
|
|
#define FORTRAN_PARSER_PARSE_TREE_VISITOR_H_
|
2018-02-23 02:00:56 +01:00
|
|
|
|
|
|
|
#include "parse-tree.h"
|
2018-03-20 18:59:07 +01:00
|
|
|
#include <cstddef>
|
2018-02-23 02:00:56 +01:00
|
|
|
#include <optional>
|
|
|
|
#include <tuple>
|
2018-03-23 23:14:52 +01:00
|
|
|
#include <utility>
|
2018-02-23 02:00:56 +01:00
|
|
|
#include <variant>
|
|
|
|
|
|
|
|
/// Parse tree visitor
|
2018-04-06 22:13:20 +02:00
|
|
|
/// Call Walk(x, visitor) to visit x and, by default, each node under x.
|
2018-02-23 02:00:56 +01:00
|
|
|
///
|
2018-02-24 01:03:16 +01:00
|
|
|
/// visitor.Pre(x) is called before visiting x and its children are not
|
2018-02-23 02:00:56 +01:00
|
|
|
/// visited if it returns false.
|
|
|
|
///
|
2018-02-24 01:03:16 +01:00
|
|
|
/// visitor.Post(x) is called after visiting x.
|
2018-02-23 02:00:56 +01:00
|
|
|
|
|
|
|
namespace Fortran {
|
|
|
|
namespace parser {
|
|
|
|
|
2018-03-20 18:59:07 +01:00
|
|
|
// Default case for visitation of non-class data members and strings
|
2018-02-28 22:24:01 +01:00
|
|
|
template<typename A, typename V>
|
|
|
|
typename std::enable_if<!std::is_class_v<A> ||
|
2018-02-28 23:53:04 +01:00
|
|
|
std::is_same_v<std::string, A>>::type
|
2018-02-28 22:24:01 +01:00
|
|
|
Walk(const A &x, V &visitor) {
|
2018-02-24 01:03:16 +01:00
|
|
|
if (visitor.Pre(x)) {
|
2018-02-28 23:53:04 +01:00
|
|
|
visitor.Post(x);
|
2018-02-23 02:00:56 +01:00
|
|
|
}
|
|
|
|
}
|
2018-02-28 22:24:01 +01:00
|
|
|
|
2018-03-01 22:23:31 +01:00
|
|
|
template<typename V> void Walk(const format::ControlEditDesc &, V &);
|
|
|
|
template<typename V> void Walk(const format::DerivedTypeDataEditDesc &, V &);
|
|
|
|
template<typename V> void Walk(const format::FormatItem &, V &);
|
|
|
|
template<typename V> void Walk(const format::FormatSpecification &, V &);
|
|
|
|
template<typename V> void Walk(const format::IntrinsicTypeDataEditDesc &, V &);
|
|
|
|
|
2018-02-28 22:24:01 +01:00
|
|
|
// Traversal of needed STL template classes (optional, list, tuple, variant)
|
2018-02-23 02:00:56 +01:00
|
|
|
template<typename T, typename V>
|
2018-02-24 01:03:16 +01:00
|
|
|
void Walk(const std::optional<T> &x, V &visitor) {
|
2018-02-23 02:00:56 +01:00
|
|
|
if (x) {
|
2018-02-24 01:03:16 +01:00
|
|
|
Walk(*x, visitor);
|
2018-02-23 02:00:56 +01:00
|
|
|
}
|
|
|
|
}
|
2018-02-24 01:03:16 +01:00
|
|
|
template<typename T, typename V> void Walk(const std::list<T> &x, V &visitor) {
|
2018-02-23 02:00:56 +01:00
|
|
|
for (const auto &elem : x) {
|
2018-02-24 01:03:16 +01:00
|
|
|
Walk(elem, visitor);
|
2018-02-23 02:00:56 +01:00
|
|
|
}
|
|
|
|
}
|
2018-03-20 18:59:07 +01:00
|
|
|
template<std::size_t I = 0, typename Func, typename T>
|
2018-02-28 22:24:01 +01:00
|
|
|
void ForEachInTuple(const T &tuple, Func func) {
|
|
|
|
if constexpr (I < std::tuple_size_v<T>) {
|
|
|
|
func(std::get<I>(tuple));
|
|
|
|
ForEachInTuple<I + 1>(tuple, func);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
template<typename V, typename... A>
|
|
|
|
void Walk(const std::tuple<A...> &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
ForEachInTuple(x, [&](const auto &y) { Walk(y, visitor); });
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
template<typename V, typename... A>
|
|
|
|
void Walk(const std::variant<A...> &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
std::visit([&](const auto &y) { Walk(y, visitor); }, x);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
2018-03-23 23:14:52 +01:00
|
|
|
}
|
|
|
|
template<typename A, typename B, typename V>
|
|
|
|
void Walk(const std::pair<A, B> &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.first, visitor);
|
|
|
|
Walk(x.second, visitor);
|
|
|
|
}
|
2018-02-28 22:24:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Trait-determined traversal of empty, tuple, union, and wrapper classes.
|
|
|
|
template<typename A, typename V>
|
2018-02-28 23:53:04 +01:00
|
|
|
typename std::enable_if<EmptyTrait<A>>::type Walk(const A &x, V &visitor) {
|
2018-02-28 22:24:01 +01:00
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename A, typename V>
|
2018-02-28 23:53:04 +01:00
|
|
|
typename std::enable_if<TupleTrait<A>>::type Walk(const A &x, V &visitor) {
|
2018-02-28 23:51:45 +01:00
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.t, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
2018-02-28 22:24:01 +01:00
|
|
|
|
|
|
|
template<typename A, typename V>
|
2018-02-28 23:53:04 +01:00
|
|
|
typename std::enable_if<UnionTrait<A>>::type Walk(const A &x, V &visitor) {
|
2018-02-28 23:51:45 +01:00
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.u, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
2018-02-28 22:24:01 +01:00
|
|
|
|
|
|
|
template<typename A, typename V>
|
2018-02-28 23:53:04 +01:00
|
|
|
typename std::enable_if<WrapperTrait<A>>::type Walk(const A &x, V &visitor) {
|
2018-02-28 22:24:01 +01:00
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.v, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-23 02:00:56 +01:00
|
|
|
template<typename T, typename V>
|
2018-02-24 01:03:16 +01:00
|
|
|
void Walk(const Indirection<T> &x, V &visitor) {
|
|
|
|
Walk(*x, visitor);
|
2018-02-23 02:00:56 +01:00
|
|
|
}
|
|
|
|
|
2018-02-26 23:22:58 +01:00
|
|
|
// Walk a class with a single field 'thing'.
|
2018-02-24 01:03:16 +01:00
|
|
|
template<typename T, typename V> void Walk(const Scalar<T> &x, V &visitor) {
|
|
|
|
Walk(x.thing, visitor);
|
2018-02-23 02:00:56 +01:00
|
|
|
}
|
2018-02-24 01:03:16 +01:00
|
|
|
template<typename T, typename V> void Walk(const Constant<T> &x, V &visitor) {
|
|
|
|
Walk(x.thing, visitor);
|
2018-02-23 02:00:56 +01:00
|
|
|
}
|
2018-02-24 01:03:16 +01:00
|
|
|
template<typename T, typename V> void Walk(const Integer<T> &x, V &visitor) {
|
|
|
|
Walk(x.thing, visitor);
|
2018-02-23 02:00:56 +01:00
|
|
|
}
|
2018-02-24 01:03:16 +01:00
|
|
|
template<typename T, typename V> void Walk(const Logical<T> &x, V &visitor) {
|
|
|
|
Walk(x.thing, visitor);
|
2018-02-23 02:00:56 +01:00
|
|
|
}
|
|
|
|
template<typename T, typename V>
|
2018-02-24 01:03:16 +01:00
|
|
|
void Walk(const DefaultChar<T> &x, V &visitor) {
|
|
|
|
Walk(x.thing, visitor);
|
2018-02-23 02:00:56 +01:00
|
|
|
}
|
|
|
|
|
2018-02-24 01:03:16 +01:00
|
|
|
template<typename T, typename V> void Walk(const Statement<T> &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
2018-03-01 01:56:10 +01:00
|
|
|
// N.B. the label is not traversed
|
2018-02-24 01:03:16 +01:00
|
|
|
Walk(x.statement, visitor);
|
|
|
|
visitor.Post(x);
|
2018-02-23 02:00:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-20 18:59:07 +01:00
|
|
|
template<typename V> void Walk(const Name &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-24 01:03:16 +01:00
|
|
|
template<typename V> void Walk(const AcSpec &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.type, visitor);
|
|
|
|
Walk(x.values, visitor);
|
|
|
|
visitor.Post(x);
|
2018-02-23 02:00:56 +01:00
|
|
|
}
|
|
|
|
}
|
2018-02-26 23:22:58 +01:00
|
|
|
template<typename V> void Walk(const ArrayElement &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.base, visitor);
|
|
|
|
Walk(x.subscripts, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
2018-02-23 02:00:56 +01:00
|
|
|
}
|
2018-02-26 23:22:58 +01:00
|
|
|
template<typename V>
|
|
|
|
void Walk(const CharSelector::LengthAndKind &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.length, visitor);
|
|
|
|
Walk(x.kind, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
2018-02-25 16:35:56 +01:00
|
|
|
}
|
2018-02-28 23:53:04 +01:00
|
|
|
template<typename V> void Walk(const CaseValueRange::Range &x, V &visitor) {
|
2018-02-28 22:24:01 +01:00
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.lower, visitor);
|
|
|
|
Walk(x.upper, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
2018-02-26 23:22:58 +01:00
|
|
|
template<typename V> void Walk(const CoindexedNamedObject &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.base, visitor);
|
|
|
|
Walk(x.imageSelector, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
2018-02-23 02:00:56 +01:00
|
|
|
}
|
2018-02-26 23:22:58 +01:00
|
|
|
template<typename V>
|
|
|
|
void Walk(const DeclarationTypeSpec::Class &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.derived, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
2018-02-23 02:00:56 +01:00
|
|
|
}
|
2018-02-26 23:22:58 +01:00
|
|
|
template<typename V> void Walk(const DeclarationTypeSpec::Type &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.derived, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
2018-02-23 02:00:56 +01:00
|
|
|
}
|
2018-02-26 23:22:58 +01:00
|
|
|
template<typename V> void Walk(const ImportStmt &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.names, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
2018-02-23 02:00:56 +01:00
|
|
|
}
|
2018-02-26 23:22:58 +01:00
|
|
|
template<typename V>
|
|
|
|
void Walk(const IntrinsicTypeSpec::Character &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.selector, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
template<typename V>
|
|
|
|
void Walk(const IntrinsicTypeSpec::Complex &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.kind, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
template<typename V>
|
|
|
|
void Walk(const IntrinsicTypeSpec::Logical &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.kind, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
template<typename V> void Walk(const IntrinsicTypeSpec::Real &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.kind, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
2018-02-28 22:24:01 +01:00
|
|
|
template<typename T, typename V> void Walk(const LoopBounds<T> &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.name, visitor);
|
|
|
|
Walk(x.lower, visitor);
|
|
|
|
Walk(x.upper, visitor);
|
|
|
|
Walk(x.step, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
2018-02-26 23:22:58 +01:00
|
|
|
template<typename V> void Walk(const PartRef &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.name, visitor);
|
|
|
|
Walk(x.subscripts, visitor);
|
|
|
|
Walk(x.imageSelector, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
template<typename V> void Walk(const ReadStmt &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.iounit, visitor);
|
|
|
|
Walk(x.format, visitor);
|
|
|
|
Walk(x.controls, visitor);
|
|
|
|
Walk(x.items, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
template<typename V> void Walk(const RealLiteralConstant &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
2018-03-20 18:59:07 +01:00
|
|
|
Walk(x.real, visitor);
|
2018-02-26 23:22:58 +01:00
|
|
|
Walk(x.kind, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
2018-03-20 18:59:07 +01:00
|
|
|
template<typename V> void Walk(const RealLiteralConstant::Real &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
2018-02-26 23:22:58 +01:00
|
|
|
template<typename V> void Walk(const StructureComponent &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.base, visitor);
|
|
|
|
Walk(x.component, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
template<typename V> void Walk(const Suffix &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.binding, visitor);
|
|
|
|
Walk(x.resultName, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
template<typename V>
|
|
|
|
void Walk(const TypeBoundProcedureStmt::WithInterface &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.interfaceName, visitor);
|
|
|
|
Walk(x.attributes, visitor);
|
|
|
|
Walk(x.bindingNames, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
template<typename V>
|
|
|
|
void Walk(const TypeBoundProcedureStmt::WithoutInterface &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.attributes, visitor);
|
|
|
|
Walk(x.declarations, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
2018-02-27 00:07:24 +01:00
|
|
|
template<typename V> void Walk(const UseStmt &x, V &visitor) {
|
2018-02-27 01:58:44 +01:00
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.nature, visitor);
|
|
|
|
Walk(x.moduleName, visitor);
|
2018-02-28 22:24:01 +01:00
|
|
|
Walk(x.u, visitor);
|
2018-02-27 01:58:44 +01:00
|
|
|
visitor.Post(x);
|
|
|
|
}
|
2018-02-27 00:07:24 +01:00
|
|
|
}
|
2018-02-26 23:22:58 +01:00
|
|
|
template<typename V> void Walk(const WriteStmt &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.iounit, visitor);
|
|
|
|
Walk(x.format, visitor);
|
|
|
|
Walk(x.controls, visitor);
|
|
|
|
Walk(x.items, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
2018-02-23 02:00:56 +01:00
|
|
|
}
|
2018-03-01 22:23:31 +01:00
|
|
|
template<typename V> void Walk(const format::ControlEditDesc &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.kind, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
template<typename V>
|
|
|
|
void Walk(const format::DerivedTypeDataEditDesc &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.type, visitor);
|
|
|
|
Walk(x.parameters, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
template<typename V> void Walk(const format::FormatItem &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.repeatCount, visitor);
|
|
|
|
Walk(x.u, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
template<typename V>
|
|
|
|
void Walk(const format::FormatSpecification &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.items, visitor);
|
|
|
|
Walk(x.unlimitedItems, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
template<typename V>
|
|
|
|
void Walk(const format::IntrinsicTypeDataEditDesc &x, V &visitor) {
|
|
|
|
if (visitor.Pre(x)) {
|
|
|
|
Walk(x.kind, visitor);
|
|
|
|
Walk(x.width, visitor);
|
|
|
|
Walk(x.digits, visitor);
|
|
|
|
Walk(x.exponentWidth, visitor);
|
|
|
|
visitor.Post(x);
|
|
|
|
}
|
|
|
|
}
|
2018-02-23 02:00:56 +01:00
|
|
|
} // namespace parser
|
|
|
|
} // namespace Fortran
|
2018-02-26 23:22:58 +01:00
|
|
|
#endif // FORTRAN_PARSER_PARSE_TREE_VISITOR_H_
|