1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING.  If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if ! defined (octave_pt_select_h)
27 #define octave_pt_select_h 1
28 
29 #include "octave-config.h"
30 
31 #include "base-list.h"
32 #include "comment-list.h"
33 #include "pt-cmd.h"
34 #include "pt-walk.h"
35 
36 namespace octave
37 {
38   class tree_expression;
39   class tree_statement_list;
40 
41   // If.
42 
43   class tree_if_clause : public tree
44   {
45   public:
46 
47     tree_if_clause (int l = -1, int c = -1)
tree(l,c)48       : tree (l, c), m_expr (nullptr), m_list (nullptr), m_lead_comm (nullptr) { }
49 
50     tree_if_clause (tree_statement_list *sl, comment_list *lc = nullptr,
51                     int l = -1, int c = -1)
tree(l,c)52       : tree (l, c), m_expr (nullptr), m_list (sl), m_lead_comm (lc) { }
53 
54     tree_if_clause (tree_expression *e, tree_statement_list *sl,
55                     comment_list *lc = nullptr,
56                     int l = -1, int c = -1)
tree(l,c)57       : tree (l, c), m_expr (e), m_list (sl), m_lead_comm (lc) { }
58 
59     // No copying!
60 
61     tree_if_clause (const tree_if_clause&) = delete;
62 
63     tree_if_clause& operator = (const tree_if_clause&) = delete;
64 
65     ~tree_if_clause (void);
66 
is_else_clause(void)67     bool is_else_clause (void) { return ! m_expr; }
68 
condition(void)69     tree_expression * condition (void) { return m_expr; }
70 
commands(void)71     tree_statement_list * commands (void) { return m_list; }
72 
leading_comment(void)73     comment_list * leading_comment (void) { return m_lead_comm; }
74 
accept(tree_walker & tw)75     void accept (tree_walker& tw)
76     {
77       tw.visit_if_clause (*this);
78     }
79 
80   private:
81 
82     // The condition to test.
83     tree_expression *m_expr;
84 
85     // The list of statements to evaluate if expr is true.
86     tree_statement_list *m_list;
87 
88     // Comment preceding ELSE or ELSEIF token.
89     comment_list *m_lead_comm;
90   };
91 
92   class tree_if_command_list : public base_list<tree_if_clause *>
93   {
94   public:
95 
tree_if_command_list(void)96     tree_if_command_list (void) { }
97 
tree_if_command_list(tree_if_clause * t)98     tree_if_command_list (tree_if_clause *t) { append (t); }
99 
100     // No copying!
101 
102     tree_if_command_list (const tree_if_command_list&) = delete;
103 
104     tree_if_command_list& operator = (const tree_if_command_list&) = delete;
105 
~tree_if_command_list(void)106     ~tree_if_command_list (void)
107     {
108       while (! empty ())
109         {
110           auto p = begin ();
111           delete *p;
112           erase (p);
113         }
114     }
115 
accept(tree_walker & tw)116     void accept (tree_walker& tw)
117     {
118       tw.visit_if_command_list (*this);
119     }
120   };
121 
122   class tree_if_command : public tree_command
123   {
124   public:
125 
126     tree_if_command (int l = -1, int c = -1)
tree_command(l,c)127       : tree_command (l, c), m_list (nullptr),
128         m_lead_comm (nullptr), m_trail_comm (nullptr)
129     { }
130 
131     tree_if_command (tree_if_command_list *lst, comment_list *lc,
132                      comment_list *tc, int l = -1, int c = -1)
tree_command(l,c)133       : tree_command (l, c), m_list (lst), m_lead_comm (lc), m_trail_comm (tc) { }
134 
135     // No copying!
136 
137     tree_if_command (const tree_if_command&) = delete;
138 
139     tree_if_command& operator = (const tree_if_command&) = delete;
140 
141     ~tree_if_command (void);
142 
cmd_list(void)143     tree_if_command_list * cmd_list (void) { return m_list; }
144 
leading_comment(void)145     comment_list * leading_comment (void) { return m_lead_comm; }
146 
trailing_comment(void)147     comment_list * trailing_comment (void) { return m_trail_comm; }
148 
accept(tree_walker & tw)149     void accept (tree_walker& tw)
150     {
151       tw.visit_if_command (*this);
152     }
153 
154   private:
155 
156     // List of if commands (if, elseif, elseif, ... else, endif)
157     tree_if_command_list *m_list;
158 
159     // Comment preceding IF token.
160     comment_list *m_lead_comm;
161 
162     // Comment preceding ENDIF token.
163     comment_list *m_trail_comm;
164   };
165 
166   // Switch.
167 
168   class tree_switch_case : public tree
169   {
170   public:
171 
172     tree_switch_case (int l = -1, int c = -1)
tree(l,c)173       : tree (l, c), m_label (nullptr), m_list (nullptr), m_lead_comm (nullptr) { }
174 
175     tree_switch_case (tree_statement_list *sl, comment_list *lc = nullptr,
176                       int l = -1, int c = -1)
tree(l,c)177       : tree (l, c), m_label (nullptr), m_list (sl), m_lead_comm (lc) { }
178 
179     tree_switch_case (tree_expression *e, tree_statement_list *sl,
180                       comment_list *lc = nullptr,
181                       int l = -1, int c = -1)
tree(l,c)182       : tree (l, c), m_label (e), m_list (sl), m_lead_comm (lc) { }
183 
184     // No copying!
185 
186     tree_switch_case (const tree_switch_case&) = delete;
187 
188     tree_switch_case& operator = (const tree_switch_case&) = delete;
189 
190     ~tree_switch_case (void);
191 
is_default_case(void)192     bool is_default_case (void) { return ! m_label; }
193 
case_label(void)194     tree_expression * case_label (void) { return m_label; }
195 
commands(void)196     tree_statement_list * commands (void) { return m_list; }
197 
leading_comment(void)198     comment_list * leading_comment (void) { return m_lead_comm; }
199 
accept(tree_walker & tw)200     void accept (tree_walker& tw)
201     {
202       tw.visit_switch_case (*this);
203     }
204 
205   private:
206 
207     // The case label.
208     tree_expression *m_label;
209 
210     // The list of statements to evaluate if the label matches.
211     tree_statement_list *m_list;
212 
213     // Comment preceding CASE or OTHERWISE token.
214     comment_list *m_lead_comm;
215   };
216 
217   class tree_switch_case_list : public base_list<tree_switch_case *>
218   {
219   public:
220 
tree_switch_case_list(void)221     tree_switch_case_list (void) { }
222 
tree_switch_case_list(tree_switch_case * t)223     tree_switch_case_list (tree_switch_case *t) { append (t); }
224 
225     // No copying!
226 
227     tree_switch_case_list (const tree_switch_case_list&) = delete;
228 
229     tree_switch_case_list& operator = (const tree_switch_case_list&) = delete;
230 
~tree_switch_case_list(void)231     ~tree_switch_case_list (void)
232     {
233       while (! empty ())
234         {
235           auto p = begin ();
236           delete *p;
237           erase (p);
238         }
239     }
240 
accept(tree_walker & tw)241     void accept (tree_walker& tw)
242     {
243       tw.visit_switch_case_list (*this);
244     }
245   };
246 
247   class tree_switch_command : public tree_command
248   {
249   public:
250 
251     tree_switch_command (int l = -1, int c = -1)
tree_command(l,c)252       : tree_command (l, c), m_expr (nullptr), m_list (nullptr),
253         m_lead_comm (nullptr), m_trail_comm (nullptr) { }
254 
255     tree_switch_command (tree_expression *e, tree_switch_case_list *lst,
256                          comment_list *lc, comment_list *tc,
257                          int l = -1, int c = -1)
tree_command(l,c)258       : tree_command (l, c), m_expr (e), m_list (lst), m_lead_comm (lc),
259         m_trail_comm (tc) { }
260 
261     // No copying!
262 
263     tree_switch_command (const tree_switch_command&) = delete;
264 
265     tree_switch_command& operator = (const tree_switch_command&) = delete;
266 
267     ~tree_switch_command (void);
268 
switch_value(void)269     tree_expression * switch_value (void) { return m_expr; }
270 
case_list(void)271     tree_switch_case_list * case_list (void) { return m_list; }
272 
leading_comment(void)273     comment_list * leading_comment (void) { return m_lead_comm; }
274 
trailing_comment(void)275     comment_list * trailing_comment (void) { return m_trail_comm; }
276 
accept(tree_walker & tw)277     void accept (tree_walker& tw)
278     {
279       tw.visit_switch_command (*this);
280     }
281 
282   private:
283 
284     // Value on which to switch.
285     tree_expression *m_expr;
286 
287     // List of cases (case 1, case 2, ..., default)
288     tree_switch_case_list *m_list;
289 
290     // Comment preceding SWITCH token.
291     comment_list *m_lead_comm;
292 
293     // Comment preceding ENDSWITCH token.
294     comment_list *m_trail_comm;
295   };
296 }
297 
298 #endif
299