@@ -31,6 +31,7 @@ using namespace langutil;
31
31
using namespace solidity ;
32
32
using namespace dev ::solidity::test;
33
33
using namespace std ;
34
+ using namespace soltest ;
34
35
35
36
namespace
36
37
{
@@ -47,14 +48,14 @@ namespace
47
48
vector<dev::solidity::test::FunctionCall> TestFileParser::parseFunctionCalls ()
48
49
{
49
50
vector<FunctionCall> calls;
50
- if (!accept (SoltToken ::EOS))
51
+ if (!accept (Token ::EOS))
51
52
{
52
- assert (m_scanner.currentToken () == SoltToken ::Unknown);
53
+ assert (m_scanner.currentToken () == Token ::Unknown);
53
54
m_scanner.scanNextToken ();
54
55
55
- while (!accept (SoltToken ::EOS))
56
+ while (!accept (Token ::EOS))
56
57
{
57
- if (!accept (SoltToken ::Whitespace))
58
+ if (!accept (Token ::Whitespace))
58
59
{
59
60
FunctionCall call;
60
61
@@ -64,63 +65,47 @@ vector<dev::solidity::test::FunctionCall> TestFileParser::parseFunctionCalls()
64
65
// / token lookahead that checks parseParameter
65
66
// / if the next token is an identifier.
66
67
if (calls.empty ())
67
- expect (SoltToken ::Newline);
68
+ expect (Token ::Newline);
68
69
else
69
- accept (SoltToken ::Newline, true );
70
+ accept (Token ::Newline, true );
70
71
71
72
call.signature = parseFunctionSignature ();
72
- if (accept (SoltToken ::Comma, true ))
73
+ if (accept (Token ::Comma, true ))
73
74
call.value = parseFunctionCallValue ();
74
- if (accept (SoltToken ::Colon, true ))
75
+ if (accept (Token ::Colon, true ))
75
76
call.arguments = parseFunctionCallArguments ();
76
77
77
- if (accept (SoltToken ::Newline, true ))
78
+ if (accept (Token ::Newline, true ))
78
79
call.displayMode = FunctionCall::DisplayMode::MultiLine;
79
80
80
81
call.arguments .comment = parseComment ();
81
82
82
- if (accept (SoltToken ::Newline, true ))
83
+ if (accept (Token ::Newline, true ))
83
84
call.displayMode = FunctionCall::DisplayMode::MultiLine;
84
85
85
- expect (SoltToken ::Arrow);
86
+ expect (Token ::Arrow);
86
87
call.expectations = parseFunctionCallExpectations ();
87
88
call.expectations .comment = parseComment ();
88
89
89
90
calls.emplace_back (std::move (call));
90
91
}
91
- else
92
- m_scanner.scanNextToken ();
93
92
}
94
93
}
95
94
return calls;
96
95
}
97
96
98
- string TestFileParser::formatToken (SoltToken _token)
97
+ bool TestFileParser::accept (soltest::Token _token, bool const _expect )
99
98
{
100
- switch (_token)
101
- {
102
- #define T (name, string, precedence ) case SoltToken::name: return string;
103
- SOLT_TOKEN_LIST (T, T)
104
- #undef T
105
- default : // Token::NUM_TOKENS:
106
- return " " ;
107
- }
108
- }
109
-
110
- bool TestFileParser::accept (SoltToken _token, bool const _expect)
111
- {
112
- if (m_scanner.currentToken () == _token)
113
- {
114
- if (_expect)
115
- expect (_token);
116
- return true ;
117
- }
118
- return false ;
99
+ if (m_scanner.currentToken () != _token)
100
+ return false ;
101
+ if (_expect)
102
+ return expect (_token);
103
+ return true ;
119
104
}
120
105
121
- bool TestFileParser::expect (SoltToken _token, bool const _advance)
106
+ bool TestFileParser::expect (soltest::Token _token, bool const _advance)
122
107
{
123
- if (m_scanner.currentToken () != _token)
108
+ if (m_scanner.currentToken () != _token || m_scanner. currentToken () == Token::Invalid )
124
109
throw Error (
125
110
Error::Type::ParserError,
126
111
" Unexpected " + formatToken (m_scanner.currentToken ()) + " : \" " +
@@ -135,32 +120,35 @@ bool TestFileParser::expect(SoltToken _token, bool const _advance)
135
120
string TestFileParser::parseFunctionSignature ()
136
121
{
137
122
string signature = m_scanner.currentLiteral ();
138
- expect (SoltToken ::Identifier);
123
+ expect (Token ::Identifier);
139
124
140
- signature += formatToken (SoltToken ::LParen);
141
- expect (SoltToken ::LParen);
125
+ signature += formatToken (Token ::LParen);
126
+ expect (Token ::LParen);
142
127
143
- while (!accept (SoltToken::RParen))
128
+ string parameters;
129
+ if (!accept (Token::RParen, false ))
130
+ parameters = parseIdentifierOrTuple ();
131
+
132
+ while (accept (Token::Comma))
144
133
{
145
- signature += m_scanner.currentLiteral ();
146
- expect (SoltToken::Identifier);
147
- while (accept (SoltToken::Comma))
148
- {
149
- signature += m_scanner.currentLiteral ();
150
- expect (SoltToken::Comma);
151
- signature += m_scanner.currentLiteral ();
152
- expect (SoltToken::Identifier);
153
- }
134
+ parameters += formatToken (Token::Comma);
135
+ expect (Token::Comma);
136
+ parameters += parseIdentifierOrTuple ();
154
137
}
155
- signature += formatToken (SoltToken::RParen);
156
- expect (SoltToken::RParen);
138
+ if (accept (Token::Arrow, true ))
139
+ throw Error (Error::Type::ParserError, " Invalid signature detected: " + signature);
140
+
141
+ signature += parameters;
142
+
143
+ expect (Token::RParen);
144
+ signature += formatToken (Token::RParen);
157
145
return signature;
158
146
}
159
147
160
148
u256 TestFileParser::parseFunctionCallValue ()
161
149
{
162
150
u256 value = convertNumber (parseNumber ());
163
- expect (SoltToken ::Ether);
151
+ expect (Token ::Ether);
164
152
return value;
165
153
}
166
154
@@ -173,7 +161,7 @@ FunctionCallArgs TestFileParser::parseFunctionCallArguments()
173
161
throw Error (Error::Type::ParserError, " No argument provided." );
174
162
arguments.parameters .emplace_back (param);
175
163
176
- while (accept (SoltToken ::Comma, true ))
164
+ while (accept (Token ::Comma, true ))
177
165
arguments.parameters .emplace_back (parseParameter ());
178
166
return arguments;
179
167
}
@@ -190,7 +178,7 @@ FunctionCallExpectations TestFileParser::parseFunctionCallExpectations()
190
178
}
191
179
expectations.result .emplace_back (param);
192
180
193
- while (accept (SoltToken ::Comma, true ))
181
+ while (accept (Token ::Comma, true ))
194
182
expectations.result .emplace_back (parseParameter ());
195
183
196
184
// / We have always one virtual parameter in the parameter list.
@@ -203,7 +191,7 @@ FunctionCallExpectations TestFileParser::parseFunctionCallExpectations()
203
191
Parameter TestFileParser::parseParameter ()
204
192
{
205
193
Parameter parameter;
206
- if (accept (SoltToken ::Newline, true ))
194
+ if (accept (Token ::Newline, true ))
207
195
parameter.format .newline = true ;
208
196
auto literal = parseABITypeLiteral ();
209
197
parameter.rawBytes = literal.first ;
@@ -218,20 +206,20 @@ pair<bytes, ABIType> TestFileParser::parseABITypeLiteral()
218
206
u256 number{0 };
219
207
ABIType abiType{ABIType::None, 0 };
220
208
221
- if (accept (SoltToken ::Sub))
209
+ if (accept (Token ::Sub))
222
210
{
223
211
abiType = ABIType{ABIType::SignedDec, 32 };
224
- expect (SoltToken ::Sub);
212
+ expect (Token ::Sub);
225
213
number = convertNumber (parseNumber ()) * -1 ;
226
214
}
227
215
else
228
216
{
229
- if (accept (SoltToken ::Number))
217
+ if (accept (Token ::Number))
230
218
{
231
219
abiType = ABIType{ABIType::UnsignedDec, 32 };
232
220
number = convertNumber (parseNumber ());
233
221
}
234
- else if (accept (SoltToken ::Failure, true ))
222
+ else if (accept (Token ::Failure, true ))
235
223
{
236
224
abiType = ABIType{ABIType::Failure, 0 };
237
225
return make_pair (bytes{}, abiType);
@@ -245,18 +233,43 @@ pair<bytes, ABIType> TestFileParser::parseABITypeLiteral()
245
233
}
246
234
}
247
235
236
+ string TestFileParser::parseIdentifierOrTuple ()
237
+ {
238
+ string identOrTuple;
239
+
240
+ if (accept (Token::Identifier))
241
+ {
242
+ identOrTuple = m_scanner.currentLiteral ();
243
+ expect (Token::Identifier);
244
+ return identOrTuple;
245
+ }
246
+ expect (Token::LParen);
247
+ identOrTuple += formatToken (Token::LParen);
248
+ identOrTuple += parseIdentifierOrTuple ();
249
+
250
+ while (accept (Token::Comma))
251
+ {
252
+ identOrTuple += formatToken (Token::Comma);
253
+ expect (Token::Comma);
254
+ identOrTuple += parseIdentifierOrTuple ();
255
+ }
256
+ expect (Token::RParen);
257
+ identOrTuple += formatToken (Token::RParen);
258
+ return identOrTuple;
259
+ }
260
+
248
261
string TestFileParser::parseComment ()
249
262
{
250
263
string comment = m_scanner.currentLiteral ();
251
- if (accept (SoltToken ::Comment, true ))
264
+ if (accept (Token ::Comment, true ))
252
265
return comment;
253
266
return string{};
254
267
}
255
268
256
269
string TestFileParser::parseNumber ()
257
270
{
258
271
string literal = m_scanner.currentLiteral ();
259
- expect (SoltToken ::Number);
272
+ expect (Token ::Number);
260
273
return literal;
261
274
}
262
275
@@ -281,69 +294,72 @@ void TestFileParser::Scanner::readStream(istream& _stream)
281
294
282
295
void TestFileParser::Scanner::scanNextToken ()
283
296
{
284
- auto detectToken = [](std::string const & _literal = " " ) -> TokenDesc {
285
- if (_literal == " ether" ) return TokenDesc{SoltToken::Ether, _literal};
286
- if (_literal == " FAILURE" ) return TokenDesc{SoltToken::Failure, _literal};
287
- return TokenDesc{SoltToken::Identifier, _literal};
297
+ // Make code coverage happy.
298
+ assert (formatToken (Token::NUM_TOKENS) == " " );
299
+
300
+ auto detectKeyword = [](std::string const & _literal = " " ) -> TokenDesc {
301
+ if (_literal == " ether" ) return TokenDesc{Token::Ether, _literal};
302
+ if (_literal == " FAILURE" ) return TokenDesc{Token::Failure, _literal};
303
+ return TokenDesc{Token::Identifier, _literal};
288
304
};
289
305
290
- auto selectToken = [this ](SoltToken _token, std::string const & _literal = " " ) -> TokenDesc {
306
+ auto selectToken = [this ](Token _token, std::string const & _literal = " " ) -> TokenDesc {
291
307
advance ();
292
308
return make_pair (_token, !_literal.empty () ? _literal : formatToken (_token));
293
309
};
294
310
295
- TokenDesc token = make_pair (SoltToken ::Unknown, " " );
311
+ TokenDesc token = make_pair (Token ::Unknown, " " );
296
312
do
297
313
{
298
314
switch (current ())
299
315
{
300
316
case ' /' :
301
317
advance ();
302
318
if (current () == ' /' )
303
- token = selectToken (SoltToken::Newline);
319
+ token = selectToken (Token::Newline);
320
+ else
321
+ token = selectToken (Token::Invalid);
304
322
break ;
305
323
case ' -' :
306
324
if (peek () == ' >' )
307
325
{
308
326
advance ();
309
- token = selectToken (SoltToken ::Arrow);
327
+ token = selectToken (Token ::Arrow);
310
328
}
311
329
else
312
- token = selectToken (SoltToken ::Sub);
330
+ token = selectToken (Token ::Sub);
313
331
break ;
314
332
case ' :' :
315
- token = selectToken (SoltToken ::Colon);
333
+ token = selectToken (Token ::Colon);
316
334
break ;
317
335
case ' #' :
318
- token = selectToken (SoltToken ::Comment, scanComment ());
336
+ token = selectToken (Token ::Comment, scanComment ());
319
337
break ;
320
338
case ' ,' :
321
- token = selectToken (SoltToken ::Comma);
339
+ token = selectToken (Token ::Comma);
322
340
break ;
323
341
case ' (' :
324
- token = selectToken (SoltToken ::LParen);
342
+ token = selectToken (Token ::LParen);
325
343
break ;
326
344
case ' )' :
327
- token = selectToken (SoltToken ::RParen);
345
+ token = selectToken (Token ::RParen);
328
346
break ;
329
347
default :
330
348
if (isIdentifierStart (current ()))
331
349
{
332
- TokenDesc detectedToken = detectToken (scanIdentifierOrKeyword ());
350
+ TokenDesc detectedToken = detectKeyword (scanIdentifierOrKeyword ());
333
351
token = selectToken (detectedToken.first , detectedToken.second );
334
352
}
335
353
else if (isdigit (current ()))
336
- token = selectToken (SoltToken ::Number, scanNumber ());
354
+ token = selectToken (Token ::Number, scanNumber ());
337
355
else if (isspace (current ()))
338
- token = selectToken (SoltToken ::Whitespace);
356
+ token = selectToken (Token ::Whitespace);
339
357
else if (isEndOfLine ())
340
- token = selectToken (SoltToken::EOS);
341
- else
342
- token = selectToken (SoltToken::Invalid);
358
+ token = selectToken (Token::EOS);
343
359
break ;
344
360
}
345
361
}
346
- while (token.first == SoltToken ::Whitespace);
362
+ while (token.first == Token ::Whitespace);
347
363
m_currentToken = token;
348
364
}
349
365
0 commit comments