v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
regexp-dotprinter.cc
Go to the documentation of this file.
1// Copyright 2019 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
6
7#include "src/base/strings.h"
10
11namespace v8 {
12namespace internal {
13
14// -------------------------------------------------------------------
15// Dot/dotty output
16
18 public:
19 explicit DotPrinterImpl(std::ostream& os) : os_(os) {}
20 void PrintNode(const char* label, RegExpNode* node);
21 void Visit(RegExpNode* node);
22 void PrintAttributes(RegExpNode* from);
23 void PrintOnFailure(RegExpNode* from, RegExpNode* to);
24#define DECLARE_VISIT(Type) virtual void Visit##Type(Type##Node* that);
26#undef DECLARE_VISIT
27 private:
28 std::ostream& os_;
29};
30
31void DotPrinterImpl::PrintNode(const char* label, RegExpNode* node) {
32 os_ << "digraph G {\n graph [label=\"";
33 for (int i = 0; label[i]; i++) {
34 switch (label[i]) {
35 case '\\':
36 os_ << "\\\\";
37 break;
38 case '"':
39 os_ << "\"";
40 break;
41 default:
42 os_ << label[i];
43 break;
44 }
45 }
46 os_ << "\"];\n";
47 Visit(node);
48 os_ << "}" << std::endl;
49}
50
52 if (node->info()->visited) return;
53 node->info()->visited = true;
54 node->Accept(this);
55}
56
58 os_ << " n" << from << " -> n" << on_failure << " [style=dotted];\n";
59 Visit(on_failure);
60}
61
63 public:
64 explicit AttributePrinter(std::ostream& os) : os_(os), first_(true) {}
66 if (first_) {
67 first_ = false;
68 } else {
69 os_ << "|";
70 }
71 }
72 void PrintBit(const char* name, bool value) {
73 if (!value) return;
75 os_ << "{" << name << "}";
76 }
77 void PrintPositive(const char* name, int value) {
78 if (value < 0) return;
80 os_ << "{" << name << "|" << value << "}";
81 }
82
83 private:
84 std::ostream& os_;
85 bool first_;
86};
87
89 os_ << " a" << that << " [shape=Mrecord, color=grey, fontcolor=grey, "
90 << "margin=0.1, fontsize=10, label=\"{";
91 AttributePrinter printer(os_);
92 NodeInfo* info = that->info();
93 printer.PrintBit("NI", info->follows_newline_interest);
94 printer.PrintBit("WI", info->follows_word_interest);
95 printer.PrintBit("SI", info->follows_start_interest);
96 Label* label = that->label();
97 if (label->is_bound()) printer.PrintPositive("@", label->pos());
98 os_ << "}\"];\n"
99 << " a" << that << " -> n" << that
100 << " [style=dashed, color=grey, arrowhead=none];\n";
101}
102
103void DotPrinterImpl::VisitChoice(ChoiceNode* that) {
104 os_ << " n" << that << " [shape=Mrecord, label=\"?\"];\n";
105 for (int i = 0; i < that->alternatives()->length(); i++) {
106 GuardedAlternative alt = that->alternatives()->at(i);
107 os_ << " n" << that << " -> n" << alt.node();
108 }
109 for (int i = 0; i < that->alternatives()->length(); i++) {
110 GuardedAlternative alt = that->alternatives()->at(i);
111 alt.node()->Accept(this);
112 }
113 PrintAttributes(that);
114}
115
116void DotPrinterImpl::VisitLoopChoice(LoopChoiceNode* that) {
117 VisitChoice(that);
118}
119
120void DotPrinterImpl::VisitNegativeLookaroundChoice(
121 NegativeLookaroundChoiceNode* that) {
122 VisitChoice(that);
123}
124
125void DotPrinterImpl::VisitText(TextNode* that) {
126 Zone* zone = that->zone();
127 os_ << " n" << that << " [label=\"";
128 for (int i = 0; i < that->elements()->length(); i++) {
129 if (i > 0) os_ << " ";
130 TextElement elm = that->elements()->at(i);
131 switch (elm.text_type()) {
132 case TextElement::ATOM: {
133 base::Vector<const base::uc16> data = elm.atom()->data();
134 for (int j = 0; j < data.length(); j++) {
136 }
137 break;
138 }
140 RegExpClassRanges* node = elm.class_ranges();
141 os_ << "[";
142 if (node->is_negated()) os_ << "^";
143 for (int j = 0; j < node->ranges(zone)->length(); j++) {
144 CharacterRange range = node->ranges(zone)->at(j);
145 os_ << AsUC32(range.from()) << "-" << AsUC32(range.to());
146 }
147 os_ << "]";
148 break;
149 }
150 default:
151 UNREACHABLE();
152 }
153 }
154 os_ << "\", shape=box, peripheries=2];\n";
155 PrintAttributes(that);
156 os_ << " n" << that << " -> n" << that->on_success() << ";\n";
157 Visit(that->on_success());
158}
159
160void DotPrinterImpl::VisitBackReference(BackReferenceNode* that) {
161 os_ << " n" << that << " [label=\"$" << that->start_register() << "..$"
162 << that->end_register() << "\", shape=doubleoctagon];\n";
163 PrintAttributes(that);
164 os_ << " n" << that << " -> n" << that->on_success() << ";\n";
165 Visit(that->on_success());
166}
167
168void DotPrinterImpl::VisitEnd(EndNode* that) {
169 os_ << " n" << that << " [style=bold, shape=point];\n";
170 PrintAttributes(that);
171}
172
173void DotPrinterImpl::VisitAssertion(AssertionNode* that) {
174 os_ << " n" << that << " [";
175 switch (that->assertion_type()) {
177 os_ << "label=\"$\", shape=septagon";
178 break;
180 os_ << "label=\"^\", shape=septagon";
181 break;
183 os_ << "label=\"\\b\", shape=septagon";
184 break;
186 os_ << "label=\"\\B\", shape=septagon";
187 break;
189 os_ << "label=\"(?<=\\n)\", shape=septagon";
190 break;
191 }
192 os_ << "];\n";
193 PrintAttributes(that);
194 RegExpNode* successor = that->on_success();
195 os_ << " n" << that << " -> n" << successor << ";\n";
196 Visit(successor);
197}
198
199void DotPrinterImpl::VisitAction(ActionNode* that) {
200 os_ << " n" << that << " [";
201 switch (that->action_type_) {
203 os_ << "label=\"$" << that->data_.u_store_register.reg
204 << ":=" << that->data_.u_store_register.value << "\", shape=octagon";
205 break;
207 os_ << "label=\"$" << that->data_.u_increment_register.reg
208 << "++\", shape=octagon";
209 break;
211 os_ << "label=\"$" << that->data_.u_position_register.reg
212 << ":=$pos\", shape=octagon";
213 break;
215 os_ << "label=\"$" << that->data_.u_submatch.current_position_register
216 << ":=$pos,begin-positive\", shape=septagon";
217 break;
219 os_ << "label=\"$" << that->data_.u_submatch.current_position_register
220 << ":=$pos,begin-negative\", shape=septagon";
221 break;
223 os_ << "label=\"escape\", shape=septagon";
224 break;
226 os_ << "label=\"$" << that->data_.u_empty_match_check.start_register
227 << "=$pos?,$" << that->data_.u_empty_match_check.repetition_register
228 << "<" << that->data_.u_empty_match_check.repetition_limit
229 << "?\", shape=septagon";
230 break;
232 os_ << "label=\"clear $" << that->data_.u_clear_captures.range_from
233 << " to $" << that->data_.u_clear_captures.range_to
234 << "\", shape=septagon";
235 break;
236 }
238 os_ << "label=\"flags $" << that->flags() << "\", shape=septagon";
239 break;
240 }
241 }
242 os_ << "];\n";
243 PrintAttributes(that);
244 RegExpNode* successor = that->on_success();
245 os_ << " n" << that << " -> n" << successor << ";\n";
246 Visit(successor);
247}
248
249void DotPrinter::DotPrint(const char* label, RegExpNode* node) {
250 StdoutStream os;
251 DotPrinterImpl printer(os);
252 printer.PrintNode(label, node);
253}
254
255} // namespace internal
256} // namespace v8
friend Zone
Definition asm-types.cc:195
#define DECLARE_VISIT(type)
void PrintPositive(const char *name, int value)
void PrintBit(const char *name, bool value)
void PrintNode(const char *label, RegExpNode *node)
void Visit(RegExpNode *node)
void PrintAttributes(RegExpNode *from)
void PrintOnFailure(RegExpNode *from, RegExpNode *to)
static void DotPrint(const char *label, RegExpNode *node)
virtual void Accept(NodeVisitor *visitor)=0
Label label
#define FOR_EACH_NODE_TYPE(VISIT)