symbolsTemplates.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "symbols.H"
27 
28 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
29 
30 template<class Type>
32 (
33  const label lastPrior,
34  tokeniser& tis,
35  const Type& identity,
36  const HashTable<Type>& table
37 )
38 {
39  Type result(identity);
40 
41  // Get initial token
42  token nextToken(tis.nextToken());
43 
44  // Store type of last token read. Used to detect two consecutive
45  // symbols and assume multiplication.
46  bool haveReadSymbol = false;
47 
48  while (true)
49  {
50  if (nextToken.isWord())
51  {
52  // Named unit conversion. Multiply.
53  if (!table.found(nextToken.wordToken()))
54  {
55  FatalIOErrorInFunction(tis.stream())
56  << nextToken.wordToken() << " not found in symbols table."
57  << " Valid symbols are:" << nl << table.toc()
58  << exit(FatalIOError);
59  }
60  result.reset(result*table[nextToken.wordToken()]);
61  haveReadSymbol = true;
62  }
63  else if (nextToken.isNumber())
64  {
65  // A number. This makes no sense.
66  FatalIOErrorInFunction(tis.stream())
67  << "Illegal token " << nextToken << exit(FatalIOError);
68  }
69  else if (nextToken.isPunctuation())
70  {
71  const label nextPrior = tokeniser::priority(nextToken);
72 
73  if (nextToken.pToken() == token::BEGIN_SQR)
74  {
75  // Start another set of symbols? This makes no sense.
76  FatalIOErrorInFunction(tis.stream())
77  << "Illegal token " << nextToken << exit(FatalIOError);
78  return result;
79  }
80  else if (nextToken.pToken() == token::END_SQR)
81  {
82  // End the units
83  tis.putBack(nextToken);
84  return result;
85  }
86  else if (nextToken.pToken() == token::COLON)
87  {
88  // End the units
89  tis.putBack(nextToken);
90  return result;
91  }
92  else if (nextToken.pToken() == token::BEGIN_LIST)
93  {
94  // Parenthesis. Evaluate the sub-units and multiply.
95  result.reset
96  (
97  result
98  *parseNoBegin(nextPrior, tis, identity, table)
99  );
100 
101  // Check that the parentheses end
102  token t = tis.nextToken();
103  if (!t.isPunctuation() || t.pToken() != token::END_LIST)
104  {
105  FatalIOErrorInFunction(tis.stream())
106  << "Illegal token " << t << exit(FatalIOError);
107  }
108 
109  haveReadSymbol = true;
110  }
111  else if (nextToken.pToken() == token::END_LIST)
112  {
113  // End the sub-units
114  tis.putBack(nextToken);
115  return result;
116  }
117  else if (nextToken.pToken() == token::MULTIPLY)
118  {
119  // Multiply operator
120  if (nextPrior > lastPrior)
121  {
122  // This has priority. Evaluate the next units and multiply.
123  result.reset
124  (
125  result
126  *parseNoBegin(nextPrior, tis, identity, table)
127  );
128  }
129  else
130  {
131  // Restore the token
132  tis.putBack(nextToken);
133  return result;
134  }
135 
136  haveReadSymbol = false;
137  }
138  else if (nextToken.pToken() == token::DIVIDE)
139  {
140  // Divide operator. As above.
141  if (nextPrior > lastPrior)
142  {
143  result.reset
144  (
145  result
146  /parseNoBegin(nextPrior, tis, identity, table)
147  );
148  }
149  else
150  {
151  tis.putBack(nextToken);
152  return result;
153  }
154 
155  haveReadSymbol = false;
156  }
157  else if (nextToken.pToken() == '^')
158  {
159  // Power operator
160  if (nextPrior > lastPrior)
161  {
162  token t = tis.nextToken();
163  if (!t.isScalar())
164  {
165  FatalIOErrorInFunction(tis.stream())
166  << "Invalid power " << t << exit(FatalIOError);
167  }
168  result.reset(pow(result, t.scalarToken()));
169  }
170  else
171  {
172  tis.putBack(nextToken);
173  return result;
174  }
175 
176  haveReadSymbol = true;
177  }
178  else
179  {
180  FatalIOErrorInFunction(tis.stream())
181  << "Illegal token " << nextToken << exit(FatalIOError);
182  }
183  }
184  else
185  {
186  FatalIOErrorInFunction(tis.stream())
187  << "Illegal token " << nextToken << exit(FatalIOError);
188  }
189 
190  if (!tis.hasToken())
191  {
192  break;
193  }
194 
195  nextToken = tis.nextToken();
196 
197  if (nextToken.error())
198  {
199  break;
200  }
201 
202  if (haveReadSymbol && (nextToken.isWord() || nextToken.isNumber()))
203  {
204  // Consecutive symbols are multiplied
205  tis.putBack(nextToken);
206  nextToken = token(token::MULTIPLY);
207  }
208  }
209 
210  return result;
211 }
212 
213 
214 template<class Type>
216 (
217  Istream& is,
218  const Type& identity,
219  const HashTable<Type>& table
220 )
221 {
222  symbols::tokeniser tis(is);
223 
224  Type result = parseNoBegin(0, tis, identity, table);
225 
226  is.putBack(tis.nextToken());
227 
228  return result;
229 }
230 
231 
232 // ************************************************************************* //
static label priority(const token &t)
...
Definition: symbols.C:196
@ DIVIDE
Definition: token.H:127
@ BEGIN_SQR
Definition: token.H:112
@ BEGIN_LIST
Definition: token.H:110
@ END_LIST
Definition: token.H:111
@ END_SQR
Definition: token.H:113
@ MULTIPLY
Definition: token.H:126
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
const HashTable< dimensionSet > table
Table of dimensions.
Definition: dimensions.C:74
Type parseNoBeginOrEnd(Istream &is, const Type &identity, const HashTable< Type > &table)
Parse tokens into a dimension set or unit conversion, assuming that the '['.
Type parseNoBegin(const label lastPrior, tokeniser &tis, const Type &identity, const HashTable< Type > &table)
Parse tokens into a dimension set or unit conversion, assuming that the '['.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
IOerror FatalIOError
tmp< DimensionedField< typename powProduct< Type, r >::type, GeoMesh, Field > > pow(const DimensionedField< Type, GeoMesh, PrimitiveField > &df, typename powProduct< Type, r >::type)
static const char nl
Definition: Ostream.H:297