1 // Copyright 2020 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/regexp/experimental/experimental-bytecode.h"
6
7 #include <cctype>
8 #include <iomanip>
9
10 namespace v8 {
11 namespace internal {
12
13 namespace {
14
PrintAsciiOrHex(std::ostream& os, base::uc16 c)15 std::ostream& PrintAsciiOrHex(std::ostream& os, base::uc16 c) {
16 if (c < 128 && std::isprint(c)) {
17 os << static_cast<char>(c);
18 } else {
19 os << "0x" << std::hex << static_cast<int>(c);
20 }
21 return os;
22 }
23
24 } // namespace
25
operator <<(std::ostream& os, const RegExpInstruction& inst)26 std::ostream& operator<<(std::ostream& os, const RegExpInstruction& inst) {
27 switch (inst.opcode) {
28 case RegExpInstruction::CONSUME_RANGE: {
29 os << "CONSUME_RANGE [";
30 PrintAsciiOrHex(os, inst.payload.consume_range.min);
31 os << ", ";
32 PrintAsciiOrHex(os, inst.payload.consume_range.max);
33 os << "]";
34 break;
35 }
36 case RegExpInstruction::ASSERTION:
37 os << "ASSERTION ";
38 switch (inst.payload.assertion_type) {
39 case RegExpAssertion::Type::START_OF_INPUT:
40 os << "START_OF_INPUT";
41 break;
42 case RegExpAssertion::Type::END_OF_INPUT:
43 os << "END_OF_INPUT";
44 break;
45 case RegExpAssertion::Type::START_OF_LINE:
46 os << "START_OF_LINE";
47 break;
48 case RegExpAssertion::Type::END_OF_LINE:
49 os << "END_OF_LINE";
50 break;
51 case RegExpAssertion::Type::BOUNDARY:
52 os << "BOUNDARY";
53 break;
54 case RegExpAssertion::Type::NON_BOUNDARY:
55 os << "NON_BOUNDARY";
56 break;
57 }
58 break;
59 case RegExpInstruction::FORK:
60 os << "FORK " << inst.payload.pc;
61 break;
62 case RegExpInstruction::JMP:
63 os << "JMP " << inst.payload.pc;
64 break;
65 case RegExpInstruction::ACCEPT:
66 os << "ACCEPT";
67 break;
68 case RegExpInstruction::SET_REGISTER_TO_CP:
69 os << "SET_REGISTER_TO_CP " << inst.payload.register_index;
70 break;
71 case RegExpInstruction::CLEAR_REGISTER:
72 os << "CLEAR_REGISTER " << inst.payload.register_index;
73 break;
74 }
75 return os;
76 }
77
78 namespace {
79
80 // The maximum number of digits required to display a non-negative number < n
81 // in base 10.
DigitsRequiredBelow(int n)82 int DigitsRequiredBelow(int n) {
83 DCHECK_GE(n, 0);
84
85 int result = 1;
86 for (int i = 10; i < n; i *= 10) {
87 result += 1;
88 }
89 return result;
90 }
91
92 } // namespace
93
operator <<(std::ostream& os, base::Vector<const RegExpInstruction> insts)94 std::ostream& operator<<(std::ostream& os,
95 base::Vector<const RegExpInstruction> insts) {
96 int inst_num = insts.length();
97 int line_digit_num = DigitsRequiredBelow(inst_num);
98
99 for (int i = 0; i != inst_num; ++i) {
100 const RegExpInstruction& inst = insts[i];
101 os << std::setfill('0') << std::setw(line_digit_num) << i << ": " << inst
102 << std::endl;
103 }
104 return os;
105 }
106
107 } // namespace internal
108 } // namespace v8
109