OPAL (Object Oriented Parallel Accelerator Library) 2022.1
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"
26#include <cctype>
27
28// Class StringStream
29// ------------------------------------------------------------------------
30
31StringStream::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])) {
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 {
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;
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] == '.') {
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') {
146 digit = false;
147
148 if(line_m[currentChar_m] == '+') {
150 } else if(line_m[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;
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];
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) {
209 if(line_m[currentChar_m] != quote) break;
210 } else if(line_m[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