FLANG
parse-tree-visitor.h
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/enum-set.h"
14#include "flang/Common/visit.h"
15#include <cstddef>
16#include <optional>
17#include <tuple>
18#include <utility>
19#include <variant>
20#include <vector>
21
30
31namespace Fortran::parser {
32
33template <typename A, typename V> void Walk(const A &x, V &visitor);
34template <typename A, typename M> void Walk(A &x, M &mutator);
35
36namespace detail {
37// A number of the Walk functions below call other Walk functions. Define
38// a dummy class, and put all of them in it to ensure that name lookup for
39// Walk considers all overloads (not just those defined prior to the call
40// to Walk).
42 // Default case for visitation of non-class data members, strings, and
43 // any other non-decomposable values.
44 template <typename A, typename V>
45 static std::enable_if_t<!std::is_class_v<A> || common::IsEnumSet<A> ||
46 std::is_same_v<std::string, A> || std::is_same_v<CharBlock, A>>
47 Walk(const A &x, V &visitor) {
48 if (visitor.Pre(x)) {
49 visitor.Post(x);
50 }
51 }
52 template <typename A, typename M>
53 static std::enable_if_t<!std::is_class_v<A> ||
54 std::is_same_v<std::string, A> || std::is_same_v<CharBlock, A>>
55 Walk(A &x, M &mutator) {
56 if (mutator.Pre(x)) {
57 mutator.Post(x);
58 }
59 }
60
61 // Traversal of needed STL template classes (optional, list, tuple, variant)
62 // For most lists, just traverse the elements; but when a list constitutes
63 // a Block (i.e., std::list<ExecutionPartConstruct>), also invoke the
64 // visitor/mutator on the list itself.
65 template <typename T, typename V>
66 static void Walk(const std::list<T> &x, V &visitor) {
67 for (const auto &elem : x) {
68 Walk(elem, visitor);
69 }
70 }
71 template <typename T, typename M>
72 static void Walk(std::list<T> &x, M &mutator) {
73 for (auto &elem : x) {
74 Walk(elem, mutator);
75 }
76 }
77 template <typename V> static void Walk(const Block &x, V &visitor) {
78 if (visitor.Pre(x)) {
79 for (const auto &elem : x) {
80 Walk(elem, visitor);
81 }
82 visitor.Post(x);
83 }
84 }
85 template <typename M> static void Walk(Block &x, M &mutator) {
86 if (mutator.Pre(x)) {
87 for (auto &elem : x) {
88 Walk(elem, mutator);
89 }
90 mutator.Post(x);
91 }
92 }
93 template <typename T, typename V>
94 static void Walk(const std::optional<T> &x, V &visitor) {
95 if (x) {
96 Walk(*x, visitor);
97 }
98 }
99 template <typename T, typename M>
100 static void Walk(std::optional<T> &x, M &mutator) {
101 if (x) {
102 Walk(*x, mutator);
103 }
104 }
105 template <std::size_t I = 0, typename Func, typename T>
106 static void ForEachInTuple(const T &tuple, Func func) {
107 func(std::get<I>(tuple));
108 if constexpr (I + 1 < std::tuple_size_v<T>) {
109 ForEachInTuple<I + 1>(tuple, func);
110 }
111 }
112 template <typename V, typename... A>
113 static void Walk(const std::tuple<A...> &x, V &visitor) {
114 if (sizeof...(A) > 0) {
115 if (visitor.Pre(x)) {
116 ForEachInTuple(x, [&](const auto &y) { Walk(y, visitor); });
117 visitor.Post(x);
118 }
119 }
120 }
121 template <std::size_t I = 0, typename Func, typename T>
122 static void ForEachInTuple(T &tuple, Func func) {
123 func(std::get<I>(tuple));
124 if constexpr (I + 1 < std::tuple_size_v<T>) {
125 ForEachInTuple<I + 1>(tuple, func);
126 }
127 }
128 template <typename M, typename... A>
129 static void Walk(std::tuple<A...> &x, M &mutator) {
130 if (sizeof...(A) > 0) {
131 if (mutator.Pre(x)) {
132 ForEachInTuple(x, [&](auto &y) { Walk(y, mutator); });
133 mutator.Post(x);
134 }
135 }
136 }
137 template <typename V, typename... A>
138 static void Walk(const std::variant<A...> &x, V &visitor) {
139 if (visitor.Pre(x)) {
140 common::visit([&](const auto &y) { Walk(y, visitor); }, x);
141 visitor.Post(x);
142 }
143 }
144 template <typename M, typename... A>
145 static void Walk(std::variant<A...> &x, M &mutator) {
146 if (mutator.Pre(x)) {
147 common::visit([&](auto &y) { Walk(y, mutator); }, x);
148 mutator.Post(x);
149 }
150 }
151 template <typename A, typename B, typename V>
152 static void Walk(const std::pair<A, B> &x, V &visitor) {
153 if (visitor.Pre(x)) {
154 Walk(x.first, visitor);
155 Walk(x.second, visitor);
156 }
157 }
158 template <typename A, typename B, typename M>
159 static void Walk(std::pair<A, B> &x, M &mutator) {
160 if (mutator.Pre(x)) {
161 Walk(x.first, mutator);
162 Walk(x.second, mutator);
163 }
164 }
165
166 // Trait-determined traversal of empty, tuple, union, wrapper,
167 // and constraint-checking classes.
168 template <typename A, typename V>
169 static std::enable_if_t<EmptyTrait<A>> Walk(const A &x, V &visitor) {
170 if (visitor.Pre(x)) {
171 visitor.Post(x);
172 }
173 }
174 template <typename A, typename M>
175 static std::enable_if_t<EmptyTrait<A>> Walk(A &x, M &mutator) {
176 if (mutator.Pre(x)) {
177 mutator.Post(x);
178 }
179 }
180
181 template <typename A, typename V>
182 static std::enable_if_t<TupleTrait<A>> Walk(const A &x, V &visitor) {
183 if (visitor.Pre(x)) {
184 Walk(x.t, visitor);
185 visitor.Post(x);
186 }
187 }
188 template <typename A, typename M>
189 static std::enable_if_t<TupleTrait<A>> Walk(A &x, M &mutator) {
190 if (mutator.Pre(x)) {
191 Walk(x.t, mutator);
192 mutator.Post(x);
193 }
194 }
195
196 template <typename A, typename V>
197 static std::enable_if_t<UnionTrait<A>> Walk(const A &x, V &visitor) {
198 if (visitor.Pre(x)) {
199 Walk(x.u, visitor);
200 visitor.Post(x);
201 }
202 }
203 template <typename A, typename M>
204 static std::enable_if_t<UnionTrait<A>> Walk(A &x, M &mutator) {
205 if (mutator.Pre(x)) {
206 Walk(x.u, mutator);
207 mutator.Post(x);
208 }
209 }
210
211 template <typename A, typename V>
212 static std::enable_if_t<WrapperTrait<A>> Walk(const A &x, V &visitor) {
213 if (visitor.Pre(x)) {
214 Walk(x.v, visitor);
215 visitor.Post(x);
216 }
217 }
218 template <typename A, typename M>
219 static std::enable_if_t<WrapperTrait<A>> Walk(A &x, M &mutator) {
220 if (mutator.Pre(x)) {
221 Walk(x.v, mutator);
222 mutator.Post(x);
223 }
224 }
225
226 template <typename A, typename V>
227 static std::enable_if_t<ConstraintTrait<A>> Walk(const A &x, V &visitor) {
228 if (visitor.Pre(x)) {
229 Walk(x.thing, visitor);
230 visitor.Post(x);
231 }
232 }
233 template <typename A, typename M>
234 static std::enable_if_t<ConstraintTrait<A>> Walk(A &x, M &mutator) {
235 if (mutator.Pre(x)) {
236 Walk(x.thing, mutator);
237 mutator.Post(x);
238 }
239 }
240
241 template <typename T, typename V>
242 static void Walk(const common::Indirection<T> &x, V &visitor) {
243 Walk(x.value(), visitor);
244 }
245 template <typename T, typename M>
246 static void Walk(common::Indirection<T> &x, M &mutator) {
247 Walk(x.value(), mutator);
248 }
249
250 template <typename T, typename V>
251 static void Walk(const Statement<T> &x, V &visitor) {
252 if (visitor.Pre(x)) {
253 // N.B. The label, if any, is not visited.
254 Walk(x.source, visitor);
255 Walk(x.statement, visitor);
256 visitor.Post(x);
257 }
258 }
259 template <typename T, typename M>
260 static void Walk(Statement<T> &x, M &mutator) {
261 if (mutator.Pre(x)) {
262 // N.B. The label, if any, is not visited.
263 Walk(x.source, mutator);
264 Walk(x.statement, mutator);
265 mutator.Post(x);
266 }
267 }
268
269 template <typename T, typename V>
270 static void Walk(const UnlabeledStatement<T> &x, V &visitor) {
271 if (visitor.Pre(x)) {
272 Walk(x.source, visitor);
273 Walk(x.statement, visitor);
274 visitor.Post(x);
275 }
276 }
277 template <typename T, typename M>
278 static void Walk(UnlabeledStatement<T> &x, M &mutator) {
279 if (mutator.Pre(x)) {
280 Walk(x.source, mutator);
281 Walk(x.statement, mutator);
282 mutator.Post(x);
283 }
284 }
285
286 template <typename V> static void Walk(const Name &x, V &visitor) {
287 if (visitor.Pre(x)) {
288 Walk(x.source, visitor);
289 visitor.Post(x);
290 }
291 }
292 template <typename M> static void Walk(Name &x, M &mutator) {
293 if (mutator.Pre(x)) {
294 Walk(x.source, mutator);
295 mutator.Post(x);
296 }
297 }
298
299 template <typename V> static void Walk(const ArrayElement &x, V &visitor) {
300 if (visitor.Pre(x)) {
301 Walk(x.base, visitor);
302 Walk(x.subscripts, visitor);
303 visitor.Post(x);
304 }
305 }
306 template <typename M> static void Walk(ArrayElement &x, M &mutator) {
307 if (mutator.Pre(x)) {
308 Walk(x.base, mutator);
309 Walk(x.subscripts, mutator);
310 mutator.Post(x);
311 }
312 }
313 template <typename V>
314 static void Walk(const CoindexedNamedObject &x, V &visitor) {
315 if (visitor.Pre(x)) {
316 Walk(x.base, visitor);
317 Walk(x.imageSelector, visitor);
318 visitor.Post(x);
319 }
320 }
321 template <typename M> static void Walk(CoindexedNamedObject &x, M &mutator) {
322 if (mutator.Pre(x)) {
323 Walk(x.base, mutator);
324 Walk(x.imageSelector, mutator);
325 mutator.Post(x);
326 }
327 }
328 template <typename A, typename B, typename V>
329 static void Walk(const LoopBounds<A, B> &x, V &visitor) {
330 if (visitor.Pre(x)) {
331 Walk(x.name, visitor);
332 Walk(x.lower, visitor);
333 Walk(x.upper, visitor);
334 Walk(x.step, visitor);
335 visitor.Post(x);
336 }
337 }
338 template <typename A, typename B, typename M>
339 static void Walk(LoopBounds<A, B> &x, M &mutator) {
340 if (mutator.Pre(x)) {
341 Walk(x.name, mutator);
342 Walk(x.lower, mutator);
343 Walk(x.upper, mutator);
344 Walk(x.step, mutator);
345 mutator.Post(x);
346 }
347 }
348
349 // Expr traversal uses iteration rather than recursion to avoid
350 // blowing out the stack on very deep expression parse trees.
351 // It replaces implementations that looked like:
352 // template <typename V> static void Walk(const Expr &x, V visitor) {
353 // if (visitor.Pre(x)) { // Pre on the Expr
354 // Walk(x.source, visitor);
355 // // Pre on the operator, walk the operands, Post on operator
356 // Walk(x.u, visitor);
357 // visitor.Post(x); // Post on the Expr
358 // }
359 // }
360 template <typename A, typename V, typename UNARY, typename BINARY>
361 static void IterativeWalk(A &start, V &visitor) {
362 struct ExprWorkList {
363 ExprWorkList(A &x) : expr(&x) {}
364 bool doPostExpr{false}, doPostOpr{false};
365 A *expr;
366 };
367 std::vector<ExprWorkList> stack;
368 stack.emplace_back(start);
369 do {
370 A &expr{*stack.back().expr};
371 if (stack.back().doPostOpr) {
372 stack.back().doPostOpr = false;
373 common::visit([&visitor](auto &y) { visitor.Post(y); }, expr.u);
374 } else if (stack.back().doPostExpr) {
375 visitor.Post(expr);
376 stack.pop_back();
377 } else if (!visitor.Pre(expr)) {
378 stack.pop_back();
379 } else {
380 stack.back().doPostExpr = true;
381 Walk(expr.source, visitor);
382 UNARY *unary{nullptr};
383 BINARY *binary{nullptr};
384 common::visit(
385 [&unary, &binary](auto &y) {
386 if constexpr (std::is_convertible_v<decltype(&y), UNARY *>) {
387 unary = &y;
388 } else if constexpr (std::is_convertible_v<decltype(&y),
389 BINARY *>) {
390 binary = &y;
391 }
392 },
393 expr.u);
394 if (!unary && !binary) {
395 Walk(expr.u, visitor);
396 } else if (common::visit([&visitor](auto &y) { return visitor.Pre(y); },
397 expr.u)) {
398 stack.back().doPostOpr = true;
399 if (unary) {
400 stack.emplace_back(unary->v.value());
401 } else {
402 stack.emplace_back(std::get<1>(binary->t).value());
403 stack.emplace_back(std::get<0>(binary->t).value());
404 }
405 }
406 }
407 } while (!stack.empty());
408 }
409 template <typename V> static void Walk(const Expr &x, V &visitor) {
410 IterativeWalk<const Expr, V, const Expr::IntrinsicUnary,
411 const Expr::IntrinsicBinary>(x, visitor);
412 }
413 template <typename M> static void Walk(Expr &x, M &mutator) {
414 IterativeWalk<Expr, M, Expr::IntrinsicUnary, Expr::IntrinsicBinary>(
415 x, mutator);
416 }
417
418 template <typename V> static void Walk(const Designator &x, V &visitor) {
419 if (visitor.Pre(x)) {
420 Walk(x.source, visitor);
421 Walk(x.u, visitor);
422 visitor.Post(x);
423 }
424 }
425 template <typename M> static void Walk(Designator &x, M &mutator) {
426 if (mutator.Pre(x)) {
427 Walk(x.source, mutator);
428 Walk(x.u, mutator);
429 mutator.Post(x);
430 }
431 }
432 template <typename V>
433 static void Walk(const FunctionReference &x, V &visitor) {
434 if (visitor.Pre(x)) {
435 Walk(x.source, visitor);
436 Walk(x.v, visitor);
437 visitor.Post(x);
438 }
439 }
440 template <typename M> static void Walk(FunctionReference &x, M &mutator) {
441 if (mutator.Pre(x)) {
442 Walk(x.source, mutator);
443 Walk(x.v, mutator);
444 mutator.Post(x);
445 }
446 }
447 template <typename V> static void Walk(const CallStmt &x, V &visitor) {
448 if (visitor.Pre(x)) {
449 Walk(x.source, visitor);
450 Walk(x.call, visitor);
451 Walk(x.chevrons, visitor);
452 visitor.Post(x);
453 }
454 }
455 template <typename M> static void Walk(CallStmt &x, M &mutator) {
456 if (mutator.Pre(x)) {
457 Walk(x.source, mutator);
458 Walk(x.call, mutator);
459 Walk(x.chevrons, mutator);
460 mutator.Post(x);
461 }
462 }
463 template <typename V> static void Walk(const PartRef &x, V &visitor) {
464 if (visitor.Pre(x)) {
465 Walk(x.name, visitor);
466 Walk(x.subscripts, visitor);
467 Walk(x.imageSelector, visitor);
468 visitor.Post(x);
469 }
470 }
471 template <typename M> static void Walk(PartRef &x, M &mutator) {
472 if (mutator.Pre(x)) {
473 Walk(x.name, mutator);
474 Walk(x.subscripts, mutator);
475 Walk(x.imageSelector, mutator);
476 mutator.Post(x);
477 }
478 }
479 template <typename V> static void Walk(const ReadStmt &x, V &visitor) {
480 if (visitor.Pre(x)) {
481 Walk(x.iounit, visitor);
482 Walk(x.format, visitor);
483 Walk(x.controls, visitor);
484 Walk(x.items, visitor);
485 visitor.Post(x);
486 }
487 }
488 template <typename M> static void Walk(ReadStmt &x, M &mutator) {
489 if (mutator.Pre(x)) {
490 Walk(x.iounit, mutator);
491 Walk(x.format, mutator);
492 Walk(x.controls, mutator);
493 Walk(x.items, mutator);
494 mutator.Post(x);
495 }
496 }
497 template <typename V>
498 static void Walk(const SignedIntLiteralConstant &x, V &visitor) {
499 if (visitor.Pre(x)) {
500 Walk(x.source, visitor);
501 Walk(x.t, visitor);
502 visitor.Post(x);
503 }
504 }
505 template <typename M>
506 static void Walk(SignedIntLiteralConstant &x, M &mutator) {
507 if (mutator.Pre(x)) {
508 Walk(x.source, mutator);
509 Walk(x.t, mutator);
510 mutator.Post(x);
511 }
512 }
513 template <typename V>
514 static void Walk(const RealLiteralConstant &x, V &visitor) {
515 if (visitor.Pre(x)) {
516 Walk(x.real, visitor);
517 Walk(x.kind, visitor);
518 visitor.Post(x);
519 }
520 }
521 template <typename M> static void Walk(RealLiteralConstant &x, M &mutator) {
522 if (mutator.Pre(x)) {
523 Walk(x.real, mutator);
524 Walk(x.kind, mutator);
525 mutator.Post(x);
526 }
527 }
528 template <typename V>
529 static void Walk(const RealLiteralConstant::Real &x, V &visitor) {
530 if (visitor.Pre(x)) {
531 Walk(x.source, visitor);
532 visitor.Post(x);
533 }
534 }
535 template <typename M>
536 static void Walk(RealLiteralConstant::Real &x, M &mutator) {
537 if (mutator.Pre(x)) {
538 Walk(x.source, mutator);
539 mutator.Post(x);
540 }
541 }
542 template <typename V>
543 static void Walk(const StructureComponent &x, V &visitor) {
544 if (visitor.Pre(x)) {
545 Walk(x.base, visitor);
546 Walk(x.component, visitor);
547 visitor.Post(x);
548 }
549 }
550 template <typename M> static void Walk(StructureComponent &x, M &mutator) {
551 if (mutator.Pre(x)) {
552 Walk(x.base, mutator);
553 Walk(x.component, mutator);
554 mutator.Post(x);
555 }
556 }
557 template <typename V> static void Walk(const Suffix &x, V &visitor) {
558 if (visitor.Pre(x)) {
559 Walk(x.binding, visitor);
560 Walk(x.resultName, visitor);
561 visitor.Post(x);
562 }
563 }
564 template <typename M> static void Walk(Suffix &x, M &mutator) {
565 if (mutator.Pre(x)) {
566 Walk(x.binding, mutator);
567 Walk(x.resultName, mutator);
568 mutator.Post(x);
569 }
570 }
571 template <typename V>
572 static void Walk(const TypeBoundProcedureStmt::WithInterface &x, V &visitor) {
573 if (visitor.Pre(x)) {
574 Walk(x.interfaceName, visitor);
575 Walk(x.attributes, visitor);
576 Walk(x.bindingNames, visitor);
577 visitor.Post(x);
578 }
579 }
580 template <typename M>
581 static void Walk(TypeBoundProcedureStmt::WithInterface &x, M &mutator) {
582 if (mutator.Pre(x)) {
583 Walk(x.interfaceName, mutator);
584 Walk(x.attributes, mutator);
585 Walk(x.bindingNames, mutator);
586 mutator.Post(x);
587 }
588 }
589 template <typename V>
590 static void Walk(
591 const TypeBoundProcedureStmt::WithoutInterface &x, V &visitor) {
592 if (visitor.Pre(x)) {
593 Walk(x.attributes, visitor);
594 Walk(x.declarations, visitor);
595 visitor.Post(x);
596 }
597 }
598 template <typename M>
599 static void Walk(TypeBoundProcedureStmt::WithoutInterface &x, M &mutator) {
600 if (mutator.Pre(x)) {
601 Walk(x.attributes, mutator);
602 Walk(x.declarations, mutator);
603 mutator.Post(x);
604 }
605 }
606 template <typename V> static void Walk(const UseStmt &x, V &visitor) {
607 if (visitor.Pre(x)) {
608 Walk(x.nature, visitor);
609 Walk(x.moduleName, visitor);
610 Walk(x.u, visitor);
611 visitor.Post(x);
612 }
613 }
614 template <typename M> static void Walk(UseStmt &x, M &mutator) {
615 if (mutator.Pre(x)) {
616 Walk(x.nature, mutator);
617 Walk(x.moduleName, mutator);
618 Walk(x.u, mutator);
619 mutator.Post(x);
620 }
621 }
622 template <typename V> static void Walk(const WriteStmt &x, V &visitor) {
623 if (visitor.Pre(x)) {
624 Walk(x.iounit, visitor);
625 Walk(x.format, visitor);
626 Walk(x.controls, visitor);
627 Walk(x.items, visitor);
628 visitor.Post(x);
629 }
630 }
631 template <typename M> static void Walk(WriteStmt &x, M &mutator) {
632 if (mutator.Pre(x)) {
633 Walk(x.iounit, mutator);
634 Walk(x.format, mutator);
635 Walk(x.controls, mutator);
636 Walk(x.items, mutator);
637 mutator.Post(x);
638 }
639 }
640 template <typename V>
641 static void Walk(const format::ControlEditDesc &x, V &visitor) {
642 if (visitor.Pre(x)) {
643 Walk(x.kind, visitor);
644 visitor.Post(x);
645 }
646 }
647 template <typename M>
648 static void Walk(format::ControlEditDesc &x, M &mutator) {
649 if (mutator.Pre(x)) {
650 Walk(x.kind, mutator);
651 mutator.Post(x);
652 }
653 }
654 template <typename V>
655 static void Walk(const format::DerivedTypeDataEditDesc &x, V &visitor) {
656 if (visitor.Pre(x)) {
657 Walk(x.type, visitor);
658 Walk(x.parameters, visitor);
659 visitor.Post(x);
660 }
661 }
662 template <typename M>
663 static void Walk(format::DerivedTypeDataEditDesc &x, M &mutator) {
664 if (mutator.Pre(x)) {
665 Walk(x.type, mutator);
666 Walk(x.parameters, mutator);
667 mutator.Post(x);
668 }
669 }
670 template <typename V>
671 static void Walk(const format::FormatItem &x, V &visitor) {
672 if (visitor.Pre(x)) {
673 Walk(x.repeatCount, visitor);
674 Walk(x.u, visitor);
675 visitor.Post(x);
676 }
677 }
678 template <typename M> static void Walk(format::FormatItem &x, M &mutator) {
679 if (mutator.Pre(x)) {
680 Walk(x.repeatCount, mutator);
681 Walk(x.u, mutator);
682 mutator.Post(x);
683 }
684 }
685 template <typename V>
686 static void Walk(const format::FormatSpecification &x, V &visitor) {
687 if (visitor.Pre(x)) {
688 Walk(x.items, visitor);
689 Walk(x.unlimitedItems, visitor);
690 visitor.Post(x);
691 }
692 }
693 template <typename M>
694 static void Walk(format::FormatSpecification &x, M &mutator) {
695 if (mutator.Pre(x)) {
696 Walk(x.items, mutator);
697 Walk(x.unlimitedItems, mutator);
698 mutator.Post(x);
699 }
700 }
701 template <typename V>
702 static void Walk(const format::IntrinsicTypeDataEditDesc &x, V &visitor) {
703 if (visitor.Pre(x)) {
704 Walk(x.kind, visitor);
705 Walk(x.width, visitor);
706 Walk(x.digits, visitor);
707 Walk(x.exponentWidth, visitor);
708 visitor.Post(x);
709 }
710 }
711 template <typename M>
712 static void Walk(format::IntrinsicTypeDataEditDesc &x, M &mutator) {
713 if (mutator.Pre(x)) {
714 Walk(x.kind, mutator);
715 Walk(x.width, mutator);
716 Walk(x.digits, mutator);
717 Walk(x.exponentWidth, mutator);
718 mutator.Post(x);
719 }
720 }
721 template <typename V>
722 static void Walk(const CompilerDirective &x, V &visitor) {
723 if (visitor.Pre(x)) {
724 Walk(x.source, visitor);
725 Walk(x.u, visitor);
726 visitor.Post(x);
727 }
728 }
729 template <typename M> static void Walk(CompilerDirective &x, M &mutator) {
730 if (mutator.Pre(x)) {
731 Walk(x.source, mutator);
732 Walk(x.u, mutator);
733 mutator.Post(x);
734 }
735 }
736 template <typename V>
737 static void Walk(const CompilerDirective::Unrecognized &x, V &visitor) {
738 if (visitor.Pre(x)) {
739 visitor.Post(x);
740 }
741 }
742 template <typename M>
743 static void Walk(CompilerDirective::Unrecognized &x, M &mutator) {
744 if (mutator.Pre(x)) {
745 mutator.Post(x);
746 }
747 }
748};
749} // namespace detail
750
751template <typename A, typename V> void Walk(const A &x, V &visitor) {
752 detail::ParseTreeVisitorLookupScope::Walk(x, visitor);
753}
754
755template <typename A, typename M> void Walk(A &x, M &mutator) {
756 detail::ParseTreeVisitorLookupScope::Walk(x, mutator);
757}
758
759} // namespace Fortran::parser
760#endif // FORTRAN_PARSER_PARSE_TREE_VISITOR_H_
Definition indirection.h:31
Definition check-expression.h:19
Definition format-specification.h:76
Definition format-specification.h:56
Definition format-specification.h:116
Definition format-specification.h:135
Definition format-specification.h:38
Definition parse-tree.h:1901
Definition parse-tree.h:3264
Definition parse-tree.h:1892
Definition parse-tree.h:3350
Definition parse-tree.h:1847
Definition parse-tree.h:1714
Definition parse-tree.h:1690
Definition parse-tree.h:3252
Definition parse-tree.h:1269
Definition parse-tree.h:587
Definition parse-tree.h:1796
Definition parse-tree.h:2742
Definition parse-tree.h:809
Definition parse-tree.h:359
Definition parse-tree.h:1877
Definition parse-tree.h:3123
Definition parse-tree.h:354
Definition parse-tree.h:3068
Definition parse-tree.h:2764