A state machine that aids in parsing a string's "trailer", which can be either non-existent, an old-style formatting sequence (e.g. `% varX` or `% (varX, varY)`), or a method-call / attribute access (e.g. `.format(varX, varY)`). NOTE: A new StringParser object MUST be instantia
| 2349 | |
| 2350 | |
| 2351 | class StringParser: |
| 2352 | """ |
| 2353 | A state machine that aids in parsing a string's "trailer", which can be |
| 2354 | either non-existent, an old-style formatting sequence (e.g. `% varX` or `% |
| 2355 | (varX, varY)`), or a method-call / attribute access (e.g. `.format(varX, |
| 2356 | varY)`). |
| 2357 | |
| 2358 | NOTE: A new StringParser object MUST be instantiated for each string |
| 2359 | trailer we need to parse. |
| 2360 | |
| 2361 | Examples: |
| 2362 | We shall assume that `line` equals the `Line` object that corresponds |
| 2363 | to the following line of python code: |
| 2364 | ``` |
| 2365 | x = "Some {}.".format("String") + some_other_string |
| 2366 | ``` |
| 2367 | |
| 2368 | Furthermore, we will assume that `string_idx` is some index such that: |
| 2369 | ``` |
| 2370 | assert line.leaves[string_idx].value == "Some {}." |
| 2371 | ``` |
| 2372 | |
| 2373 | The following code snippet then holds: |
| 2374 | ``` |
| 2375 | string_parser = StringParser() |
| 2376 | idx = string_parser.parse(line.leaves, string_idx) |
| 2377 | assert line.leaves[idx].type == token.PLUS |
| 2378 | ``` |
| 2379 | """ |
| 2380 | |
| 2381 | DEFAULT_TOKEN: Final = 20210605 |
| 2382 | |
| 2383 | # String Parser States |
| 2384 | START: Final = 1 |
| 2385 | DOT: Final = 2 |
| 2386 | NAME: Final = 3 |
| 2387 | PERCENT: Final = 4 |
| 2388 | SINGLE_FMT_ARG: Final = 5 |
| 2389 | LPAR: Final = 6 |
| 2390 | RPAR: Final = 7 |
| 2391 | DONE: Final = 8 |
| 2392 | |
| 2393 | # Lookup Table for Next State |
| 2394 | _goto: Final[dict[tuple[ParserState, NodeType], ParserState]] = { |
| 2395 | # A string trailer may start with '.' OR '%'. |
| 2396 | (START, token.DOT): DOT, |
| 2397 | (START, token.PERCENT): PERCENT, |
| 2398 | (START, DEFAULT_TOKEN): DONE, |
| 2399 | # A '.' MUST be followed by an attribute or method name. |
| 2400 | (DOT, token.NAME): NAME, |
| 2401 | # A method name MUST be followed by an '(', whereas an attribute name |
| 2402 | # is the last symbol in the string trailer. |
| 2403 | (NAME, token.LPAR): LPAR, |
| 2404 | (NAME, DEFAULT_TOKEN): DONE, |
| 2405 | # A '%' symbol can be followed by an '(' or a single argument (e.g. a |
| 2406 | # string or variable name). |
| 2407 | (PERCENT, token.LPAR): LPAR, |
| 2408 | (PERCENT, DEFAULT_TOKEN): SINGLE_FMT_ARG, |
no outgoing calls
no test coverage detected