* Parse a match argument. */
| 289 | * Parse a match argument. |
| 290 | */ |
| 291 | static const MatchArg parseMatchArg(Parser &parser, bool val = false) |
| 292 | { |
| 293 | bool neg = false; |
| 294 | int t = parser.getToken(); |
| 295 | |
| 296 | // Step (1): attempt to parse a value: |
| 297 | switch (t) |
| 298 | { |
| 299 | case TOKEN_STRING: |
| 300 | return MatchArg(new MatchVal(strDup(parser.s))); |
| 301 | case TOKEN_REGEX: |
| 302 | try |
| 303 | { |
| 304 | return MatchArg(new MatchVal(new MatchRegex(parser.s))); |
| 305 | } |
| 306 | catch (const std::regex_error &e) |
| 307 | { |
| 308 | error("failed to parse regular expression \"%s\"", parser.s); |
| 309 | } |
| 310 | case '&': |
| 311 | { |
| 312 | if (parser.peekToken() == TOKEN_MEM) |
| 313 | break; |
| 314 | std::string name; |
| 315 | switch (parser.getToken()) |
| 316 | { |
| 317 | case '.': |
| 318 | name += '.'; |
| 319 | parser.expectToken(TOKEN_NAME); |
| 320 | // Fallthrough: |
| 321 | case TOKEN_NAME: |
| 322 | name += parser.s; |
| 323 | break; |
| 324 | case TOKEN_STRING: |
| 325 | name += parser.s; |
| 326 | break; |
| 327 | default: |
| 328 | parser.unexpectedToken(); |
| 329 | } |
| 330 | intptr_t val = parseSymbol(parser, name.c_str()); |
| 331 | return MatchArg(val == INTPTR_MIN? new MatchVal(): |
| 332 | new MatchVal(val)); |
| 333 | } |
| 334 | case TOKEN_NIL: |
| 335 | return MatchArg(new MatchVal(nullptr)); |
| 336 | case '-': |
| 337 | if (parser.peekToken() != TOKEN_INTEGER) |
| 338 | return MatchArg(new MatchVal((Access)0x0)); |
| 339 | neg = true; |
| 340 | // Fallthrough |
| 341 | case '+': |
| 342 | parser.expectToken(TOKEN_INTEGER); |
| 343 | // Fallthrough |
| 344 | case TOKEN_INTEGER: |
| 345 | return MatchArg(new MatchVal((neg? -parser.i: parser.i))); |
| 346 | case TOKEN_REGISTER: |
| 347 | return MatchArg(new MatchVal((Register)parser.i)); |
| 348 | case TOKEN_MEM: case TOKEN_REG: case TOKEN_IMM: |
no test coverage detected