huntzhan / clidoc

Prove Of Conecept Fork Of Docopt.
MIT License
7 stars 1 forks source link

Strategy of `StructureOptimizer`. #18

Closed huntzhan closed 9 years ago

huntzhan commented 9 years ago

According to the meaning of logical nodes(discussed in #15 ), the AST should be optimized by removing some non-terminal nodes. Code fragment implemented the strategy is as follow:

  SharedPtrNodeContainer optimized_children;
  for (auto child : node->children_) {
    child->Accept(this);
    // decide expand or not.
    bool child_is_logic_and =
        child->GetID() == kNonTermianlClassName.at(NonTerminalType::LOGIC_AND);
    bool child_is_logic_xor =
        child->GetID() == kNonTermianlClassName.at(NonTerminalType::LOGIC_XOR);
    bool child_is_logic_or =
        child->GetID() == kNonTermianlClassName.at(NonTerminalType::LOGIC_OR);
    bool equivalent = false;
    // 1. equivalent if they have the same id.
    if (node->GetID() == child->GetID()) {
      equivalent = true;
    }
    // 2. when child is one of (`LogicAnd`, `LogicXor`, `LogicOr`), and
    // child->GetSizeOfChildren() equals to 1, remove the child.
    if ((child_is_logic_and || child_is_logic_xor || child_is_logic_or)
        && child->GetSizeOfChildren() == 1) {
      equivalent = true;
    }
    // remove non-terminal based on `equivalent`.
    if (equivalent) {
      // same non-terminal nodes.
      optimized_children.insert(
          optimized_children.end(),
          children_of_child_.begin(), children_of_child_.end());
    } else {
      optimized_children.push_back(child);
    }
  }

And node type transformation:

void StructureOptimizer::ProcessNode(
    LogicXor::SharedPtr node) {
  RemoveDuplicatedNodes(node);
  // transfrom to `LogicAnd` when there's only one child.
  if (node->GetSizeOfChildren() == 1) {
    NodeTypeModifier<LogicAnd>::ChangeNonTerminalType(node);
  }
}

void StructureOptimizer::ProcessNode(
    LogicOr::SharedPtr node) {
  RemoveDuplicatedNodes(node);
  // transfrom to `LogicAnd` when there's only one child.
  if (node->GetSizeOfChildren() == 1) {
    NodeTypeModifier<LogicAnd>::ChangeNonTerminalType(node);
  }
}
huntzhan commented 9 years ago

If the SYNOPSIS shows an optional option-argument (as with [ -f[ option_argument]] in the example), a conforming application shall place any option-argument for that option directly adjacent to the option in the same argument string, without intervening characters. If the utility receives an argument containing only the option, it shall behave as specified in its description for an omitted option-argument; it shall not treat the next argument (if any) as the option-argument for that option.

Remove non-terminals with no child!