tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

regexp-dotprinter.cc (8353B)


      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 
      5 #include "irregexp/imported/regexp-dotprinter.h"
      6 
      7 #include "irregexp/imported/regexp-compiler.h"
      8 
      9 namespace v8 {
     10 namespace internal {
     11 
     12 // -------------------------------------------------------------------
     13 // Dot/dotty output
     14 
     15 class DotPrinterImpl : public NodeVisitor {
     16 public:
     17  explicit DotPrinterImpl(std::ostream& os) : os_(os) {}
     18  void PrintNode(const char* label, RegExpNode* node);
     19  void Visit(RegExpNode* node);
     20  void PrintAttributes(RegExpNode* from);
     21  void PrintOnFailure(RegExpNode* from, RegExpNode* to);
     22 #define DECLARE_VISIT(Type) virtual void Visit##Type(Type##Node* that);
     23  FOR_EACH_NODE_TYPE(DECLARE_VISIT)
     24 #undef DECLARE_VISIT
     25 private:
     26  std::ostream& os_;
     27 };
     28 
     29 void DotPrinterImpl::PrintNode(const char* label, RegExpNode* node) {
     30  os_ << "digraph G {\n  graph [label=\"";
     31  for (int i = 0; label[i]; i++) {
     32    switch (label[i]) {
     33      case '\\':
     34        os_ << "\\\\";
     35        break;
     36      case '"':
     37        os_ << "\"";
     38        break;
     39      default:
     40        os_ << label[i];
     41        break;
     42    }
     43    if (i > 40) {
     44      os_ << "...";
     45      break;
     46    }
     47  }
     48  os_ << "\"];\n";
     49  Visit(node);
     50  os_ << "}" << std::endl;
     51 }
     52 
     53 void DotPrinterImpl::Visit(RegExpNode* node) {
     54  if (node->info()->visited) return;
     55  node->info()->visited = true;
     56  node->Accept(this);
     57 }
     58 
     59 void DotPrinterImpl::PrintOnFailure(RegExpNode* from, RegExpNode* on_failure) {
     60  os_ << "  n" << from << " -> n" << on_failure << " [style=dotted];\n";
     61  Visit(on_failure);
     62 }
     63 
     64 class AttributePrinter {
     65 public:
     66  explicit AttributePrinter(std::ostream& os) : os_(os), first_(true) {}
     67  void PrintSeparator() {
     68    if (first_) {
     69      first_ = false;
     70    } else {
     71      os_ << "|";
     72    }
     73  }
     74  void PrintBit(const char* name, bool value) {
     75    if (!value) return;
     76    PrintSeparator();
     77    os_ << "{";
     78    for (const char* p = name; *p; p++) {
     79      os_ << AsUC16(static_cast<unsigned char>(*p));
     80    }
     81    os_ << name << "}";
     82  }
     83  void PrintPositive(const char* name, int value) {
     84    if (value < 0) return;
     85    PrintSeparator();
     86    os_ << "{" << name << "|" << value << "}";
     87  }
     88 
     89 private:
     90  std::ostream& os_;
     91  bool first_;
     92 };
     93 
     94 void DotPrinterImpl::PrintAttributes(RegExpNode* that) {
     95  os_ << "  a" << that << " [shape=Mrecord, color=grey, fontcolor=grey, "
     96      << "margin=0.1, fontsize=10, label=\"{";
     97  AttributePrinter printer(os_);
     98  NodeInfo* info = that->info();
     99  printer.PrintBit("NI", info->follows_newline_interest);
    100  printer.PrintBit("WI", info->follows_word_interest);
    101  printer.PrintBit("SI", info->follows_start_interest);
    102  Label* label = that->label();
    103  if (label->is_bound()) printer.PrintPositive("@", label->pos());
    104  os_ << "}\"];\n"
    105      << "  a" << that << " -> n" << that
    106      << " [style=dashed, color=grey, arrowhead=none];\n";
    107 }
    108 
    109 void DotPrinterImpl::VisitChoice(ChoiceNode* that) {
    110  os_ << "  n" << that << " [shape=Mrecord, label=\"?";
    111  if (that->AsNegativeLookaroundChoiceNode()) os_ << " neg";
    112  os_ << "\"];\n";
    113  for (int i = 0; i < that->alternatives()->length(); i++) {
    114    GuardedAlternative alt = that->alternatives()->at(i);
    115    os_ << "  n" << that << " -> n" << alt.node();
    116  }
    117  for (int i = 0; i < that->alternatives()->length(); i++) {
    118    GuardedAlternative alt = that->alternatives()->at(i);
    119    alt.node()->Accept(this);
    120  }
    121  PrintAttributes(that);
    122 }
    123 
    124 void DotPrinterImpl::VisitLoopChoice(LoopChoiceNode* that) {
    125  VisitChoice(that);
    126 }
    127 
    128 void DotPrinterImpl::VisitNegativeLookaroundChoice(
    129    NegativeLookaroundChoiceNode* that) {
    130  VisitChoice(that);
    131 }
    132 
    133 void DotPrinterImpl::VisitText(TextNode* that) {
    134  Zone* zone = that->zone();
    135  os_ << "  n" << that << " [label=\"";
    136  for (int i = 0; i < that->elements()->length(); i++) {
    137    if (i > 0) os_ << " ";
    138    TextElement elm = that->elements()->at(i);
    139    switch (elm.text_type()) {
    140      case TextElement::ATOM: {
    141        base::Vector<const base::uc16> data = elm.atom()->data();
    142        for (int j = 0; j < data.length(); j++) {
    143          os_ << AsUC32(data[j]);
    144        }
    145        break;
    146      }
    147      case TextElement::CLASS_RANGES: {
    148        RegExpClassRanges* node = elm.class_ranges();
    149        os_ << "[";
    150        if (node->is_negated()) os_ << "^";
    151        for (int j = 0; j < node->ranges(zone)->length(); j++) {
    152          CharacterRange range = node->ranges(zone)->at(j);
    153          os_ << AsUC32(range.from()) << "-" << AsUC32(range.to());
    154          if (j > 5) {
    155            os_ << "...";
    156            break;
    157          }
    158        }
    159        os_ << "]";
    160        break;
    161      }
    162      default:
    163        UNREACHABLE();
    164    }
    165    if (i > 40) {
    166      os_ << "...";
    167      break;
    168    }
    169  }
    170  os_ << "\", shape=box, peripheries=2];\n";
    171  PrintAttributes(that);
    172  os_ << "  n" << that << " -> n" << that->on_success() << ";\n";
    173  Visit(that->on_success());
    174 }
    175 
    176 void DotPrinterImpl::VisitBackReference(BackReferenceNode* that) {
    177  os_ << "  n" << that << " [label=\"$" << that->start_register() << "..$"
    178      << that->end_register() << "\", shape=doubleoctagon];\n";
    179  PrintAttributes(that);
    180  os_ << "  n" << that << " -> n" << that->on_success() << ";\n";
    181  Visit(that->on_success());
    182 }
    183 
    184 void DotPrinterImpl::VisitEnd(EndNode* that) {
    185  os_ << "  n" << that << " [style=bold, shape=point];\n";
    186  PrintAttributes(that);
    187 }
    188 
    189 void DotPrinterImpl::VisitAssertion(AssertionNode* that) {
    190  os_ << "  n" << that << " [";
    191  switch (that->assertion_type()) {
    192    case AssertionNode::AT_END:
    193      os_ << "label=\"$\", shape=septagon";
    194      break;
    195    case AssertionNode::AT_START:
    196      os_ << "label=\"^\", shape=septagon";
    197      break;
    198    case AssertionNode::AT_BOUNDARY:
    199      os_ << "label=\"\\b\", shape=septagon";
    200      break;
    201    case AssertionNode::AT_NON_BOUNDARY:
    202      os_ << "label=\"\\B\", shape=septagon";
    203      break;
    204    case AssertionNode::AFTER_NEWLINE:
    205      os_ << "label=\"(?<=\\n)\", shape=septagon";
    206      break;
    207  }
    208  os_ << "];\n";
    209  PrintAttributes(that);
    210  RegExpNode* successor = that->on_success();
    211  os_ << "  n" << that << " -> n" << successor << ";\n";
    212  Visit(successor);
    213 }
    214 
    215 void DotPrinterImpl::VisitAction(ActionNode* that) {
    216  os_ << "  n" << that << " [";
    217  switch (that->action_type_) {
    218    case ActionNode::SET_REGISTER_FOR_LOOP:
    219      os_ << "label=\"$" << that->register_from() << ":=" << that->value()
    220          << "\", shape=octagon";
    221      break;
    222    case ActionNode::INCREMENT_REGISTER:
    223      os_ << "label=\"$" << that->register_from() << "++\", shape=octagon";
    224      break;
    225    case ActionNode::CLEAR_POSITION:
    226      os_ << "label=\"$" << that->register_from()
    227          << ":=$pos c\", shape=octagon";
    228      break;
    229    case ActionNode::RESTORE_POSITION:
    230      os_ << "label=\"$" << that->register_from()
    231          << ":=$pos r\", shape=octagon";
    232      break;
    233    case ActionNode::BEGIN_POSITIVE_SUBMATCH:
    234      os_ << "label=\"$" << that->data_.u_submatch.current_position_register
    235          << ":=$pos,begin-positive\", shape=septagon";
    236      break;
    237    case ActionNode::BEGIN_NEGATIVE_SUBMATCH:
    238      os_ << "label=\"$" << that->data_.u_submatch.current_position_register
    239          << ":=$pos,begin-negative\", shape=septagon";
    240      break;
    241    case ActionNode::POSITIVE_SUBMATCH_SUCCESS:
    242      os_ << "label=\"escape\", shape=septagon";
    243      break;
    244    case ActionNode::EMPTY_MATCH_CHECK:
    245      os_ << "label=\"$" << that->data_.u_empty_match_check.start_register
    246          << "=$pos?,$" << that->data_.u_empty_match_check.repetition_register
    247          << "<" << that->data_.u_empty_match_check.repetition_limit
    248          << "?\", shape=septagon";
    249      break;
    250    case ActionNode::CLEAR_CAPTURES: {
    251      os_ << "label=\"clear $" << that->register_from() << " to $"
    252          << that->register_to() << "\", shape=septagon";
    253      break;
    254    }
    255    case ActionNode::MODIFY_FLAGS: {
    256      os_ << "label=\"flags $" << that->flags() << "\", shape=septagon";
    257      break;
    258    }
    259  }
    260  os_ << "];\n";
    261  PrintAttributes(that);
    262  RegExpNode* successor = that->on_success();
    263  os_ << "  n" << that << " -> n" << successor << ";\n";
    264  Visit(successor);
    265 }
    266 
    267 void DotPrinter::DotPrint(const char* label, RegExpNode* node) {
    268  StdoutStream os;
    269  DotPrinterImpl printer(os);
    270  printer.PrintNode(label, node);
    271 }
    272 
    273 }  // namespace internal
    274 }  // namespace v8