void CTagQualifiers::operator()( const CNode& node, CTreeNode& tree_node )
{
    (*this)(node);
    auto arg = node.first_child();
    CTag& argTag = CTagContainer::getTag( arg.name() );
    int argType = argTag.getType();
    argTag(arg, tree_node.Step(node.name()));
    arg = argTag.checkSignature(arg);
}
bool FormulaComputability::checkComputability( const CNode& rootNode )
{
    CNode currentNode = rootNode.first_child();
    while ( !currentNode.empty() )
    {
        CTag& currentTag = CTagContainer::getTag(currentNode.name());
        CNode nextNode = currentTag.checkSignature( currentNode );
        currentTag(currentNode);
        currentNode = nextNode;
    }
    return true;
}
void CTagCn::operator ()(const CNode& node, CTreeNode& tree_node)
{
	(*this)(node);
	checkAttributes(node, { "type" });
	string attr = node.attribute("type").as_string();
	CNode child = node.first_child();
	if (attr == "real" || attr == "")
	{
		hasNChilds(node, 1);
		nodeIsReal(child, tree_node.Step("cn"));
		return;
	}
}
void CTagCn::operator ()(const CNode& node)const
{
	checkAttributes(node, { "type" });
	string attr = node.attribute("type").as_string();
	CNode child = node.first_child();
	if (attr == "real" || attr == "")
	{
		hasNChilds(node, 1);
		nodeIsReal(child);
		return;
	}
	if (attr == "integer")
	{
		hasNChilds(node, 1);
		nodeIsInteger(child);
		return;
	};
	// syntax "real <sep/> real"
	if ((attr == "complex-cartesian") || (attr == "complex-polar"))
	{
		hasNChilds(node, 3);
		nodeIsReal(child);
		nodeIsReal(child.next_sibling().next_sibling());
		if (string(child.next_sibling().name()) != string("sep"))
			throwException(node, node.offset_debug(), INCORRECT_VALUE);
		return;
	};

	// syntax "int <sep/> imt"
	if (attr == "rational")
	{
		hasNChilds(node, 3);
		nodeIsInteger(child);
		nodeIsInteger(child.next_sibling().next_sibling());
		if (string(child.next_sibling().name()) != string("sep"))
			throwException(node, node.offset_debug(), INCORRECT_VALUE);
		return;
	};

	if (attr == "constant")
	{
		return;
	};

	throwException(node, node.offset_debug(), UNKNOWN_ATTRIBUTE);
}
void CTagQualifiers::operator()( const CNode& node ) const
{
    auto arg = node.first_child();
    if (arg.empty()) {
        throwException(arg, arg.offset_debug(), MISSED_ARGUMENT);
    }
    CTag& argTag = CTagContainer::getTag( arg.name() );
    int argType = argTag.getType();
    //проверяем тип первого тега
    if ( !( argType & (NUMBER | VARIABLE |SPECIAL) ) ) {
        throwException( arg, arg.offset_debug(), INVALID_ARGUMENT );
    }
    //инициируем проверку дочерних тэгов
    argTag(arg);
    //проверяем, что больше детей нет
    arg = argTag.checkSignature(arg);
    if ( !arg.empty() ) {
        throwException( arg, arg.offset_debug(), INVALID_ARGUMENT );
    }
}