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