|
9 | 9 |
|
10 | 10 | from specfile.exceptions import OptionsException |
11 | 11 | from specfile.formatter import formatted |
| 12 | +from specfile.value_parser import Node, StringLiteral, ValueParser |
12 | 13 |
|
13 | 14 |
|
14 | 15 | class TokenType(Enum): |
@@ -474,63 +475,80 @@ def tokenize(option_string: str) -> List[Token]: |
474 | 475 | Raises: |
475 | 476 | OptionsException if the option string is untokenizable. |
476 | 477 | """ |
477 | | - result = [] |
478 | | - token = "" |
479 | | - quote = None |
480 | | - inp = list(option_string) |
481 | | - while inp: |
482 | | - c = inp.pop(0) |
483 | | - if c == quote: |
484 | | - if token: |
485 | | - result.append( |
486 | | - Token( |
487 | | - TokenType.QUOTED |
488 | | - if quote == "'" |
489 | | - else TokenType.DOUBLE_QUOTED, |
490 | | - token, |
491 | | - ) |
492 | | - ) |
493 | | - token = "" |
| 478 | + result: List[Token] = [] |
| 479 | + |
| 480 | + def append_default(s): |
| 481 | + if result and result[-1].type == TokenType.DEFAULT: |
| 482 | + result[-1].value += s |
| 483 | + else: |
| 484 | + result.append(Token(TokenType.DEFAULT, s)) |
| 485 | + |
| 486 | + token_nodes: List[Node] = [] |
| 487 | + for node in ValueParser.parse(option_string): |
| 488 | + if isinstance(node, StringLiteral): |
| 489 | + if token_nodes: |
| 490 | + append_default("".join(str(n) for n in token_nodes)) |
| 491 | + token_nodes = [] |
| 492 | + token = "" |
494 | 493 | quote = None |
495 | | - continue |
496 | | - if quote: |
497 | | - if c == "\\": |
498 | | - if not inp: |
499 | | - raise OptionsException("No escaped character") |
500 | | - c = inp.pop(0) |
501 | | - if c != quote: |
502 | | - token += "\\" |
503 | | - token += c |
504 | | - continue |
505 | | - if c.isspace(): |
506 | | - if token: |
507 | | - result.append(Token(TokenType.DEFAULT, token)) |
508 | | - token = "" |
509 | | - whitespace = c |
| 494 | + inp = list(str(node)) |
510 | 495 | while inp: |
511 | 496 | c = inp.pop(0) |
512 | | - if not c.isspace(): |
513 | | - break |
514 | | - whitespace += c |
515 | | - else: |
516 | | - result.append(Token(TokenType.WHITESPACE, whitespace)) |
517 | | - break |
518 | | - inp.insert(0, c) |
519 | | - result.append(Token(TokenType.WHITESPACE, whitespace)) |
520 | | - continue |
521 | | - if c in ('"', "'"): |
| 497 | + if c == quote: |
| 498 | + if token: |
| 499 | + result.append( |
| 500 | + Token( |
| 501 | + TokenType.QUOTED |
| 502 | + if quote == "'" |
| 503 | + else TokenType.DOUBLE_QUOTED, |
| 504 | + token, |
| 505 | + ) |
| 506 | + ) |
| 507 | + token = "" |
| 508 | + quote = None |
| 509 | + continue |
| 510 | + if quote: |
| 511 | + if c == "\\": |
| 512 | + if not inp: |
| 513 | + raise OptionsException("No escaped character") |
| 514 | + c = inp.pop(0) |
| 515 | + if c != quote: |
| 516 | + token += "\\" |
| 517 | + token += c |
| 518 | + continue |
| 519 | + if c.isspace(): |
| 520 | + if token: |
| 521 | + append_default(token) |
| 522 | + token = "" |
| 523 | + whitespace = c |
| 524 | + while inp: |
| 525 | + c = inp.pop(0) |
| 526 | + if not c.isspace(): |
| 527 | + break |
| 528 | + whitespace += c |
| 529 | + else: |
| 530 | + result.append(Token(TokenType.WHITESPACE, whitespace)) |
| 531 | + break |
| 532 | + inp.insert(0, c) |
| 533 | + result.append(Token(TokenType.WHITESPACE, whitespace)) |
| 534 | + continue |
| 535 | + if c in ('"', "'"): |
| 536 | + if token: |
| 537 | + append_default(token) |
| 538 | + token = "" |
| 539 | + quote = c |
| 540 | + continue |
| 541 | + if c == "\\": |
| 542 | + if not inp: |
| 543 | + raise OptionsException("No escaped character") |
| 544 | + c = inp.pop(0) |
| 545 | + token += c |
| 546 | + if quote: |
| 547 | + raise OptionsException("No closing quotation") |
522 | 548 | if token: |
523 | | - result.append(Token(TokenType.DEFAULT, token)) |
524 | | - token = "" |
525 | | - quote = c |
526 | | - continue |
527 | | - if c == "\\": |
528 | | - if not inp: |
529 | | - raise OptionsException("No escaped character") |
530 | | - c = inp.pop(0) |
531 | | - token += c |
532 | | - if quote: |
533 | | - raise OptionsException("No closing quotation") |
534 | | - if token: |
535 | | - result.append(Token(TokenType.DEFAULT, token)) |
| 549 | + append_default(token) |
| 550 | + else: |
| 551 | + token_nodes.append(node) |
| 552 | + if token_nodes: |
| 553 | + append_default("".join(str(n) for n in token_nodes)) |
536 | 554 | return result |
0 commit comments