| 442 | } |
| 443 | |
| 444 | void Prog::ComputeByteMap() { |
| 445 | // Fill in bytemap with byte classes for the program. |
| 446 | // Ranges of bytes that are treated indistinguishably |
| 447 | // will be mapped to a single byte class. |
| 448 | ByteMapBuilder builder; |
| 449 | |
| 450 | // Don't repeat the work for ^ and $. |
| 451 | bool marked_line_boundaries = false; |
| 452 | // Don't repeat the work for \b and \B. |
| 453 | bool marked_word_boundaries = false; |
| 454 | |
| 455 | for (int id = 0; id < size(); id++) { |
| 456 | Inst* ip = inst(id); |
| 457 | if (ip->opcode() == kInstByteRange) { |
| 458 | int lo = ip->lo(); |
| 459 | int hi = ip->hi(); |
| 460 | builder.Mark(lo, hi); |
| 461 | if (ip->foldcase() && lo <= 'z' && hi >= 'a') { |
| 462 | int foldlo = lo; |
| 463 | int foldhi = hi; |
| 464 | if (foldlo < 'a') |
| 465 | foldlo = 'a'; |
| 466 | if (foldhi > 'z') |
| 467 | foldhi = 'z'; |
| 468 | if (foldlo <= foldhi) { |
| 469 | foldlo += 'A' - 'a'; |
| 470 | foldhi += 'A' - 'a'; |
| 471 | builder.Mark(foldlo, foldhi); |
| 472 | } |
| 473 | } |
| 474 | // If this Inst is not the last Inst in its list AND the next Inst is |
| 475 | // also a ByteRange AND the Insts have the same out, defer the merge. |
| 476 | if (!ip->last() && |
| 477 | inst(id+1)->opcode() == kInstByteRange && |
| 478 | ip->out() == inst(id+1)->out()) |
| 479 | continue; |
| 480 | builder.Merge(); |
| 481 | } else if (ip->opcode() == kInstEmptyWidth) { |
| 482 | if (ip->empty() & (kEmptyBeginLine|kEmptyEndLine) && |
| 483 | !marked_line_boundaries) { |
| 484 | builder.Mark('\n', '\n'); |
| 485 | builder.Merge(); |
| 486 | marked_line_boundaries = true; |
| 487 | } |
| 488 | if (ip->empty() & (kEmptyWordBoundary|kEmptyNonWordBoundary) && |
| 489 | !marked_word_boundaries) { |
| 490 | // We require two batches here: the first for ranges that are word |
| 491 | // characters, the second for ranges that are not word characters. |
| 492 | for (bool isword : {true, false}) { |
| 493 | int j; |
| 494 | for (int i = 0; i < 256; i = j) { |
| 495 | for (j = i + 1; j < 256 && |
| 496 | Prog::IsWordChar(static_cast<uint8_t>(i)) == |
| 497 | Prog::IsWordChar(static_cast<uint8_t>(j)); |
| 498 | j++) |
| 499 | ; |
| 500 | if (Prog::IsWordChar(static_cast<uint8_t>(i)) == isword) |
| 501 | builder.Mark(i, j - 1); |