From 1425db604175e2e53f151e63eefe542c82cac09d Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Wed, 6 Apr 2016 12:54:38 +0200 Subject: [PATCH] UnrankedNonlinearPattern +fixes --- .../common/RankedNonlinearPatternAlphabet.cpp | 6 +- .../UnrankedNonlinearPatternAlphabet.cpp | 49 +++++ .../common/UnrankedNonlinearPatternAlphabet.h | 57 ++++++ .../tree/ranked/RankedNonlinearPattern.cpp | 9 +- .../src/tree/ranked/RankedNonlinearPattern.h | 1 + alib2data/src/tree/unranked/UnrankedNode.h | 1 + .../unranked/UnrankedNonlinearPattern.cpp | 185 ++++++++++++++++++ .../tree/unranked/UnrankedNonlinearPattern.h | 127 ++++++++++++ 8 files changed, 430 insertions(+), 5 deletions(-) create mode 100644 alib2data/src/tree/common/UnrankedNonlinearPatternAlphabet.cpp create mode 100644 alib2data/src/tree/common/UnrankedNonlinearPatternAlphabet.h create mode 100644 alib2data/src/tree/unranked/UnrankedNonlinearPattern.cpp create mode 100644 alib2data/src/tree/unranked/UnrankedNonlinearPattern.h diff --git a/alib2data/src/tree/common/RankedNonlinearPatternAlphabet.cpp b/alib2data/src/tree/common/RankedNonlinearPatternAlphabet.cpp index 6d734ac4ea..63e63ea4db 100644 --- a/alib2data/src/tree/common/RankedNonlinearPatternAlphabet.cpp +++ b/alib2data/src/tree/common/RankedNonlinearPatternAlphabet.cpp @@ -32,7 +32,7 @@ bool RankedNonlinearPatternAlphabet::addNonlinearVariable ( alphabet::RankedSymb void RankedNonlinearPatternAlphabet::addNonlinearVariables ( std::set < alphabet::RankedSymbol > symbols ) { for ( alphabet::RankedSymbol addedSymbol : std::move ( symbols ) ) - addSymbolToAlphabet ( std::move ( addedSymbol ) ); + addNonlinearVariable ( std::move ( addedSymbol ) ); } void RankedNonlinearPatternAlphabet::setNonlinearVariables ( std::set < alphabet::RankedSymbol > newSymbols ) { @@ -42,7 +42,7 @@ void RankedNonlinearPatternAlphabet::setNonlinearVariables ( std::set < alphabet for ( const alphabet::RankedSymbol & removedSymbol : removed ) removeNonlinearVariable ( removedSymbol ); - alphabet = std::move ( newSymbols ); + nonlinearVariables = std::move ( newSymbols ); } const std::set < alphabet::RankedSymbol > & RankedNonlinearPatternAlphabet::getNonlinearVariables ( ) const { @@ -50,7 +50,7 @@ const std::set < alphabet::RankedSymbol > & RankedNonlinearPatternAlphabet::getN } bool RankedNonlinearPatternAlphabet::removeNonlinearVariable ( const alphabet::RankedSymbol & symbol ) { - return alphabet.insert ( std::move ( symbol ) ).second; + return nonlinearVariables.insert ( std::move ( symbol ) ).second; } } /* namespace tree */ diff --git a/alib2data/src/tree/common/UnrankedNonlinearPatternAlphabet.cpp b/alib2data/src/tree/common/UnrankedNonlinearPatternAlphabet.cpp new file mode 100644 index 0000000000..647f270d3b --- /dev/null +++ b/alib2data/src/tree/common/UnrankedNonlinearPatternAlphabet.cpp @@ -0,0 +1,49 @@ +/* + * UnrankedNonlinearAlphabet.cpp + * + * Created on: Mar 13, 2016 + * Author: Jan Travnicek + */ + +#include "UnrankedNonlinearPatternAlphabet.h" +#include "../TreeException.h" + +#include <algorithm> + +namespace tree { + +UnrankedNonlinearPatternAlphabet::UnrankedNonlinearPatternAlphabet ( alphabet::Symbol subtreeWildcard, std::set < alphabet::Symbol > nonlinearVariables ) : UnrankedPatternAlphabet ( subtreeWildcard ), nonlinearVariables ( nonlinearVariables ) { + alphabet.insert ( std::move ( subtreeWildcard ) ); +} + +bool UnrankedNonlinearPatternAlphabet::addNonlinearVariable ( alphabet::Symbol symbol ) { + if ( !alphabet.count ( symbol ) ) + throw TreeException ( "Subtree nonlinear variable \"" + ( std::string ) symbol + "\" is not in the alphabet." ); + + return nonlinearVariables.insert ( symbol ).second; +} + +void UnrankedNonlinearPatternAlphabet::addNonlinearVariables ( std::set < alphabet::Symbol > symbols ) { + for ( alphabet::Symbol addedSymbol : std::move ( symbols ) ) + addNonlinearVariable ( std::move ( addedSymbol ) ); +} + +void UnrankedNonlinearPatternAlphabet::setNonlinearVariables ( std::set < alphabet::Symbol > newSymbols ) { + std::set < alphabet::Symbol > removed; + std::set_difference ( nonlinearVariables.begin ( ), nonlinearVariables.end ( ), newSymbols.begin ( ), newSymbols.end ( ), std::inserter ( removed, removed.end ( ) ) ); + + for ( const alphabet::Symbol & removedSymbol : removed ) + removeNonlinearVariable ( removedSymbol ); + + nonlinearVariables = std::move ( newSymbols ); +} + +const std::set < alphabet::Symbol > & UnrankedNonlinearPatternAlphabet::getNonlinearVariables ( ) const { + return nonlinearVariables; +} + +bool UnrankedNonlinearPatternAlphabet::removeNonlinearVariable ( const alphabet::Symbol & symbol ) { + return alphabet.insert ( std::move ( symbol ) ).second; +} + +} /* namespace tree */ diff --git a/alib2data/src/tree/common/UnrankedNonlinearPatternAlphabet.h b/alib2data/src/tree/common/UnrankedNonlinearPatternAlphabet.h new file mode 100644 index 0000000000..9189e94a52 --- /dev/null +++ b/alib2data/src/tree/common/UnrankedNonlinearPatternAlphabet.h @@ -0,0 +1,57 @@ +/* + * UnrankedNonlinearPatternAlphabet.h + * + * Created on: Mar 13, 2016 + * Author: Jan Travnicek + */ + +#ifndef UNRANKED_NONLINEAR_PATTERN_ALPHABET_H_ +#define UNRANKED_NONLINEAR_PATTERN_ALPHABET_H_ + +#include "UnrankedPatternAlphabet.h" + +namespace tree { + +/** + * Abstract base class for all strings. Contains common elements of strings. + */ +class UnrankedNonlinearPatternAlphabet : public UnrankedPatternAlphabet { +protected: + std::set < alphabet::Symbol > nonlinearVariables; + +public: + UnrankedNonlinearPatternAlphabet ( alphabet::Symbol subtreeWildcard, std::set < alphabet::Symbol > nonlinearVariables ); + + /** + * Adds the nonlinear variable = symbol representing subtree substitution place in the pattern + * @param symbol Symbol to set + */ + bool addNonlinearVariable ( alphabet::Symbol symbol ); + + /** + * Adds the nonlinear variables = symbols representing subtree substitution place in the pattern + * @param symbol Symbol to set + */ + void addNonlinearVariables ( std::set < alphabet::Symbol > symbols ); + + /** + * Sets the nonlinear variables = symbol representing subtree substitution place in the pattern + * @param symbol Symbol to set + */ + void setNonlinearVariables ( std::set < alphabet::Symbol > symbols ); + + /** + * @return symbols representing nonlinear variables + */ + const std::set < alphabet::Symbol > & getNonlinearVariables ( ) const; + + /** + * Removes the nonlinear variable = symbol representing subtree substitution place in the pattern + * @param symbol Symbol to set + */ + bool removeNonlinearVariable ( const alphabet::Symbol & symbol ); +}; + +} /* namespace tree */ + +#endif /* UNRANKED_NONLINEAR_PATTERN_ALPHABET_H_ */ diff --git a/alib2data/src/tree/ranked/RankedNonlinearPattern.cpp b/alib2data/src/tree/ranked/RankedNonlinearPattern.cpp index a9f63cc152..9a3f861035 100644 --- a/alib2data/src/tree/ranked/RankedNonlinearPattern.cpp +++ b/alib2data/src/tree/ranked/RankedNonlinearPattern.cpp @@ -31,8 +31,13 @@ RankedNonlinearPattern::RankedNonlinearPattern ( alphabet::RankedSymbol subtreeW setTree ( std::move ( pattern ) ); } -RankedNonlinearPattern::RankedNonlinearPattern ( alphabet::RankedSymbol subtreeWildcard, RankedNode pattern ) : RankedNonlinearPatternAlphabet ( std::move ( subtreeWildcard ), { - } ) { +RankedNonlinearPattern::RankedNonlinearPattern ( alphabet::RankedSymbol subtreeWildcard, std::set < alphabet::RankedSymbol > nonlinearVariables, RankedNode pattern ) : RankedNonlinearPatternAlphabet ( std::move ( subtreeWildcard ), std::move ( nonlinearVariables ) ) { + pattern.computeMinimalAlphabet ( alphabet ); + this->pattern = NULL; + setTree ( std::move ( pattern ) ); +} + +RankedNonlinearPattern::RankedNonlinearPattern ( alphabet::RankedSymbol subtreeWildcard, RankedNode pattern ) : RankedNonlinearPatternAlphabet ( std::move ( subtreeWildcard ), { } ) { pattern.computeMinimalAlphabet ( alphabet ); this->pattern = NULL; setTree ( std::move ( pattern ) ); diff --git a/alib2data/src/tree/ranked/RankedNonlinearPattern.h b/alib2data/src/tree/ranked/RankedNonlinearPattern.h index 50c6374bba..2c74d13771 100644 --- a/alib2data/src/tree/ranked/RankedNonlinearPattern.h +++ b/alib2data/src/tree/ranked/RankedNonlinearPattern.h @@ -41,6 +41,7 @@ public: virtual RankedTreeBase * plunder ( ) &&; explicit RankedNonlinearPattern ( alphabet::RankedSymbol subtreeWildcard, std::set < alphabet::RankedSymbol > nonlinearVariables, std::set < alphabet::RankedSymbol > alphabet, RankedNode pattern ); + explicit RankedNonlinearPattern ( alphabet::RankedSymbol subtreeWildcard, std::set < alphabet::RankedSymbol > nonlinearVariables, RankedNode pattern ); explicit RankedNonlinearPattern ( alphabet::RankedSymbol subtreeWildcard, RankedNode pattern ); /** diff --git a/alib2data/src/tree/unranked/UnrankedNode.h b/alib2data/src/tree/unranked/UnrankedNode.h index e92e9b4100..10842e833c 100644 --- a/alib2data/src/tree/unranked/UnrankedNode.h +++ b/alib2data/src/tree/unranked/UnrankedNode.h @@ -113,6 +113,7 @@ public: friend class UnrankedTree; friend class UnrankedPattern; + friend class UnrankedNonlinearPattern; friend class RankedTree; friend class RankedPattern; }; diff --git a/alib2data/src/tree/unranked/UnrankedNonlinearPattern.cpp b/alib2data/src/tree/unranked/UnrankedNonlinearPattern.cpp new file mode 100644 index 0000000000..7ae4298a38 --- /dev/null +++ b/alib2data/src/tree/unranked/UnrankedNonlinearPattern.cpp @@ -0,0 +1,185 @@ +/* + * UnrankedNonlinearPattern.cpp + * + * Created on: Nov 23, 2013 + * Author: Jan Travnicek + */ + +#include "UnrankedNonlinearPattern.h" +#include <exception/AlibException.h> + +#include <iostream> +#include <algorithm> +#include <sstream> + +#include "../unranked/UnrankedPattern.h" + +#include <sax/FromXMLParserHelper.h> +#include "../common/TreeFromXMLParser.h" +#include "../common/TreeToXMLComposer.h" +#include "../Tree.h" +#include "../UnrankedTreeWrapper.h" +#include <object/Object.h> +#include <XmlApi.hpp> +#include <cast/CastApi.hpp> + +namespace tree { + +UnrankedNonlinearPattern::UnrankedNonlinearPattern ( alphabet::Symbol subtreeWildcard, std::set < alphabet::Symbol > nonlinearVariables, std::set < alphabet::Symbol > alphabet, UnrankedNode pattern ) : UnrankedNonlinearPatternAlphabet ( std::move ( subtreeWildcard ), std::move ( nonlinearVariables ) ) { + setAlphabet ( std::move ( alphabet ) ); + this->pattern = NULL; + setTree ( std::move ( pattern ) ); +} + +UnrankedNonlinearPattern::UnrankedNonlinearPattern ( alphabet::Symbol subtreeWildcard, std::set < alphabet::Symbol > nonlinearVariables, UnrankedNode pattern ) : UnrankedNonlinearPatternAlphabet ( std::move ( subtreeWildcard ), std::move ( nonlinearVariables ) ) { + pattern.computeMinimalAlphabet ( alphabet ); + this->pattern = NULL; + setTree ( std::move ( pattern ) ); +} + +UnrankedNonlinearPattern::UnrankedNonlinearPattern ( alphabet::Symbol subtreeWildcard, UnrankedNode pattern ) : UnrankedNonlinearPatternAlphabet ( std::move ( subtreeWildcard ), { } ) { + pattern.computeMinimalAlphabet ( alphabet ); + this->pattern = NULL; + setTree ( std::move ( pattern ) ); +} + +UnrankedNonlinearPattern::UnrankedNonlinearPattern ( const UnrankedNonlinearPattern & other ) : UnrankedNonlinearPatternAlphabet ( other ), pattern ( other.pattern->clone ( ) ) { + this->pattern->attachTree ( this ); +} + +UnrankedNonlinearPattern::UnrankedNonlinearPattern ( UnrankedNonlinearPattern && other ) noexcept : UnrankedNonlinearPatternAlphabet ( other ), pattern ( other.pattern ) { + this->pattern->attachTree ( this ); + other.pattern = NULL; +} + +UnrankedTreeBase * UnrankedNonlinearPattern::clone ( ) const { + return new UnrankedNonlinearPattern ( * this ); +} + +UnrankedTreeBase * UnrankedNonlinearPattern::plunder ( ) && { + return new UnrankedNonlinearPattern ( std::move ( * this ) ); +} + +UnrankedNonlinearPattern & UnrankedNonlinearPattern::operator =( const UnrankedNonlinearPattern & other ) { + if ( this == & other ) + return * this; + + * this = UnrankedNonlinearPattern ( other ); + + return * this; +} + +UnrankedNonlinearPattern & UnrankedNonlinearPattern::operator =( UnrankedNonlinearPattern && other ) noexcept { + std::swap ( this->pattern, other.pattern ); + std::swap ( this->alphabet, other.alphabet ); + std::swap ( this->subtreeWildcard, other.subtreeWildcard ); + std::swap ( this->nonlinearVariables, other.nonlinearVariables ); + + return * this; +} + +UnrankedNonlinearPattern::~UnrankedNonlinearPattern ( ) noexcept { + delete pattern; +} + +const UnrankedNode & UnrankedNonlinearPattern::getRoot ( ) const { + return * pattern; +} + +UnrankedNode & UnrankedNonlinearPattern::getRoot ( ) { + return * pattern; +} + +void UnrankedNonlinearPattern::setTree ( UnrankedNode pattern ) { + delete this->pattern; + this->pattern = std::move ( pattern ).plunder ( ); + + if ( !this->pattern->attachTree ( this ) ) { + delete this->pattern; + throw exception::AlibException ( "Input symbols not in the alphabet." ); + } +} + +bool UnrankedNonlinearPattern::removeSymbolFromAlphabet ( const alphabet::Symbol & symbol ) { + if ( this->pattern->testSymbol ( symbol ) ) + throw exception::AlibException ( "Input symbol \"" + ( std::string ) symbol + "\" is used." ); + + if ( this->subtreeWildcard == symbol ) + throw exception::AlibException ( "Input symbol \"" + ( std::string ) symbol + "\" is subtreeWildcard." ); + + if ( std::any_of ( this->nonlinearVariables.begin ( ), this->nonlinearVariables.end ( ), [&] ( const alphabet::Symbol & nonlinearVariable ) { + return nonlinearVariable == symbol; + } ) ) + throw exception::AlibException ( "Input symbol \"" + ( std::string ) symbol + "\" is nonlinearVariable." ); + + return alphabet.erase ( symbol ); +} + +void UnrankedNonlinearPattern::operator >>( std::ostream & out ) const { + out << "(UnrankedNonlinearPattern " << * ( this->pattern ) << ")"; +} + +int UnrankedNonlinearPattern::compare ( const UnrankedNonlinearPattern & other ) const { + int res = pattern->compare ( * other.pattern ); + + if ( res == 0 ) { + std::compare < alphabet::Symbol > comp; + res = comp ( subtreeWildcard, other.subtreeWildcard ); + } + + if ( res == 0 ) { + std::compare < std::set < alphabet::Symbol > > comp; + res = comp ( nonlinearVariables, other.nonlinearVariables ); + } + + if ( res == 0 ) { + std::compare < std::set < alphabet::Symbol > > comp; + res = comp ( alphabet, other.alphabet ); + } + + return res; +} + +void UnrankedNonlinearPattern::nicePrint ( std::ostream & os ) const { + pattern->nicePrint ( os ); +} + +UnrankedNonlinearPattern::operator std::string ( ) const { + std::stringstream ss; + ss << * this; + return ss.str ( ); +} + +const std::string UnrankedNonlinearPattern::XML_TAG_NAME = "UnrankedNonlinearPattern"; + +UnrankedNonlinearPattern UnrankedNonlinearPattern::parse ( std::deque < sax::Token >::iterator & input ) { + sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, UnrankedNonlinearPattern::XML_TAG_NAME ); + alphabet::Symbol subtreeWildcardSymbol = TreeFromXMLParser::parseSubtreeWildcardSymbol ( input ); + std::set < alphabet::Symbol > nonlinearVariables = TreeFromXMLParser::parseUnrankedNonlinearVariables ( input ); + std::set < alphabet::Symbol > rankedAlphabet = TreeFromXMLParser::parseUnrankedAlphabet ( input ); + UnrankedNode * root = alib::xmlApi < UnrankedNode * >::parse ( input ); + UnrankedNonlinearPattern tree ( std::move ( subtreeWildcardSymbol ), std::move ( nonlinearVariables ), std::move ( rankedAlphabet ), std::move ( * root ) ); + + delete root; + sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, UnrankedNonlinearPattern::XML_TAG_NAME ); + return tree; +} + +void UnrankedNonlinearPattern::compose ( std::deque < sax::Token > & out ) const { + out.emplace_back ( UnrankedNonlinearPattern::XML_TAG_NAME, sax::Token::TokenType::START_ELEMENT ); + TreeToXMLComposer::composeSubtreeWildcard ( out, subtreeWildcard ); + TreeToXMLComposer::composeNonlinearVariables ( out, nonlinearVariables ); + TreeToXMLComposer::composeAlphabet ( out, alphabet ); + alib::xmlApi < UnrankedNode * >::compose ( out, pattern ); + out.emplace_back ( UnrankedNonlinearPattern::XML_TAG_NAME, sax::Token::TokenType::END_ELEMENT ); +} + +} /* namespace tree */ + +namespace alib { + +auto UnrankedNonlinearPatternParserRegister = xmlApi < tree::Tree >::ParserRegister < tree::UnrankedNonlinearPattern > ( ); +auto UnrankedNonlinearPatternParserRegister2 = xmlApi < tree::UnrankedTreeWrapper >::ParserRegister < tree::UnrankedNonlinearPattern > ( ); +auto UnrankedNonlinearPatternParserRegister3 = xmlApi < alib::Object >::ParserRegister < tree::UnrankedNonlinearPattern > ( ); + +} /* namespace alib */ diff --git a/alib2data/src/tree/unranked/UnrankedNonlinearPattern.h b/alib2data/src/tree/unranked/UnrankedNonlinearPattern.h new file mode 100644 index 0000000000..a66972f2c6 --- /dev/null +++ b/alib2data/src/tree/unranked/UnrankedNonlinearPattern.h @@ -0,0 +1,127 @@ +/* + * UnrankedNonlinearPattern.h + * + * Created on: Nov 23, 2013 + * Author: Jan Travnicek + */ + +#ifndef UNRANKED_NONLINEAR_PATTERN_H_ +#define UNRANKED_NONLINEAR_PATTERN_H_ + +#include <vector> +#include <list> +#include <string> +#include <set> +#include "UnrankedNode.h" +#include "../UnrankedTreeBase.h" +#include "../common/UnrankedNonlinearPatternAlphabet.h" + +namespace tree { + +class UnrankedNode; +class UnrankedPattern; + +/** + * Represents regular expression parsed from the XML. Regular expression is stored + * as a pattern of RegExpElement. + */ +class UnrankedNonlinearPattern : public UnrankedTreeBase, public UnrankedNonlinearPatternAlphabet { +protected: + UnrankedNode * pattern; + +public: + /** + * @copydoc UnrankedNode::clone() const + */ + virtual UnrankedTreeBase * clone ( ) const; + + /** + * @copydoc UnrankedNode::plunder() const + */ + virtual UnrankedTreeBase * plunder ( ) &&; + + explicit UnrankedNonlinearPattern ( alphabet::Symbol subtreeWildcard, std::set < alphabet::Symbol > nonlinearVariables, std::set < alphabet::Symbol > alphabet, UnrankedNode pattern ); + explicit UnrankedNonlinearPattern ( alphabet::Symbol subtreeWildcard, std::set < alphabet::Symbol > nonlinearVariables, UnrankedNode pattern ); + explicit UnrankedNonlinearPattern ( alphabet::Symbol subtreeWildcard, UnrankedNode pattern ); + + /** + * Copy constructor. + * @param other pattern to copy + */ + UnrankedNonlinearPattern ( const UnrankedNonlinearPattern & other ); + UnrankedNonlinearPattern ( UnrankedNonlinearPattern && other ) noexcept; + UnrankedNonlinearPattern & operator =( const UnrankedNonlinearPattern & other ); + UnrankedNonlinearPattern & operator =( UnrankedNonlinearPattern && other ) noexcept; + ~UnrankedNonlinearPattern ( ) noexcept; + + /** + * @return Root node of the regular expression pattern + */ + const UnrankedNode & getRoot ( ) const; + + const std::set < alphabet::Symbol > & getAlphabet ( ) const { + return UnrankedNonlinearPatternAlphabet::getAlphabet ( ); + } + + void extendAlphabet ( const std::set < alphabet::Symbol > & symbols ) { + addSymbolsToAlphabet ( symbols ); + } + + /** + * @return Root node of the regular expression pattern + */ + UnrankedNode & getRoot ( ); + + /** + * Sets the root node of the regular expression pattern + * @param pattern root node to set + */ + void setTree ( UnrankedNode pattern ); + + /** + * Removes symbol from the alphabet of symbol available in the regular expression + * @param symbol removed symbol from the alphabet + */ + bool removeSymbolFromAlphabet ( const alphabet::Symbol & symbol ); + + /** + * Prints XML representation of the pattern to the output stream. + * @param out output stream to which print the pattern + * @param pattern pattern to print + */ + virtual void operator >>( std::ostream & out ) const; + + virtual int compare ( const ObjectBase & other ) const { + if ( std::type_index ( typeid ( * this ) ) == std::type_index ( typeid ( other ) ) ) return this->compare ( ( decltype ( * this ) )other ); + + return std::type_index ( typeid ( * this ) ) - std::type_index ( typeid ( other ) ); + } + + virtual int compare ( const UnrankedNonlinearPattern & other ) const; + + void nicePrint ( std::ostream & os ) const; + + virtual explicit operator std::string ( ) const; + + const static std::string XML_TAG_NAME; + + static UnrankedNonlinearPattern parse ( std::deque < sax::Token >::iterator & input ); + + void compose ( std::deque < sax::Token > & out ) const; +}; + +} /* namespace tree */ + +namespace std { + +template < > +struct compare < tree::UnrankedNonlinearPattern > { + int operator ()( const tree::UnrankedNonlinearPattern & first, const tree::UnrankedNonlinearPattern & second ) const { + return first.compare ( second ); + } + +}; + +} /* namespace std */ + +#endif /* UNRANKED_NONLINEAR_PATTERN_H_ */ -- GitLab