OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
AbsFileStream.cpp
Go to the documentation of this file.
1 // ------------------------------------------------------------------------
2 // $RCSfile: AbsFileStream.cpp,v $
3 // ------------------------------------------------------------------------
4 // $Revision: 1.1.1.1 $
5 // ------------------------------------------------------------------------
6 // Copyright: see Copyright.readme
7 // ------------------------------------------------------------------------
8 //
9 // Class: AbsFileStream
10 // Implements an abstract input buffer for reading from a file.
11 //
12 // ------------------------------------------------------------------------
13 // Class category: Parser
14 // ------------------------------------------------------------------------
15 //
16 // $Date: 2000/03/27 09:32:37 $
17 // $Author: fci $
18 //
19 // ------------------------------------------------------------------------
20 
21 #include "Parser/AbsFileStream.h"
22 #include "Parser/Token.h"
23 #include "Utilities/FormatError.h"
24 #include <cctype>
25 #include <iostream>
26 #include <algorithm>
27 
28 // Class AbsFileStream
29 // ------------------------------------------------------------------------
30 
31 AbsFileStream::AbsFileStream(const std::string &name):
33  line("\n"),
34  curr_char(0)
35 {}
36 
37 
39 {}
40 
41 
43  if(put_back_flag) {
44  put_back_flag = false;
45  return put_back;
46  }
47 
48  // Skip white space.
49  while(true) {
50  char ch = line[curr_char];
51 
52  if(ch == '\n') {
53  // End of line.
54  if(! fillLine()) {
55  // End of file.
56  return Token(stream_name, curr_line, Token::IS_EOF, "EOF");
57  }
58  } else if(isspace(ch)) {
59  // Skip white space.
60  curr_char++;
61  } else {
62  break;
63  }
64  }
65 
66  // First character.
67  char ch = line[curr_char];
68 
69  if(ch == '/') {
70  // Skip comments.
71  char ch1 = line[curr_char+1];
72  if(ch1 == '/') {
73  // C++ like comment.
74  if(fillLine()) {
75  return readToken();
76  } else {
77  return Token(stream_name, curr_line, Token::IS_EOF, "EOF");
78  }
79  } else if(ch1 == '*') {
80  // C like comment.
81  if(skipComments()) {
82  return readToken();
83  } else {
85  "Comment not closed.");
86  }
87  }
88  }
89 
90  if(ch == '"' || ch == '\'') {
91  // String token.
92  return readString();
93  } else if(isalpha(ch)) {
94  // Word token.
95  return readWord();
96  } else if(isdigit(ch) ||
97  (ch == '.' && isdigit(line[curr_char+1]))) {
98  // Numeric token.
99  return readNumber();
100  } else {
101  // Delimiter tokens.
102  if(ch == '<' && line[curr_char+1] == '=') {
103  curr_char += 2;
105  } else if(ch == '>' && line[curr_char+1] == '=') {
106  curr_char += 2;
108  } else if(ch == '=' && line[curr_char+1] == '=') {
109  curr_char += 2;
111  } else if(ch == '!' && line[curr_char+1] == '=') {
112  curr_char += 2;
114  } else if(ch == '|' && line[curr_char+1] == '|') {
115  curr_char += 2;
117  } else if(ch == '&' && line[curr_char+1] == '&') {
118  curr_char += 2;
120  } else if(ch == ':' && line[curr_char+1] == '=') {
121  curr_char += 2;
123  } else if(ch == '-' && line[curr_char+1] == '>') {
124  curr_char += 2;
126  } else if(ch == '/' && line[curr_char+1] == '*') {
127  curr_char += 2;
128  if(skipComments()) {
129  return readToken();
130  } else {
132  "Comment not closed.");
133  }
134  } else {
135  curr_char++;
137  }
138  }
139 
140  return Token(stream_name, curr_line, Token::IS_ERROR, "ERROR");
141 }
142 
143 
145  bool digit = false;
146  bool eflag = false;
147  double value = 0.0;
148  int expsig = 1;
149  int expval = 0;
150  int places = 0;
151  int lex_pos = curr_char;
152 
153  while(isdigit(line[curr_char])) {
154  // Digits preceding decimal point.
155  value = 10.0 * value + double(line[curr_char] - '0');
156  digit = true;
157  curr_char++;
158  }
159 
160  if(digit && line[curr_char] != '.' &&
161  toupper(line[curr_char]) != 'E') {
162  // Unsigned integer seen.
163  std::string lexeme(line.data() + lex_pos, curr_char - lex_pos);
164  return Token(stream_name, curr_line, lexeme, int(value + 0.5));
165  }
166 
167  // Decimal point.
168  if(line[curr_char] == '.') {
169  curr_char++;
170 
171  // Digits following decimal point.
172  while(isdigit(line[curr_char])) {
173  value = 10.0 * value + double(line[curr_char++] - '0');
174  digit = true;
175  places++;
176  }
177  }
178 
179  if(! digit) eflag = true;
180 
181  // Exponent ?
182  if(toupper(line[curr_char]) == 'E') {
183  curr_char++;
184  digit = false;
185 
186  if(line[curr_char] == '+') {
187  curr_char++;
188  } else if(line[curr_char] == '-') {
189  curr_char++;
190  expsig = -1;
191  }
192 
193  while(isdigit(line[curr_char])) {
194  expval = 10 * expval + (line[curr_char++] - '0');
195  digit = true;
196  }
197 
198  if(! digit) eflag = true;
199 
200  // Skip over any non-punctuation characters.
201  char ch = line[curr_char];
202 
203  while(! isspace(ch) && ! ispunct(ch)) {
204  eflag = true;
205  curr_char++;
206  ch = line[curr_char];
207  }
208  }
209 
210  // Put pieces together.
211  std::string lexeme(line.data() + lex_pos, curr_char - lex_pos);
212 
213  if(eflag) {
215  "Invalid numeric token \"" + lexeme + "\".");
216  } else {
217  int power = expsig * expval - places;
218 
219  if(power > 0) {
220  for(places = power; places > 0; places--)
221  value *= 10.0;
222  } else {
223  for(places = - power; places > 0; places--)
224  value /= 10.0;
225  }
226 
227  return Token(stream_name, curr_line, lexeme, value);
228  }
229 }
230 
231 
233  std::string lexeme;
234 
235  if(line[curr_char] == '"' || line[curr_char] == '\'') {
236  char quote = line[curr_char];
237  curr_char++;
238 
239  while(true) {
240  if(line[curr_char] == '\n') {
241  return Token(stream_name, curr_line, Token::IS_ERROR, "String \"" +
242  lexeme + "\" not terminated at end of line.");
243  }
244 
245  if(line[curr_char] == quote) {
246  curr_char++;
247  if(line[curr_char] != quote) break;
248  } else if(line[curr_char] == '\\') {
249  curr_char++;
250  }
251 
252  lexeme += line[curr_char++];
253  }
254  }
255 
256  return Token(stream_name, curr_line, Token::IS_STRING, lexeme);
257 }
258 
259 
261  std::string lexeme;
262  char ch = line[curr_char];
263 
264  if(isalpha(line[curr_char])) {
265  lexeme += toupper(ch);
266  char ch = line[++curr_char];
267 
268  while(isalnum(ch) || ch == '_' || ch == '.') {
269  lexeme += toupper(ch);
270  ch = line[++curr_char];
271  }
272  }
273 
274  return Token(stream_name, curr_line, Token::IS_WORD, lexeme);
275 }
276 
277 
279  curr_char += 2;
280 
281  while(true) {
282  while(line[curr_char] != '\n') {
283  if(line[curr_char] == '*' && line[curr_char+1] == '/') {
284  curr_char += 2;
285  return true;
286  } else if(line[curr_char] == '/' && line[curr_char+1] == '*') {
287  skipComments();
288  } else {
289  curr_char++;
290  }
291  }
292 
293  // End of line
294  if(! fillLine()) return false;
295  }
296 }
const std::string name
std::string line
Definition: AbsFileStream.h:63
virtual bool fillLine()=0
Read next input line.
virtual ~AbsFileStream()
virtual Token readToken()
Read single token from file.
Representation of a single input token.
Definition: Token.h:33
@ IS_STRING
Definition: Token.h:45
@ IS_ERROR
Definition: Token.h:41
@ IS_DELIMITER
Definition: Token.h:39
@ IS_WORD
Definition: Token.h:44
@ IS_EOF
Definition: Token.h:40
Abstract interface for a stream of input tokens.
Definition: TokenStream.h:33
bool put_back_flag
Definition: TokenStream.h:65
std::string stream_name
Definition: TokenStream.h:59
Token put_back
Definition: TokenStream.h:66