OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
StringStream.cpp
Go to the documentation of this file.
1 // ------------------------------------------------------------------------
2 // $RCSfile: StringStream.cpp,v $
3 // ------------------------------------------------------------------------
4 // $Revision: 1.1.1.1 $
5 // ------------------------------------------------------------------------
6 // Copyright: see Copyright.readme
7 // ------------------------------------------------------------------------
8 //
9 // Class: StringStream
10 // Implements an input buffer for reading from a string.
11 // This string is intended for storing valid MAD-9 expressions,
12 // it must not contain comments.
13 //
14 // ------------------------------------------------------------------------
15 // Class category: Parser
16 // ------------------------------------------------------------------------
17 //
18 // $Date: 2000/03/27 09:32:37 $
19 // $Author: fci $
20 //
21 // ------------------------------------------------------------------------
22 
23 #include "Parser/StringStream.h"
24 #include "Parser/Token.h"
25 #include "Utilities/FormatError.h"
26 #include <cctype>
27 
28 // Class StringStream
29 // ------------------------------------------------------------------------
30 
31 StringStream::StringStream(const std::string &str):
32  TokenStream("expression"),
33  line_m(str + '\n'),
34  currentChar_m(0)
35 {}
36 
37 
39 {}
40 
41 
43  if(put_back_flag) {
44  put_back_flag = false;
45  return put_back;
46  }
47 
48  while(true) {
49  if(currentChar_m >= line_m.length() || line_m[currentChar_m] == '\n') {
50  return Token("string", 1, Token::IS_EOF, "EOF");
51  } else if(isspace(line_m[currentChar_m])) {
52  currentChar_m++;
53  } else {
54  break;
55  }
56  }
57 
58  // First character.
59  char ch = line_m[currentChar_m];
60 
61  if(ch == '"' || ch == '\'') {
62  // String token.
63  return readString();
64  } else if(isalpha(ch)) {
65  // Word token.
66  return readWord();
67  } else if(isdigit(ch) ||
68  (ch == '.' && isdigit(line_m[currentChar_m+1]))) {
69  // Numeric token.
70  return readNumber();
71  } else {
72  // Delimiter tokens.
73  if(ch == '<' && line_m[currentChar_m+1] == '=') {
74  currentChar_m += 2;
75  return Token("string", 1, Token::IS_DELIMITER, "<=");
76  } else if(ch == '>' && line_m[currentChar_m+1] == '=') {
77  currentChar_m += 2;
78  return Token("string", 1, Token::IS_DELIMITER, ">=");
79  } else if(ch == '=' && line_m[currentChar_m+1] == '=') {
80  currentChar_m += 2;
81  return Token("string", 1, Token::IS_DELIMITER, "==");
82  } else if(ch == '!' && line_m[currentChar_m+1] == '=') {
83  currentChar_m += 2;
84  return Token("string", 1, Token::IS_DELIMITER, "!=");
85  } else if(ch == '|' && line_m[currentChar_m+1] == '|') {
86  currentChar_m += 2;
87  return Token("string", 1, Token::IS_DELIMITER, "||");
88  } else if(ch == '&' && line_m[currentChar_m+1] == '&') {
89  currentChar_m += 2;
90  return Token("string", 1, Token::IS_DELIMITER, "&&");
91  } else if(ch == ':' && line_m[currentChar_m+1] == '=') {
92  currentChar_m += 2;
93  return Token("string", 1, Token::IS_DELIMITER, ":=");
94  } else if(ch == '-' && line_m[currentChar_m+1] == '>') {
95  currentChar_m += 2;
96  return Token("string", 1, Token::IS_DELIMITER, "->");
97  } else {
98  currentChar_m++;
99  return Token("string", 1, Token::IS_DELIMITER, ch);
100  }
101  }
102 
103  return Token(stream_name, curr_line, Token::IS_ERROR, "ERROR");
104 }
105 
106 
108  bool digit = false;
109  bool eflag = false;
110  double value = 0.0;
111  int expsig = 1;
112  int expval = 0;
113  int places = 0;
114  int lex_pos = currentChar_m;
115 
116  while(isdigit(line_m[currentChar_m])) {
117  // Digits preceding decimal point.
118  value = 10.0 * value + double(line_m[currentChar_m] - '0');
119  digit = true;
120  currentChar_m++;
121  }
122 
123  if(digit && line_m[currentChar_m] != '.' && toupper(line_m[currentChar_m]) != 'E') {
124  // Unsigned integer seen.
125  std::string lexeme(line_m.data() + lex_pos, currentChar_m - lex_pos);
126  return Token("string", 1, lexeme, int(value + 0.5));
127  }
128 
129  // Decimal point.
130  if(line_m[currentChar_m] == '.') {
131  currentChar_m++;
132 
133  // Digits following decimal point.
134  while(isdigit(line_m[currentChar_m])) {
135  value = 10.0 * value + double(line_m[currentChar_m++] - '0');
136  digit = true;
137  places++;
138  }
139  }
140 
141  if(! digit) eflag = true;
142 
143  // Exponent ?
144  if(toupper(line_m[currentChar_m]) == 'E') {
145  currentChar_m++;
146  digit = false;
147 
148  if(line_m[currentChar_m] == '+') {
149  currentChar_m++;
150  } else if(line_m[currentChar_m] == '-') {
151  currentChar_m++;
152  expsig = -1;
153  }
154 
155  while(isdigit(line_m[currentChar_m])) {
156  expval = 10 * expval + (line_m[currentChar_m++] - '0');
157  digit = true;
158  }
159 
160  if(! digit) eflag = true;
161 
162  // Skip over any non-punctuation characters.
163  char ch = line_m[currentChar_m];
164 
165  while(! isspace(ch) && ! ispunct(ch)) {
166  eflag = true;
167  currentChar_m++;
168  ch = line_m[currentChar_m];
169  }
170  }
171 
172  // Put pieces together.
173  std::string lexeme(line_m.data() + lex_pos, currentChar_m - lex_pos);
174 
175  if(eflag) {
176  return Token("string", 1, Token::IS_ERROR,
177  "Invalid numeric token \"" + lexeme + "\".");
178  } else {
179  int power = expsig * expval - places;
180 
181  if(power > 0) {
182  for(places = power; places > 0; places--)
183  value *= 10.0;
184  } else {
185  for(places = - power; places > 0; places--)
186  value /= 10.0;
187  }
188 
189  return Token("string", 1, lexeme, value);
190  }
191 }
192 
193 
195  std::string lexeme;
196 
197  if(line_m[currentChar_m] == '"' || line_m[currentChar_m] == '\'') {
198  char quote = line_m[currentChar_m];
199  currentChar_m++;
200 
201  while(true) {
202  if(currentChar_m >= line_m.length()) {
203  throw FormatError("StringStream::readString()",
204  "String not terminated.");
205  }
206 
207  if(line_m[currentChar_m] == quote) {
208  currentChar_m++;
209  if(line_m[currentChar_m] != quote) break;
210  } else if(line_m[currentChar_m] == '\\') {
211  currentChar_m++;
212  }
213 
214  lexeme += line_m[currentChar_m++];
215  }
216  }
217 
218  return Token("string", 1, Token::IS_STRING, lexeme);
219 }
220 
221 
223  std::string lexeme;
224  char ch = line_m[currentChar_m];
225 
226  if(isalpha(line_m[currentChar_m])) {
227  lexeme += toupper(ch);
228  char ch = line_m[++currentChar_m];
229 
230  while(isalnum(ch) || ch == '_' || ch == '.' || ch == '\'') {
231  lexeme += toupper(ch);
232  ch = line_m[++currentChar_m];
233  }
234  }
235 
236  return Token("string", 1, Token::IS_WORD, lexeme);
237 }
Token readString()
virtual ~StringStream()
Token readWord()
std::string::size_type currentChar_m
Definition: StringStream.h:62
const std::string line_m
Definition: StringStream.h:61
virtual Token readToken()
Read single token from file.
Token readNumber()
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
Format error exception.
Definition: FormatError.h:32