Warning: This file is not a C or C++ file. It does not have highlighting.

1//===-- include/flang/Parser/parse-tree-visitor.h ---------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef FORTRAN_PARSER_PARSE_TREE_VISITOR_H_
10#define FORTRAN_PARSER_PARSE_TREE_VISITOR_H_
11
12#include "parse-tree.h"
13#include "flang/Common/visit.h"
14#include <cstddef>
15#include <optional>
16#include <tuple>
17#include <utility>
18#include <variant>
19#include <vector>
20
21/// Parse tree visitor
22/// Call Walk(x, visitor) to visit x and, by default, each node under x.
23/// If x is non-const, the visitor member functions can modify the tree.
24///
25/// visitor.Pre(x) is called before visiting x and its children are not
26/// visited if it returns false.
27///
28/// visitor.Post(x) is called after visiting x.
29
30namespace Fortran::parser {
31
32// Default case for visitation of non-class data members, strings, and
33// any other non-decomposable values.
34template <typename A, typename V>
35std::enable_if_t<!std::is_class_v<A> || std::is_same_v<std::string, A> ||
36 std::is_same_v<CharBlock, A>>
37Walk(const A &x, V &visitor) {
38 if (visitor.Pre(x)) {
39 visitor.Post(x);
40 }
41}
42template <typename A, typename M>
43std::enable_if_t<!std::is_class_v<A> || std::is_same_v<std::string, A> ||
44 std::is_same_v<CharBlock, A>>
45Walk(A &x, M &mutator) {
46 if (mutator.Pre(x)) {
47 mutator.Post(x);
48 }
49}
50
51template <typename V> void Walk(const format::ControlEditDesc &, V &);
52template <typename M> void Walk(format::ControlEditDesc &, M &);
53template <typename V> void Walk(const format::DerivedTypeDataEditDesc &, V &);
54template <typename M> void Walk(format::DerivedTypeDataEditDesc &, M &);
55template <typename V> void Walk(const format::FormatItem &, V &);
56template <typename M> void Walk(format::FormatItem &, M &);
57template <typename V> void Walk(const format::FormatSpecification &, V &);
58template <typename M> void Walk(format::FormatSpecification &, M &);
59template <typename V> void Walk(const format::IntrinsicTypeDataEditDesc &, V &);
60template <typename M> void Walk(format::IntrinsicTypeDataEditDesc &, M &);
61
62// Traversal of needed STL template classes (optional, list, tuple, variant)
63// For most lists, just traverse the elements; but when a list constitutes
64// a Block (i.e., std::list<ExecutionPartConstruct>), also invoke the
65// visitor/mutator on the list itself.
66template <typename T, typename V> void Walk(const std::list<T> &x, V &visitor) {
67 for (const auto &elem : x) {
68 Walk(elem, visitor);
69 }
70}
71template <typename T, typename M> void Walk(std::list<T> &x, M &mutator) {
72 for (auto &elem : x) {
73 Walk(elem, mutator);
74 }
75}
76template <typename V> void Walk(const Block &x, V &visitor) {
77 if (visitor.Pre(x)) {
78 for (const auto &elem : x) {
79 Walk(elem, visitor);
80 }
81 visitor.Post(x);
82 }
83}
84template <typename M> void Walk(Block &x, M &mutator) {
85 if (mutator.Pre(x)) {
86 for (auto &elem : x) {
87 Walk(elem, mutator);
88 }
89 mutator.Post(x);
90 }
91}
92template <typename T, typename V>
93void Walk(const std::optional<T> &x, V &visitor) {
94 if (x) {
95 Walk(*x, visitor);
96 }
97}
98template <typename T, typename M> void Walk(std::optional<T> &x, M &mutator) {
99 if (x) {
100 Walk(*x, mutator);
101 }
102}
103template <std::size_t I = 0, typename Func, typename T>
104void ForEachInTuple(const T &tuple, Func func) {
105 func(std::get<I>(tuple));
106 if constexpr (I + 1 < std::tuple_size_v<T>) {
107 ForEachInTuple<I + 1>(tuple, func);
108 }
109}
110template <typename V, typename... A>
111void Walk(const std::tuple<A...> &x, V &visitor) {
112 if (sizeof...(A) > 0) {
113 if (visitor.Pre(x)) {
114 ForEachInTuple(x, [&](const auto &y) { Walk(y, visitor); });
115 visitor.Post(x);
116 }
117 }
118}
119template <std::size_t I = 0, typename Func, typename T>
120void ForEachInTuple(T &tuple, Func func) {
121 func(std::get<I>(tuple));
122 if constexpr (I + 1 < std::tuple_size_v<T>) {
123 ForEachInTuple<I + 1>(tuple, func);
124 }
125}
126template <typename M, typename... A>
127void Walk(std::tuple<A...> &x, M &mutator) {
128 if (sizeof...(A) > 0) {
129 if (mutator.Pre(x)) {
130 ForEachInTuple(x, [&](auto &y) { Walk(y, mutator); });
131 mutator.Post(x);
132 }
133 }
134}
135template <typename V, typename... A>
136void Walk(const std::variant<A...> &x, V &visitor) {
137 if (visitor.Pre(x)) {
138 common::visit([&](const auto &y) { Walk(y, visitor); }, x);
139 visitor.Post(x);
140 }
141}
142template <typename M, typename... A>
143void Walk(std::variant<A...> &x, M &mutator) {
144 if (mutator.Pre(x)) {
145 common::visit([&](auto &y) { Walk(y, mutator); }, x);
146 mutator.Post(x);
147 }
148}
149template <typename A, typename B, typename V>
150void Walk(const std::pair<A, B> &x, V &visitor) {
151 if (visitor.Pre(x)) {
152 Walk(x.first, visitor);
153 Walk(x.second, visitor);
154 }
155}
156template <typename A, typename B, typename M>
157void Walk(std::pair<A, B> &x, M &mutator) {
158 if (mutator.Pre(x)) {
159 Walk(x.first, mutator);
160 Walk(x.second, mutator);
161 }
162}
163
164// Trait-determined traversal of empty, tuple, union, wrapper,
165// and constraint-checking classes.
166template <typename A, typename V>
167std::enable_if_t<EmptyTrait<A>> Walk(const A &x, V &visitor) {
168 if (visitor.Pre(x)) {
169 visitor.Post(x);
170 }
171}
172template <typename A, typename M>
173std::enable_if_t<EmptyTrait<A>> Walk(A &x, M &mutator) {
174 if (mutator.Pre(x)) {
175 mutator.Post(x);
176 }
177}
178
179template <typename A, typename V>
180std::enable_if_t<TupleTrait<A>> Walk(const A &x, V &visitor) {
181 if (visitor.Pre(x)) {
182 Walk(x.t, visitor);
183 visitor.Post(x);
184 }
185}
186template <typename A, typename M>
187std::enable_if_t<TupleTrait<A>> Walk(A &x, M &mutator) {
188 if (mutator.Pre(x)) {
189 Walk(x.t, mutator);
190 mutator.Post(x);
191 }
192}
193
194template <typename A, typename V>
195std::enable_if_t<UnionTrait<A>> Walk(const A &x, V &visitor) {
196 if (visitor.Pre(x)) {
197 Walk(x.u, visitor);
198 visitor.Post(x);
199 }
200}
201template <typename A, typename M>
202std::enable_if_t<UnionTrait<A>> Walk(A &x, M &mutator) {
203 if (mutator.Pre(x)) {
204 Walk(x.u, mutator);
205 mutator.Post(x);
206 }
207}
208
209template <typename A, typename V>
210std::enable_if_t<WrapperTrait<A>> Walk(const A &x, V &visitor) {
211 if (visitor.Pre(x)) {
212 Walk(x.v, visitor);
213 visitor.Post(x);
214 }
215}
216template <typename A, typename M>
217std::enable_if_t<WrapperTrait<A>> Walk(A &x, M &mutator) {
218 if (mutator.Pre(x)) {
219 Walk(x.v, mutator);
220 mutator.Post(x);
221 }
222}
223
224template <typename A, typename V>
225std::enable_if_t<ConstraintTrait<A>> Walk(const A &x, V &visitor) {
226 if (visitor.Pre(x)) {
227 Walk(x.thing, visitor);
228 visitor.Post(x);
229 }
230}
231template <typename A, typename M>
232std::enable_if_t<ConstraintTrait<A>> Walk(A &x, M &mutator) {
233 if (mutator.Pre(x)) {
234 Walk(x.thing, mutator);
235 mutator.Post(x);
236 }
237}
238
239template <typename T, typename V>
240void Walk(const common::Indirection<T> &x, V &visitor) {
241 Walk(x.value(), visitor);
242}
243template <typename T, typename M>
244void Walk(common::Indirection<T> &x, M &mutator) {
245 Walk(x.value(), mutator);
246}
247
248template <typename T, typename V> void Walk(const Statement<T> &x, V &visitor) {
249 if (visitor.Pre(x)) {
250 // N.B. The label, if any, is not visited.
251 Walk(x.source, visitor);
252 Walk(x.statement, visitor);
253 visitor.Post(x);
254 }
255}
256template <typename T, typename M> void Walk(Statement<T> &x, M &mutator) {
257 if (mutator.Pre(x)) {
258 // N.B. The label, if any, is not visited.
259 Walk(x.source, mutator);
260 Walk(x.statement, mutator);
261 mutator.Post(x);
262 }
263}
264
265template <typename T, typename V>
266void Walk(const UnlabeledStatement<T> &x, V &visitor) {
267 if (visitor.Pre(x)) {
268 Walk(x.source, visitor);
269 Walk(x.statement, visitor);
270 visitor.Post(x);
271 }
272}
273template <typename T, typename M>
274void Walk(UnlabeledStatement<T> &x, M &mutator) {
275 if (mutator.Pre(x)) {
276 Walk(x.source, mutator);
277 Walk(x.statement, mutator);
278 mutator.Post(x);
279 }
280}
281
282template <typename V> void Walk(const Name &x, V &visitor) {
283 if (visitor.Pre(x)) {
284 Walk(x.source, visitor);
285 visitor.Post(x);
286 }
287}
288template <typename M> void Walk(Name &x, M &mutator) {
289 if (mutator.Pre(x)) {
290 Walk(x.source, mutator);
291 mutator.Post(x);
292 }
293}
294
295template <typename V> void Walk(const AcSpec &x, V &visitor) {
296 if (visitor.Pre(x)) {
297 Walk(x.type, visitor);
298 Walk(x.values, visitor);
299 visitor.Post(x);
300 }
301}
302template <typename M> void Walk(AcSpec &x, M &mutator) {
303 if (mutator.Pre(x)) {
304 Walk(x.type, mutator);
305 Walk(x.values, mutator);
306 mutator.Post(x);
307 }
308}
309template <typename V> void Walk(const ArrayElement &x, V &visitor) {
310 if (visitor.Pre(x)) {
311 Walk(x.base, visitor);
312 Walk(x.subscripts, visitor);
313 visitor.Post(x);
314 }
315}
316template <typename M> void Walk(ArrayElement &x, M &mutator) {
317 if (mutator.Pre(x)) {
318 Walk(x.base, mutator);
319 Walk(x.subscripts, mutator);
320 mutator.Post(x);
321 }
322}
323template <typename V>
324void Walk(const CharSelector::LengthAndKind &x, V &visitor) {
325 if (visitor.Pre(x)) {
326 Walk(x.length, visitor);
327 Walk(x.kind, visitor);
328 visitor.Post(x);
329 }
330}
331template <typename M> void Walk(CharSelector::LengthAndKind &x, M &mutator) {
332 if (mutator.Pre(x)) {
333 Walk(x.length, mutator);
334 Walk(x.kind, mutator);
335 mutator.Post(x);
336 }
337}
338template <typename V> void Walk(const CaseValueRange::Range &x, V &visitor) {
339 if (visitor.Pre(x)) {
340 Walk(x.lower, visitor);
341 Walk(x.upper, visitor);
342 visitor.Post(x);
343 }
344}
345template <typename M> void Walk(CaseValueRange::Range &x, M &mutator) {
346 if (mutator.Pre(x)) {
347 Walk(x.lower, mutator);
348 Walk(x.upper, mutator);
349 mutator.Post(x);
350 }
351}
352template <typename V> void Walk(const CoindexedNamedObject &x, V &visitor) {
353 if (visitor.Pre(x)) {
354 Walk(x.base, visitor);
355 Walk(x.imageSelector, visitor);
356 visitor.Post(x);
357 }
358}
359template <typename M> void Walk(CoindexedNamedObject &x, M &mutator) {
360 if (mutator.Pre(x)) {
361 Walk(x.base, mutator);
362 Walk(x.imageSelector, mutator);
363 mutator.Post(x);
364 }
365}
366template <typename V>
367void Walk(const DeclarationTypeSpec::Class &x, V &visitor) {
368 if (visitor.Pre(x)) {
369 Walk(x.derived, visitor);
370 visitor.Post(x);
371 }
372}
373template <typename M> void Walk(DeclarationTypeSpec::Class &x, M &mutator) {
374 if (mutator.Pre(x)) {
375 Walk(x.derived, mutator);
376 mutator.Post(x);
377 }
378}
379template <typename V>
380void Walk(const DeclarationTypeSpec::Type &x, V &visitor) {
381 if (visitor.Pre(x)) {
382 Walk(x.derived, visitor);
383 visitor.Post(x);
384 }
385}
386template <typename M> void Walk(DeclarationTypeSpec::Type &x, M &mutator) {
387 if (mutator.Pre(x)) {
388 Walk(x.derived, mutator);
389 mutator.Post(x);
390 }
391}
392template <typename V> void Walk(const ImportStmt &x, V &visitor) {
393 if (visitor.Pre(x)) {
394 Walk(x.names, visitor);
395 visitor.Post(x);
396 }
397}
398template <typename M> void Walk(ImportStmt &x, M &mutator) {
399 if (mutator.Pre(x)) {
400 Walk(x.names, mutator);
401 mutator.Post(x);
402 }
403}
404template <typename V>
405void Walk(const IntrinsicTypeSpec::Character &x, V &visitor) {
406 if (visitor.Pre(x)) {
407 Walk(x.selector, visitor);
408 visitor.Post(x);
409 }
410}
411template <typename M> void Walk(IntrinsicTypeSpec::Character &x, M &mutator) {
412 if (mutator.Pre(x)) {
413 Walk(x.selector, mutator);
414 mutator.Post(x);
415 }
416}
417template <typename V>
418void Walk(const IntrinsicTypeSpec::Complex &x, V &visitor) {
419 if (visitor.Pre(x)) {
420 Walk(x.kind, visitor);
421 visitor.Post(x);
422 }
423}
424template <typename M> void Walk(IntrinsicTypeSpec::Complex &x, M &mutator) {
425 if (mutator.Pre(x)) {
426 Walk(x.kind, mutator);
427 mutator.Post(x);
428 }
429}
430template <typename V>
431void Walk(const IntrinsicTypeSpec::Logical &x, V &visitor) {
432 if (visitor.Pre(x)) {
433 Walk(x.kind, visitor);
434 visitor.Post(x);
435 }
436}
437template <typename M> void Walk(IntrinsicTypeSpec::Logical &x, M &mutator) {
438 if (mutator.Pre(x)) {
439 Walk(x.kind, mutator);
440 mutator.Post(x);
441 }
442}
443template <typename V> void Walk(const IntrinsicTypeSpec::Real &x, V &visitor) {
444 if (visitor.Pre(x)) {
445 Walk(x.kind, visitor);
446 visitor.Post(x);
447 }
448}
449template <typename M> void Walk(IntrinsicTypeSpec::Real &x, M &mutator) {
450 if (mutator.Pre(x)) {
451 Walk(x.kind, mutator);
452 mutator.Post(x);
453 }
454}
455template <typename A, typename B, typename V>
456void Walk(const LoopBounds<A, B> &x, V &visitor) {
457 if (visitor.Pre(x)) {
458 Walk(x.name, visitor);
459 Walk(x.lower, visitor);
460 Walk(x.upper, visitor);
461 Walk(x.step, visitor);
462 visitor.Post(x);
463 }
464}
465template <typename A, typename B, typename M>
466void Walk(LoopBounds<A, B> &x, M &mutator) {
467 if (mutator.Pre(x)) {
468 Walk(x.name, mutator);
469 Walk(x.lower, mutator);
470 Walk(x.upper, mutator);
471 Walk(x.step, mutator);
472 mutator.Post(x);
473 }
474}
475template <typename V> void Walk(const CommonStmt &x, V &visitor) {
476 if (visitor.Pre(x)) {
477 Walk(x.blocks, visitor);
478 visitor.Post(x);
479 }
480}
481template <typename M> void Walk(CommonStmt &x, M &mutator) {
482 if (mutator.Pre(x)) {
483 Walk(x.blocks, mutator);
484 mutator.Post(x);
485 }
486}
487
488// Expr traversal uses iteration rather than recursion to avoid
489// blowing out the stack on very deep expression parse trees.
490// It replaces implementations that looked like:
491// template <typename V> void Walk(const Expr &x, V visitor) {
492// if (visitor.Pre(x)) { // Pre on the Expr
493// Walk(x.source, visitor);
494// // Pre on the operator, walk the operands, Post on operator
495// Walk(x.u, visitor);
496// visitor.Post(x); // Post on the Expr
497// }
498// }
499template <typename A, typename V, typename UNARY, typename BINARY>
500static void IterativeWalk(A &start, V &visitor) {
501 struct ExprWorkList {
502 ExprWorkList(A &x) : expr(&x) {}
503 bool doPostExpr{false}, doPostOpr{false};
504 A *expr;
505 };
506 std::vector<ExprWorkList> stack;
507 stack.emplace_back(start);
508 do {
509 A &expr{*stack.back().expr};
510 if (stack.back().doPostOpr) {
511 stack.back().doPostOpr = false;
512 common::visit([&visitor](auto &y) { visitor.Post(y); }, expr.u);
513 } else if (stack.back().doPostExpr) {
514 visitor.Post(expr);
515 stack.pop_back();
516 } else if (!visitor.Pre(expr)) {
517 stack.pop_back();
518 } else {
519 stack.back().doPostExpr = true;
520 Walk(expr.source, visitor);
521 UNARY *unary{nullptr};
522 BINARY *binary{nullptr};
523 common::visit(
524 [&unary, &binary](auto &y) {
525 if constexpr (std::is_convertible_v<decltype(&y), UNARY *>) {
526 unary = &y;
527 } else if constexpr (std::is_convertible_v<decltype(&y),
528 BINARY *>) {
529 binary = &y;
530 }
531 },
532 expr.u);
533 if (!unary && !binary) {
534 Walk(expr.u, visitor);
535 } else if (common::visit(
536 [&visitor](auto &y) { return visitor.Pre(y); }, expr.u)) {
537 stack.back().doPostOpr = true;
538 if (unary) {
539 stack.emplace_back(unary->v.value());
540 } else {
541 stack.emplace_back(std::get<1>(binary->t).value());
542 stack.emplace_back(std::get<0>(binary->t).value());
543 }
544 }
545 }
546 } while (!stack.empty());
547}
548template <typename V> void Walk(const Expr &x, V &visitor) {
549 IterativeWalk<const Expr, V, const Expr::IntrinsicUnary,
550 const Expr::IntrinsicBinary>(x, visitor);
551}
552template <typename M> void Walk(Expr &x, M &mutator) {
553 IterativeWalk<Expr, M, Expr::IntrinsicUnary, Expr::IntrinsicBinary>(
554 x, mutator);
555}
556
557template <typename V> void Walk(const Designator &x, V &visitor) {
558 if (visitor.Pre(x)) {
559 Walk(x.source, visitor);
560 Walk(x.u, visitor);
561 visitor.Post(x);
562 }
563}
564template <typename M> void Walk(Designator &x, M &mutator) {
565 if (mutator.Pre(x)) {
566 Walk(x.source, mutator);
567 Walk(x.u, mutator);
568 mutator.Post(x);
569 }
570}
571template <typename V> void Walk(const FunctionReference &x, V &visitor) {
572 if (visitor.Pre(x)) {
573 Walk(x.source, visitor);
574 Walk(x.v, visitor);
575 visitor.Post(x);
576 }
577}
578template <typename M> void Walk(FunctionReference &x, M &mutator) {
579 if (mutator.Pre(x)) {
580 Walk(x.source, mutator);
581 Walk(x.v, mutator);
582 mutator.Post(x);
583 }
584}
585template <typename V> void Walk(const CallStmt &x, V &visitor) {
586 if (visitor.Pre(x)) {
587 Walk(x.source, visitor);
588 Walk(x.call, visitor);
589 Walk(x.chevrons, visitor);
590 visitor.Post(x);
591 }
592}
593template <typename M> void Walk(CallStmt &x, M &mutator) {
594 if (mutator.Pre(x)) {
595 Walk(x.source, mutator);
596 Walk(x.call, mutator);
597 Walk(x.chevrons, mutator);
598 mutator.Post(x);
599 }
600}
601template <typename V> void Walk(const PartRef &x, V &visitor) {
602 if (visitor.Pre(x)) {
603 Walk(x.name, visitor);
604 Walk(x.subscripts, visitor);
605 Walk(x.imageSelector, visitor);
606 visitor.Post(x);
607 }
608}
609template <typename M> void Walk(PartRef &x, M &mutator) {
610 if (mutator.Pre(x)) {
611 Walk(x.name, mutator);
612 Walk(x.subscripts, mutator);
613 Walk(x.imageSelector, mutator);
614 mutator.Post(x);
615 }
616}
617template <typename V> void Walk(const ReadStmt &x, V &visitor) {
618 if (visitor.Pre(x)) {
619 Walk(x.iounit, visitor);
620 Walk(x.format, visitor);
621 Walk(x.controls, visitor);
622 Walk(x.items, visitor);
623 visitor.Post(x);
624 }
625}
626template <typename M> void Walk(ReadStmt &x, M &mutator) {
627 if (mutator.Pre(x)) {
628 Walk(x.iounit, mutator);
629 Walk(x.format, mutator);
630 Walk(x.controls, mutator);
631 Walk(x.items, mutator);
632 mutator.Post(x);
633 }
634}
635template <typename V> void Walk(const SignedIntLiteralConstant &x, V &visitor) {
636 if (visitor.Pre(x)) {
637 Walk(x.source, visitor);
638 Walk(x.t, visitor);
639 visitor.Post(x);
640 }
641}
642template <typename M> void Walk(SignedIntLiteralConstant &x, M &mutator) {
643 if (mutator.Pre(x)) {
644 Walk(x.source, mutator);
645 Walk(x.t, mutator);
646 mutator.Post(x);
647 }
648}
649template <typename V> void Walk(const RealLiteralConstant &x, V &visitor) {
650 if (visitor.Pre(x)) {
651 Walk(x.real, visitor);
652 Walk(x.kind, visitor);
653 visitor.Post(x);
654 }
655}
656template <typename M> void Walk(RealLiteralConstant &x, M &mutator) {
657 if (mutator.Pre(x)) {
658 Walk(x.real, mutator);
659 Walk(x.kind, mutator);
660 mutator.Post(x);
661 }
662}
663template <typename V>
664void Walk(const RealLiteralConstant::Real &x, V &visitor) {
665 if (visitor.Pre(x)) {
666 Walk(x.source, visitor);
667 visitor.Post(x);
668 }
669}
670template <typename M> void Walk(RealLiteralConstant::Real &x, M &mutator) {
671 if (mutator.Pre(x)) {
672 Walk(x.source, mutator);
673 mutator.Post(x);
674 }
675}
676template <typename V> void Walk(const StructureComponent &x, V &visitor) {
677 if (visitor.Pre(x)) {
678 Walk(x.base, visitor);
679 Walk(x.component, visitor);
680 visitor.Post(x);
681 }
682}
683template <typename M> void Walk(StructureComponent &x, M &mutator) {
684 if (mutator.Pre(x)) {
685 Walk(x.base, mutator);
686 Walk(x.component, mutator);
687 mutator.Post(x);
688 }
689}
690template <typename V> void Walk(const Suffix &x, V &visitor) {
691 if (visitor.Pre(x)) {
692 Walk(x.binding, visitor);
693 Walk(x.resultName, visitor);
694 visitor.Post(x);
695 }
696}
697template <typename M> void Walk(Suffix &x, M &mutator) {
698 if (mutator.Pre(x)) {
699 Walk(x.binding, mutator);
700 Walk(x.resultName, mutator);
701 mutator.Post(x);
702 }
703}
704template <typename V>
705void Walk(const TypeBoundProcedureStmt::WithInterface &x, V &visitor) {
706 if (visitor.Pre(x)) {
707 Walk(x.interfaceName, visitor);
708 Walk(x.attributes, visitor);
709 Walk(x.bindingNames, visitor);
710 visitor.Post(x);
711 }
712}
713template <typename M>
714void Walk(TypeBoundProcedureStmt::WithInterface &x, M &mutator) {
715 if (mutator.Pre(x)) {
716 Walk(x.interfaceName, mutator);
717 Walk(x.attributes, mutator);
718 Walk(x.bindingNames, mutator);
719 mutator.Post(x);
720 }
721}
722template <typename V>
723void Walk(const TypeBoundProcedureStmt::WithoutInterface &x, V &visitor) {
724 if (visitor.Pre(x)) {
725 Walk(x.attributes, visitor);
726 Walk(x.declarations, visitor);
727 visitor.Post(x);
728 }
729}
730template <typename M>
731void Walk(TypeBoundProcedureStmt::WithoutInterface &x, M &mutator) {
732 if (mutator.Pre(x)) {
733 Walk(x.attributes, mutator);
734 Walk(x.declarations, mutator);
735 mutator.Post(x);
736 }
737}
738template <typename V> void Walk(const UseStmt &x, V &visitor) {
739 if (visitor.Pre(x)) {
740 Walk(x.nature, visitor);
741 Walk(x.moduleName, visitor);
742 Walk(x.u, visitor);
743 visitor.Post(x);
744 }
745}
746template <typename M> void Walk(UseStmt &x, M &mutator) {
747 if (mutator.Pre(x)) {
748 Walk(x.nature, mutator);
749 Walk(x.moduleName, mutator);
750 Walk(x.u, mutator);
751 mutator.Post(x);
752 }
753}
754template <typename V> void Walk(const WriteStmt &x, V &visitor) {
755 if (visitor.Pre(x)) {
756 Walk(x.iounit, visitor);
757 Walk(x.format, visitor);
758 Walk(x.controls, visitor);
759 Walk(x.items, visitor);
760 visitor.Post(x);
761 }
762}
763template <typename M> void Walk(WriteStmt &x, M &mutator) {
764 if (mutator.Pre(x)) {
765 Walk(x.iounit, mutator);
766 Walk(x.format, mutator);
767 Walk(x.controls, mutator);
768 Walk(x.items, mutator);
769 mutator.Post(x);
770 }
771}
772template <typename V> void Walk(const format::ControlEditDesc &x, V &visitor) {
773 if (visitor.Pre(x)) {
774 Walk(x.kind, visitor);
775 visitor.Post(x);
776 }
777}
778template <typename M> void Walk(format::ControlEditDesc &x, M &mutator) {
779 if (mutator.Pre(x)) {
780 Walk(x.kind, mutator);
781 mutator.Post(x);
782 }
783}
784template <typename V>
785void Walk(const format::DerivedTypeDataEditDesc &x, V &visitor) {
786 if (visitor.Pre(x)) {
787 Walk(x.type, visitor);
788 Walk(x.parameters, visitor);
789 visitor.Post(x);
790 }
791}
792template <typename M>
793void Walk(format::DerivedTypeDataEditDesc &x, M &mutator) {
794 if (mutator.Pre(x)) {
795 Walk(x.type, mutator);
796 Walk(x.parameters, mutator);
797 mutator.Post(x);
798 }
799}
800template <typename V> void Walk(const format::FormatItem &x, V &visitor) {
801 if (visitor.Pre(x)) {
802 Walk(x.repeatCount, visitor);
803 Walk(x.u, visitor);
804 visitor.Post(x);
805 }
806}
807template <typename M> void Walk(format::FormatItem &x, M &mutator) {
808 if (mutator.Pre(x)) {
809 Walk(x.repeatCount, mutator);
810 Walk(x.u, mutator);
811 mutator.Post(x);
812 }
813}
814template <typename V>
815void Walk(const format::FormatSpecification &x, V &visitor) {
816 if (visitor.Pre(x)) {
817 Walk(x.items, visitor);
818 Walk(x.unlimitedItems, visitor);
819 visitor.Post(x);
820 }
821}
822template <typename M> void Walk(format::FormatSpecification &x, M &mutator) {
823 if (mutator.Pre(x)) {
824 Walk(x.items, mutator);
825 Walk(x.unlimitedItems, mutator);
826 mutator.Post(x);
827 }
828}
829template <typename V>
830void Walk(const format::IntrinsicTypeDataEditDesc &x, V &visitor) {
831 if (visitor.Pre(x)) {
832 Walk(x.kind, visitor);
833 Walk(x.width, visitor);
834 Walk(x.digits, visitor);
835 Walk(x.exponentWidth, visitor);
836 visitor.Post(x);
837 }
838}
839template <typename M>
840void Walk(format::IntrinsicTypeDataEditDesc &x, M &mutator) {
841 if (mutator.Pre(x)) {
842 Walk(x.kind, mutator);
843 Walk(x.width, mutator);
844 Walk(x.digits, mutator);
845 Walk(x.exponentWidth, mutator);
846 mutator.Post(x);
847 }
848}
849template <typename V> void Walk(const CompilerDirective &x, V &visitor) {
850 if (visitor.Pre(x)) {
851 Walk(x.source, visitor);
852 Walk(x.u, visitor);
853 visitor.Post(x);
854 }
855}
856template <typename M> void Walk(CompilerDirective &x, M &mutator) {
857 if (mutator.Pre(x)) {
858 Walk(x.source, mutator);
859 Walk(x.u, mutator);
860 mutator.Post(x);
861 }
862}
863template <typename V>
864void Walk(const CompilerDirective::Unrecognized &x, V &visitor) {
865 if (visitor.Pre(x)) {
866 visitor.Post(x);
867 }
868}
869template <typename M>
870void Walk(CompilerDirective::Unrecognized &x, M &mutator) {
871 if (mutator.Pre(x)) {
872 mutator.Post(x);
873 }
874}
875template <typename V>
876void Walk(const OmpLinearClause::WithModifier &x, V &visitor) {
877 if (visitor.Pre(x)) {
878 Walk(x.modifier, visitor);
879 Walk(x.names, visitor);
880 Walk(x.step, visitor);
881 visitor.Post(x);
882 }
883}
884template <typename M> void Walk(OmpLinearClause::WithModifier &x, M &mutator) {
885 if (mutator.Pre(x)) {
886 Walk(x.modifier, mutator);
887 Walk(x.names, mutator);
888 Walk(x.step, mutator);
889 mutator.Post(x);
890 }
891}
892template <typename V>
893void Walk(const OmpLinearClause::WithoutModifier &x, V &visitor) {
894 if (visitor.Pre(x)) {
895 Walk(x.names, visitor);
896 Walk(x.step, visitor);
897 visitor.Post(x);
898 }
899}
900template <typename M>
901void Walk(OmpLinearClause::WithoutModifier &x, M &mutator) {
902 if (mutator.Pre(x)) {
903 Walk(x.names, mutator);
904 Walk(x.step, mutator);
905 mutator.Post(x);
906 }
907}
908} // namespace Fortran::parser
909#endif // FORTRAN_PARSER_PARSE_TREE_VISITOR_H_
910

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of flang/include/flang/Parser/parse-tree-visitor.h