www.cemf.ir
Istream.cpp
Go to the documentation of this file.
1 /*------------------------------- phasicFlow ---------------------------------
2  O C enter of
3  O O E ngineering and
4  O O M ultiscale modeling of
5  OOOOOOO F luid flow
6 ------------------------------------------------------------------------------
7  Copyright (C): www.cemf.ir
8  email: hamid.r.norouzi AT gmail.com
9 ------------------------------------------------------------------------------
10 Licence:
11  This file is part of phasicFlow code. It is a free software for simulating
12  granular and multiphase flows. You can redistribute it and/or modify it under
13  the terms of GNU General Public License v3 or any other later versions.
14 
15  phasicFlow is distributed to help others in their research in the field of
16  granular and multiphase flows, but WITHOUT ANY WARRANTY; without even the
17  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 
19 -----------------------------------------------------------------------------*/
20 // based on OpenFOAM stream, with some modifications/simplifications
21 // to be tailored to our needs
22 
23 
24 #include "Istream.hpp"
25 #include "token.hpp"
26 #include "error.hpp"
27 
28 
29 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
30 
31 // Truncate error message for readability
32 static constexpr const unsigned errLen = 80;
33 
34 
35 namespace
36 {
37 
38 // Convert a single character to a word with length 1
39 inline static pFlow::word charToWord(char c)
40 {
41  return pFlow::word(std::string(1, c), false);
42 }
43 
44 // Permit slash-scoping of entries
45 static inline bool validVariableChar(char c)
46 {
47  return (pFlow::validWord(c) || c == '/');
48 }
49 
50 } // End anonymous namespace
51 
52 
54 {
55  char c = 0;
56 
57  while (true)
58  {
59  // Get next non-whitespace character
60  while (get(c) && isspace(c))
61  {}
62 
63  // Return if stream is bad - ie, previous get() failed
64  if (bad() || isspace(c))
65  {
66  return 0;
67  }
68 
69  // Is this the start of a C/C++ comment?
70  if (c == '/')
71  {
72  if (!get(c))
73  {
74  // Cannot get another character - return this one
75  return '/';
76  }
77 
78  if (c == '/')
79  {
80  // C++ style single-line comment - skip through past end-of-line
81  while (get(c) && c != '\n')
82  {}
83  }
84  else if (c == '*')
85  {
86  // Within a C-style comment
87  while (true)
88  {
89  // Search for end of C-style comment - '*/'
90  if (get(c) && c == '*')
91  {
92  if (get(c))
93  {
94  if (c == '/')
95  {
96  // matched '*/'
97  break;
98  }
99  else if (c == '*')
100  {
101  // check again
102  putback(c);
103  }
104  }
105  }
106 
107  if (!good())
108  {
109  return 0;
110  }
111  }
112  }
113  else
114  {
115  // The '/' did not start a C/C++ comment - return it
116  putback(c);
117  return '/';
118  }
119  }
120  else
121  {
122  // A valid character - return it
123  return c;
124  }
125  }
126 
127  return 0;
128 }
129 
130 
132 {
133  word val;
134  if (read(val).bad())
135  {
136  t.setBad();
137  }
138  else
139  {
140  t = std::move(val); // Move contents to token
141  }
142 }
143 
144 
146 {
147  constexpr const unsigned maxLen = 1024;
148  static char buf[maxLen];
149 
150  unsigned nChar = 0;
151  unsigned depth = 0; // Track depth of (..) or {..} nesting
152  char c;
153 
154  // First character must be '$'
155  if (!get(c) || c != token::DOLLAR)
156  {
157  ioErrorInFile( name(), lineNumber())
158  << "Invalid first character found : " << c << nl;
159  fatalExit;
160  }
161  buf[nChar++] = c;
162 
163  // Next character should also exist.
164  // This should never fail, since it was checked before calling.
165  if (!get(c))
166  {
167  str.assign(buf, nChar);
169  << "Truncated variable name : " << str << nl;
170 
171  return *this;
172  }
173  buf[nChar++] = c;
174 
175  str.clear();
176  if (c == token::BEGIN_BLOCK)
177  {
178  // Processing ${...} style.
179  ++depth;
180 
181  // Could check that the next char is good and not one of '{}'
182  // since this would indicate "${}", "${{..." or truncated "${"
183 
184  while (get(c))
185  {
186  buf[nChar++] = c;
187  if (nChar == maxLen)
188  {
189  str.append(buf, nChar);
190  nChar = 0;
191  }
192  if (c == token::BEGIN_BLOCK)
193  {
194  ++depth;
195  }
196  else if (c == token::END_BLOCK)
197  {
198  --depth;
199  if (!depth)
200  {
201  // Found closing '}' character
202  str.append(buf, nChar);
203  return *this;
204  }
205  }
206  }
207 
208  // Should never reach here on normal input
209 
210  str.append(buf, nChar); // Finalize pending buffer input
211 
212  nChar = str.length();
213  if (str.length() > errLen)
214  {
215  str.erase(errLen);
216  }
217 
218  ioErrorInFile(name(), lineNumber())
219  << "stream terminated while reading variable '"
220  << str.c_str() << "...' [" << static_cast<int32>(nChar) << "]\n";
221  fatalExit;
222 
223  return *this;
224  }
225  else if (validVariableChar(c))
226  {
227  // Processing $var style
228 
229  while
230  (
231  (nChar < maxLen) && get(c)
232  && (validVariableChar(c))
233  )
234  {
235  if (c == token::BEGIN_LIST)
236  {
237  ++depth;
238  }
239  else if (c == token::END_LIST)
240  {
241  if (!depth)
242  {
243  break; // Closed ')' without an opening '(' ? ... stop
244  }
245  --depth;
246  }
247 
248  buf[nChar++] = c;
249  }
250  }
251  else
252  {
253  // Invalid character. Terminate string (for message) without
254  // including the invalid character in the count.
255 
256  buf[nChar--] = '\0';
257 
259  << "Bad variable name: " << buf << nl << endl;
260  }
261 
262  if (nChar >= maxLen)
263  {
264  buf[errLen] = '\0';
265 
266  ioErrorInFile(name(), lineNumber())
267  << "variable '" << buf << "...'\n"
268  << " is too long (max. " << static_cast<int32>(maxLen) << " characters)";
269  fatalExit;
270 
271  return *this;
272  }
273 
274  buf[nChar] = '\0'; // Terminate string
275 
276  if (bad())
277  {
278  // Could probably skip this check
279  buf[errLen] = '\0';
280 
281  ioErrorInFile(name(), lineNumber())
282  << "Problem while reading variable '" << buf << "...' after "
283  << static_cast<int32>(nChar) << " characters\n";
284  fatalExit;
285 
286  ioErrorInFile(name(), lineNumber());
287 
288  return *this;
289  }
290 
291  if (depth)
292  {
294  << "Missing " << static_cast<int32>(depth)
295  << " closing ')' while parsing" << nl << nl
296  << buf << nl << endl;
297  }
298 
299  // Finalize
300  str.assign(buf, nChar);
301  putback(c);
302 
303  return *this;
304 }
305 
306 
308 (
309  std::istream& is,
310  const word& streamName,
311  writeFormat wf
312 )
313 :
314  iIstream(wf),
315  name_(streamName),
316  is_(is)
317 {
318  if (is_.good())
319  {
320  setOpened();
321  setGood();
322  }
323  else
324  {
325  setState(is_.rdstate());
326  }
327 }
328 
330 {
331  is_.get(c);
332  setState(is_.rdstate());
333 
334  if (good() && c == '\n')
335  {
336  ++lineNumber_;
337  }
338 
339  return *this;
340 }
341 
342 
344 {
345  return is_.peek();
346 }
347 
348 
349 pFlow::Istream& pFlow::Istream::getLine(std::string& str, char delim)
350 {
351  std::getline(is_, str, delim);
352  setState(is_.rdstate());
353 
354  if (delim == '\n')
355  {
356  ++lineNumber_;
357  }
358 
359  return *this;
360 }
361 
362 
363 std::streamsize pFlow::Istream::getLine(std::nullptr_t, char delim)
364 {
365  is_.ignore(std::numeric_limits<std::streamsize>::max(), delim);
366  setState(is_.rdstate());
367 
368  std::streamsize count = is_.gcount();
369 
370  if (count && delim == '\n')
371  {
372  ++lineNumber_;
373  }
374 
375  return count;
376 }
377 
378 
380 {
381  if (c == '\n')
382  {
383  --lineNumber_;
384  }
385 
386  if (!is_.putback(c))
387  {
388  setBad();
389  }
390 
391  setState(is_.rdstate());
392 
393  return *this;
394 }
395 
397 {
398  constexpr const unsigned maxLen = 128; // Max length for units/scalars
399  static char buf[maxLen];
400 
401  // Return the put back token if it exists
402  if (Istream::getBack(t))
403  {
404  return *this;
405  }
406 
407  // Assume that the streams supplied are in working order.
408  // Lines are counted by '\n'
409 
410  // Get next 'valid character': i.e. proceed through any whitespace
411  // and/or comments until a semantically valid character is found
412 
413  char c = nextValid();
414 
415  // Set the line number of this token to the current stream line number
416  t.lineNumber() = lineNumber();
417 
418  // Return on error
419  if (!c)
420  {
421  t.setBad();
422  return *this;
423  }
424 
425  // Analyse input starting with this character.
426  switch (c)
427  {
428  // Check for punctuation first - same as token::isseparator()
429 
430  case token::END_STATEMENT :
431  case token::BEGIN_LIST :
432  case token::END_LIST :
433  case token::BEGIN_SQR :
434  case token::END_SQR :
435  case token::BEGIN_BLOCK :
436  case token::END_BLOCK :
437  case token::COLON :
438  case token::COMMA :
439  case token::DIVIDE :
440  {
442  return *this;
443  }
444 
445  // String: enclosed by double quotes.
446  case token::BEGIN_STRING :
447  {
448  putback(c);
449 
450  word val;
451  if (readString(val).bad())
452  {
453  t.setBad();
454  }
455  else
456  {
457  t = std::move(val); // Move contents to token
458  }
459 
460  return *this;
461  }
462  // Dictionary variable (as rvalue)
463  case token::DOLLAR :
464  {
465  char nextC;
466  if (read(nextC).bad())
467  {
468  // Return lone '$' as word
469  t = charToWord(c);
470  }
471  else
472  {
473  // Put back both so that '$...' is included in the variable
474  putback(nextC);
475  putback(c);
476 
477  word val;
478  if (readVariable(val).bad())
479  {
480  t.setBad();
481  }
482  else
483  {
484  t = std::move(val); // Move contents to token
485  t.setType(token::tokenType::VARIABLE);
486  }
487  }
488 
489  return *this;
490  }
491 
492  // Number: integer or floating point
493  //
494  // ideally match the equivalent of this regular expression
495  //
496  // /[-+]?([0-9]+\.?[0-9]*|\.[0-9]+)([Ee][-+]?[0-9]+)?/
497  //
498  case '-' :
499  case '.' :
500  case '0' : case '1' : case '2' : case '3' : case '4' :
501  case '5' : case '6' : case '7' : case '8' : case '9' :
502  {
503  int64 int64Val = (c != '.'); // used as bool here
504 
505  unsigned nChar = 0;
506  buf[nChar++] = c;
507 
508  // get everything that could resemble a number and let
509  // readScalar determine the validity
510  while
511  (
512  is_.get(c)
513  && (
514  isdigit(c)
515  || c == '+'
516  || c == '-'
517  || c == '.'
518  || c == 'E'
519  || c == 'e'
520  )
521  )
522  {
523  if (int64Val)
524  {
525  int64Val = isdigit(c);
526  }
527 
528  buf[nChar++] = c;
529  if (nChar == maxLen)
530  {
531  // Runaway argument - avoid buffer overflow
532  buf[maxLen-1] = '\0';
533 
534  ioErrorInFile( name(), lineNumber())
535  << "number '" << buf << "...'\n"
536  << " is too long (max. " <<
537  static_cast<int32>(maxLen) << " characters)";
538  fatalExit;
539 
540  t.setBad();
541  return *this;
542  }
543  }
544  buf[nChar] = '\0'; // Terminate string
545 
546  setState(is_.rdstate());
547  if (is_.bad())
548  {
549  t.setBad();
550  }
551  else
552  {
553  is_.putback(c);
554 
555  if (nChar == 1 && buf[0] == '-')
556  {
557  // A single '-' is punctuation
559  }
560  else if (int64Val && readInt64(buf, int64Val))
561  {
562  t = int64Val;
563  }
564  else
565  {
566  real realVal;
567 
568  if (readReal(buf, realVal))
569  {
570  // A scalar or too big to fit as a unit
571  t = realVal;
572  }
573  else
574  {
575  t.setBad();
576  }
577  }
578  }
579 
580  return *this;
581  }
582 
583  // Should be a word (which can also be a single character)
584  default:
585  {
586  putback(c);
587  readWordToken(t);
588 
589  return *this;
590  }
591  }
592 }
593 
594 
596 {
597  c = nextValid();
598  return *this;
599 }
600 
601 
603 {
604 
605  constexpr const unsigned maxLen = 1024;
606  static char buf[maxLen];
607 
608  unsigned nChar = 0;
609  unsigned depth = 0; // Track depth of (..) nesting
610  char c;
611 
612  while
613  (
614  (nChar < maxLen)
615  && get(c)
616  && validWord(c)
617  )
618  {
619  if (c == token::BEGIN_LIST)
620  {
621  ++depth;
622  }
623  else if (c == token::END_LIST)
624  {
625  if (!depth)
626  {
627  break; // Closed ')' without an opening '(' ? ... stop
628  }
629  --depth;
630  }
631 
632  buf[nChar++] = c;
633  }
634 
635  if (nChar >= maxLen)
636  {
637  buf[errLen] = '\0';
638  ioErrorInFile(name(), lineNumber())
639  << "word '" << buf << "...'\n"
640  << " is too long (max. " <<
641  static_cast<int32>(maxLen) << " characters)";
642  fatalExit;
643 
644  return *this;
645  }
646 
647  buf[nChar] = '\0'; // Terminate string
648 
649  if (bad())
650  {
651  // Could probably skip this check
652  buf[errLen] = '\0';
653 
654  ioErrorInFile(name(), lineNumber())
655  << "Problem while reading word '" << buf << "...' after "
656  << static_cast<int32>(nChar) << " characters\n";
657  fatalExit;
658 
659  return *this;
660  }
661 
662  if (nChar == 0)
663  {
664  ioErrorInFile(name(), lineNumber())
665  << "Invalid first character found : " << c;
666  fatalExit;
667  }
668  else if (depth)
669  {
671  << "Missing " << static_cast<int32>(depth)
672  << " closing ')' while parsing" << nl << nl
673  << buf << nl << endl;
674  }
675 
676  // Finalize: content already validated, assign without additional checks.
677  str.assign(buf, nChar);
678  putback(c);
679 
680  return *this;
681 }
682 
683 
685 {
686  constexpr const unsigned maxLen = 1024;
687  static char buf[maxLen];
688 
689  char c;
690 
691  if (!get(c))
692  {
693  ioErrorInFile(name(), lineNumber())
694  << "cannot read start of string";
695  fatalExit;
696 
697  return *this;
698  }
699 
700  // Note, we could also handle single-quoted strings here (if desired)
701  if (c != token::BEGIN_STRING)
702  {
703  ioErrorInFile(name(), lineNumber())
704  << "Incorrect start of string character found : " << c;
705  fatalExit;
706 
707  return *this;
708  }
709 
710  unsigned nChar = 0;
711  bool escaped = false;
712 
713  while
714  (
715  (nChar < maxLen)
716  && get(c)
717  )
718  {
719  if (c == token::END_STRING)
720  {
721  if (escaped)
722  {
723  escaped = false;
724  --nChar; // Overwrite backslash
725  }
726  else
727  {
728  // Done reading
729  str.assign(buf, nChar);
730  return *this;
731  }
732  }
733  else if (c == token::NL)
734  {
735  if (escaped)
736  {
737  escaped = false;
738  --nChar; // Overwrite backslash
739  }
740  else
741  {
742  buf[errLen] = buf[nChar] = '\0';
743 
744  ioErrorInFile(name(), lineNumber())
745  << "found '\\n' while reading string \""
746  << buf << "...\"";
747  fatalExit;
748 
749  return *this;
750  }
751  }
752  else if (c == '\\')
753  {
754  escaped = !escaped; // toggle state (retains backslashes)
755  }
756  else
757  {
758  escaped = false;
759  }
760 
761  buf[nChar++] = c;
762  }
763 
764  if (nChar >= maxLen)
765  {
766  buf[errLen] = '\0';
767 
768  ioErrorInFile(name(), lineNumber())
769  << "string \"" << buf << "...\"\n"
770  << " is too long (max. " << static_cast<int32>(maxLen) << " characters)";
771  fatalExit;
772 
773  return *this;
774  }
775 
776  // Don't worry about a dangling backslash if string terminated prematurely
777  buf[errLen] = buf[nChar] = '\0';
778 
779  ioErrorInFile(name(), lineNumber())
780  << "Problem while reading string \"" << buf << "...\"";
781  fatalExit;
782 
783  return *this;
784 }
785 
787 {
788  is_ >> val;
789  setState(is_.rdstate());
790  return *this;
791 }
792 
794 {
795  is_ >> val;
796  setState(is_.rdstate());
797  return *this;
798 }
799 
801 {
802  is_ >> val;
803  setState(is_.rdstate());
804  return *this;
805 }
806 
808 {
809  is_ >> val;
810  setState(is_.rdstate());
811  return *this;
812 }
813 
815 {
816  is_ >> val;
817  setState(is_.rdstate());
818  return *this;
819 }
820 
822 {
823  is_ >> val;
824  setState(is_.rdstate());
825  return *this;
826 }
827 
829 {
830  is_ >> val;
831  setState(is_.rdstate());
832  return *this;
833 }
834 
836 {
837  is_ >> val;
838  setState(is_.rdstate());
839  return *this;
840 }
841 
842 
844 {
845  is_ >> val;
846  setState(is_.rdstate());
847  return *this;
848 }
849 
851 (
852  char* buffer,
853  std::streamsize count
854 )
855 {
856  if ( !isBinary() )
857  {
858  fatalErrorInFunction<<"stream format is not binray. Stream name is "<<
859  name()<<'\n';
860  fatalExit;
861  }
862 
863  readBegin("binaryBlock");
864  is_.read(buffer, count);
865  readEnd("binaryBlock");
866 
867  setState(is_.rdstate());
868  return *this;
869 }
870 
872 {
873  lineNumber_ = 1; // Reset line number
874 
875  stdStream().clear(); // Clear the iostate error state flags
876  setGood(); // Sync local copy of iostate
877 
878  // pubseekpos() rather than seekg() so that it works with gzstream
879  stdStream().rdbuf()->pubseekpos(0, std::ios_base::in);
880 }
881 
882 
883 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
884 
885 std::ios_base::fmtflags pFlow::Istream::flags() const
886 {
887  return is_.flags();
888 }
889 
890 
891 std::ios_base::fmtflags pFlow::Istream::flags(const ios_base::fmtflags f)
892 {
893  return is_.flags(f);
894 }
895 
896 
897 // ************************************************************************* //
pFlow::token::setType
bool setType(const tokenType tokType)
Definition: tokenI.hpp:290
pFlow::real
float real
Definition: builtinTypes.hpp:46
fatalExit
#define fatalExit
Definition: error.hpp:57
pFlow::token
Definition: token.hpp:42
pFlow::Istream::nextValid
char nextValid()
Definition: Istream.cpp:53
pFlow::Istream::readWordToken
void readWordToken(token &t)
Definition: Istream.cpp:131
errLen
static constexpr const unsigned errLen
Definition: Istream.cpp:32
warningInFunction
#define warningInFunction
Definition: error.hpp:55
pFlow::token::punctuationToken
punctuationToken
Definition: token.hpp:81
pFlow::Istream::Istream
Istream(std::istream &is, const word &streamName, writeFormat wf=ASCII)
Definition: Istream.cpp:308
pFlow::token::END_BLOCK
@ END_BLOCK
End block [isseparator].
Definition: token.hpp:94
pFlow::uint32
unsigned int uint32
Definition: builtinTypes.hpp:59
pFlow::readReal
bool readReal(const word &w, real &val)
Definition: bTypesFunctions.cpp:335
token.hpp
pFlow::word
std::string word
Definition: builtinTypes.hpp:63
pFlow::token::NL
@ NL
Newline [isspace].
Definition: token.hpp:86
pFlow::int64
long long int int64
Definition: builtinTypes.hpp:55
pFlow::validWord
bool validWord(char c)
Definition: bTypesFunctions.cpp:180
Istream.hpp
pFlow::endl
iOstream & endl(iOstream &os)
Add newline and flush stream.
Definition: iOstream.hpp:320
pFlow::token::BEGIN_BLOCK
@ BEGIN_BLOCK
Begin block [isseparator].
Definition: token.hpp:93
pFlow::readInt64
bool readInt64(const word &w, int64 &val)
Definition: bTypesFunctions.cpp:262
pFlow::Istream::rewind
virtual void rewind()
Definition: Istream.cpp:871
pFlow::Istream::readString
virtual iIstream & readString(word &str) override
Definition: Istream.cpp:684
pFlow::Istream
Definition: Istream.hpp:38
pFlow::int16
short int int16
Definition: builtinTypes.hpp:51
pFlow::uint16
unsigned short int uint16
Definition: builtinTypes.hpp:57
pFlow::iIstream
Definition: iIstream.hpp:33
pFlow::IOstream::bad
bool bad() const
Return true if stream is corrupted.
Definition: IOstream.hpp:202
pFlow::iIstream::getBack
bool getBack(token &tok)
Definition: iIstream.cpp:27
pFlow::Istream::readVariable
Istream & readVariable(word &str)
Definition: Istream.cpp:145
fatalErrorInFunction
#define fatalErrorInFunction
Definition: error.hpp:42
pFlow::int32
int int32
Definition: builtinTypes.hpp:53
pFlow::algorithms::KOKKOS::max
INLINE_FUNCTION_H Type max(const Type *first, int32 numElems)
Definition: kokkosAlgorithms.hpp:104
pFlow::Istream::read
virtual iIstream & read(token &t) override
Definition: Istream.cpp:396
pFlow::token::BEGIN_STRING
@ BEGIN_STRING
Begin string with double quote.
Definition: token.hpp:104
pFlow::token::END_LIST
@ END_LIST
End list [isseparator].
Definition: token.hpp:90
pFlow::token::DOLLAR
@ DOLLAR
Dollar - start variable.
Definition: token.hpp:97
pFlow::count
auto count(const Vector< T, Allocator > &vec, const T &val)
Definition: VectorAlgorithm.hpp:26
pFlow::Istream::get
Istream & get(char &c)
Definition: Istream.cpp:329
pFlow::token::COLON
@ COLON
Colon [isseparator].
Definition: token.hpp:95
pFlow::token::END_STATEMENT
@ END_STATEMENT
End entry [isseparator].
Definition: token.hpp:88
pFlow::IOstream::good
bool good() const
Return true if next operation might succeed.
Definition: IOstream.hpp:184
pFlow::token::SUBTRACT
@ SUBTRACT
Subtract or start of negative number.
Definition: token.hpp:101
pFlow::token::BEGIN_LIST
@ BEGIN_LIST
Begin list [isseparator].
Definition: token.hpp:89
pFlow::token::BEGIN_SQR
@ BEGIN_SQR
Begin dimensions [isseparator].
Definition: token.hpp:91
pFlow::token::DIVIDE
@ DIVIDE
Divide [isseparator].
Definition: token.hpp:102
ioErrorInFile
#define ioErrorInFile(fileName, lineNumber)
Definition: error.hpp:49
pFlow::label
std::size_t label
Definition: builtinTypes.hpp:61
pFlow::token::COMMA
@ COMMA
Comma [isseparator].
Definition: token.hpp:96
pFlow::int8
signed char int8
Definition: builtinTypes.hpp:49
pFlow::Istream::peek
int peek()
Definition: Istream.cpp:343
pFlow::IOstream::writeFormat
writeFormat
Definition: IOstream.hpp:57
pFlow::Istream::flags
virtual ios_base::fmtflags flags() const
Return flags of stream.
Definition: Istream.cpp:885
pFlow::token::END_STRING
@ END_STRING
End string with double quote.
Definition: token.hpp:105
pFlow::Istream::putback
Istream & putback(const char c)
Definition: Istream.cpp:379
pFlow::Istream::getLine
Istream & getLine(word &str, char delim='\n')
Definition: Istream.cpp:349
pFlow::nl
constexpr char nl
Definition: iOstream.hpp:417
pFlow::token::END_SQR
@ END_SQR
End dimensions [isseparator].
Definition: token.hpp:92
pFlow::token::setBad
void setBad()
Definition: tokenI.hpp:658
pFlow::token::lineNumber
int32 lineNumber() const
Definition: tokenI.hpp:360
error.hpp