-
Jan Trávníček authoredJan Trávníček authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ExactPatternMatchingAutomaton.cpp 11.73 KiB
/*
* ExactPatternMatchingAutomaton.cpp
*
* Created on: 9. 2. 2014
* Author: Jan Travnicek
*/
#include "ExactPatternMatchingAutomaton.h"
#include "ExactSubtreeMatchingAutomaton.h"
#include "SubtreeJumpTable.h"
#include <tree/ranked/RankedTree.h>
#include <tree/ranked/RankedPattern.h>
#include <tree/ranked/PrefixRankedTree.h>
#include <tree/ranked/PrefixRankedPattern.h>
#include <tree/ranked/PrefixRankedBarTree.h>
#include <tree/ranked/PrefixRankedBarPattern.h>
#include <automaton/PDA/InputDrivenNPDA.h>
#include <automaton/PDA/VisiblyPushdownNPDA.h>
#include <automaton/PDA/NPDA.h>
#include <automaton/TA/NFTA.h>
#include <alphabet/BottomOfTheStackSymbol.h>
#include <deque>
#include <alphabet/RankedSymbol.h>
namespace arbology {
namespace exact {
automaton::Automaton ExactPatternMatchingAutomaton::construct ( const tree::Tree & pattern ) {
return dispatch ( pattern.getData ( ) );
}
automaton::InputDrivenNPDA < > ExactPatternMatchingAutomaton::construct ( const tree::PrefixRankedTree < > & pattern ) {
return ExactSubtreeMatchingAutomaton::construct ( pattern );
}
auto ExactPatternMatchingAutomatonPrefixRankedTree = ExactPatternMatchingAutomaton::RegistratorWrapper < automaton::InputDrivenNPDA < >, tree::PrefixRankedTree < > > ( ExactPatternMatchingAutomaton::construct );
std::vector < alphabet::Symbol > computeRHS ( const tree::PrefixRankedPattern < > & pattern, const std::vector < int > & patternSubtreeJumpTable, int i ) {
const std::vector < std::ranked_symbol < > > & content = pattern.getContent ( );
unsigned rank = content[i].getRank ( ).getData ( );
i++;
std::vector < alphabet::Symbol > res;
for ( unsigned ranki = 0; ranki < rank; ranki++ ) {
if ( content[i] == pattern.getSubtreeWildcard ( ) ) {
res.push_back ( alphabet::symbolFrom ( 'R' ) );
i++;
} else {
res.push_back ( alphabet::symbolFrom ( 'T' ) );
i = patternSubtreeJumpTable[i];
}
}
return res;
}
automaton::NPDA < > ExactPatternMatchingAutomaton::construct ( const tree::PrefixRankedPattern < > & pattern ) {
automaton::NPDA < > res ( label::labelFrom ( 0 ), alphabet::symbolFrom ( 'T' ) );
for ( const std::ranked_symbol < > & symbol : pattern.getAlphabet ( ) ) {
if ( symbol == pattern.getSubtreeWildcard ( ) ) continue;
res.addInputSymbol ( alphabet::Symbol ( alphabet::RankedSymbol < > { symbol } ) );
}
res.setPushdownStoreAlphabet ( { alphabet::symbolFrom ( 'T' ), alphabet::symbolFrom ( 'R' ) } );
for ( const std::ranked_symbol < > & symbol : pattern.getAlphabet ( ) ) {
if ( symbol == pattern.getSubtreeWildcard ( ) ) continue;
res.addTransition ( label::labelFrom ( 0 ), alphabet::Symbol ( alphabet::RankedSymbol < > { symbol } ), std::vector < alphabet::Symbol > ( 1, alphabet::symbolFrom ( 'T' ) ), label::labelFrom ( 0 ), std::vector < alphabet::Symbol > ( symbol.getRank ( ).getData ( ), alphabet::symbolFrom ( 'T' ) ) );
}
std::vector < int > patternSubtreeJumpTable = SubtreeJumpTable::compute ( pattern );
int i = 1;
for ( const std::ranked_symbol < > & symbol : pattern.getContent ( ) ) {
res.addState ( label::labelFrom ( i ) );
if ( symbol == pattern.getSubtreeWildcard ( ) )
for ( const std::ranked_symbol < > & symbol : pattern.getAlphabet ( ) ) {
if ( symbol == pattern.getSubtreeWildcard ( ) ) continue;
if ( symbol.getRank ( ).getData ( ) == 0 ) {
res.addTransition ( label::labelFrom ( i - 1 ), alphabet::Symbol ( alphabet::RankedSymbol < > { symbol } ), std::vector < alphabet::Symbol > ( 1, alphabet::symbolFrom ( 'T' ) ), label::labelFrom ( i - 1 ), std::vector < alphabet::Symbol > { } );
res.addTransition ( label::labelFrom ( i - 1 ), alphabet::Symbol ( alphabet::RankedSymbol < > { symbol } ), std::vector < alphabet::Symbol > ( 1, alphabet::symbolFrom ( 'R' ) ), label::labelFrom ( i ), std::vector < alphabet::Symbol > { } );
} else {
std::vector < alphabet::Symbol > push ( symbol.getRank ( ).getData ( ), alphabet::symbolFrom ( 'T' ) );
res.addTransition ( label::labelFrom ( i - 1 ), alphabet::Symbol ( alphabet::RankedSymbol < > { symbol } ), std::vector < alphabet::Symbol > ( 1, alphabet::symbolFrom ( 'T' ) ), label::labelFrom ( i - 1 ), push );
push[symbol.getRank ( ).getData ( ) - 1] = alphabet::symbolFrom ( 'R' );
res.addTransition ( label::labelFrom ( i - 1 ), alphabet::Symbol ( alphabet::RankedSymbol < > { symbol } ), std::vector < alphabet::Symbol > ( 1, alphabet::symbolFrom ( 'R' ) ), label::labelFrom ( i - 1 ), push );
}
}
else
res.addTransition ( label::labelFrom ( i - 1 ), alphabet::Symbol ( alphabet::RankedSymbol < > { symbol } ), std::vector < alphabet::Symbol > ( 1, alphabet::symbolFrom ( 'T' ) ), label::labelFrom ( i ), computeRHS ( pattern, patternSubtreeJumpTable, i - 1 ) );
i++;
}
res.addFinalState ( label::labelFrom ( i - 1 ) );
return res;
}
auto ExactPatternMatchingAutomatonPrefixRankedPattern = ExactPatternMatchingAutomaton::RegistratorWrapper < automaton::NPDA < >, tree::PrefixRankedPattern < > > ( ExactPatternMatchingAutomaton::construct );
automaton::InputDrivenNPDA < > ExactPatternMatchingAutomaton::construct ( const tree::PrefixRankedBarTree < > & pattern ) {
return ExactSubtreeMatchingAutomaton::construct ( pattern );
}
auto ExactPatternMatchingAutomatonPrefixRankedBarTree = ExactPatternMatchingAutomaton::RegistratorWrapper < automaton::InputDrivenNPDA < >, tree::PrefixRankedBarTree < > > ( ExactPatternMatchingAutomaton::construct );
automaton::VisiblyPushdownNPDA < > ExactPatternMatchingAutomaton::construct ( const tree::PrefixRankedBarPattern & pattern ) {
automaton::VisiblyPushdownNPDA < > res ( alphabet::Symbol { alphabet::BottomOfTheStackSymbol::BOTTOM_OF_THE_STACK } );
res.addState ( label::labelFrom ( 0 ) );
res.addInitialState ( label::labelFrom ( 0 ) );
for ( const std::ranked_symbol < > & symbol : pattern.getAlphabet ( ) ) {
if ( ( symbol == pattern.getSubtreeWildcard ( ) ) || ( symbol == pattern.getVariablesBar ( ) ) ) continue;
if ( pattern.getBars ( ).count ( symbol ) )
res.addReturnInputSymbol ( alphabet::Symbol ( alphabet::RankedSymbol < > { symbol } ) );
else
res.addCallInputSymbol ( alphabet::Symbol ( alphabet::RankedSymbol < > { symbol } ) );
}
res.setPushdownStoreAlphabet ( { alphabet::Symbol { alphabet::BottomOfTheStackSymbol::BOTTOM_OF_THE_STACK }, alphabet::symbolFrom ( 'T' ), alphabet::symbolFrom ( 'R' ) } );
for ( const std::ranked_symbol < > & symbol : pattern.getAlphabet ( ) ) {
if ( ( symbol == pattern.getSubtreeWildcard ( ) ) || ( symbol == pattern.getVariablesBar ( ) ) ) continue;
if ( pattern.getBars ( ).count ( symbol ) )
res.addReturnTransition ( label::labelFrom ( 0 ), alphabet::Symbol ( alphabet::RankedSymbol < > { symbol } ), alphabet::symbolFrom ( 'T' ), label::labelFrom ( 0 ) );
else
res.addCallTransition ( label::labelFrom ( 0 ), alphabet::Symbol ( alphabet::RankedSymbol < > { symbol } ), label::labelFrom ( 0 ), alphabet::symbolFrom ( 'T' ) );
}
int i = 1;
for ( const std::ranked_symbol < > & symbol : pattern.getContent ( ) ) {
res.addState ( label::labelFrom ( i ) );
if ( symbol == pattern.getSubtreeWildcard ( ) ) {
for ( const std::ranked_symbol < > & symbol : pattern.getAlphabet ( ) ) {
if ( ( symbol == pattern.getSubtreeWildcard ( ) ) || ( symbol == pattern.getVariablesBar ( ) ) || ( pattern.getBars ( ).count ( symbol ) ) ) continue;
res.addCallTransition ( label::labelFrom ( i - 1 ), alphabet::Symbol ( alphabet::RankedSymbol < > { symbol } ), label::labelFrom ( i ), alphabet::symbolFrom ( 'R' ) );
}
} else if ( symbol == pattern.getVariablesBar ( ) ) {
for ( const std::ranked_symbol < > & symbol : pattern.getAlphabet ( ) ) {
if ( ( symbol == pattern.getSubtreeWildcard ( ) ) || ( symbol == pattern.getVariablesBar ( ) ) ) continue;
if ( pattern.getBars ( ).count ( symbol ) )
res.addReturnTransition ( label::labelFrom ( i - 1 ), alphabet::Symbol ( alphabet::RankedSymbol < > { symbol } ), alphabet::symbolFrom ( 'T' ), label::labelFrom ( i - 1 ) );
else
res.addCallTransition ( label::labelFrom ( i - 1 ), alphabet::Symbol ( alphabet::RankedSymbol < > { symbol } ), label::labelFrom ( i - 1 ), alphabet::symbolFrom ( 'T' ) );
}
for ( const std::ranked_symbol < > & symbol : pattern.getAlphabet ( ) ) {
if ( ( symbol == pattern.getSubtreeWildcard ( ) ) || ( symbol == pattern.getVariablesBar ( ) ) || ( ! pattern.getBars ( ).count ( symbol ) ) ) continue;
res.addReturnTransition ( label::labelFrom ( i - 1 ), alphabet::Symbol ( alphabet::RankedSymbol < > { symbol } ), alphabet::symbolFrom ( 'R' ), label::labelFrom ( i ) );
}
} else if ( pattern.getBars ( ).count ( symbol ) ) {
res.addReturnTransition ( label::labelFrom ( i - 1 ), alphabet::Symbol ( alphabet::RankedSymbol < > { symbol } ), alphabet::symbolFrom ( 'T' ), label::labelFrom ( i ) );
} else {
res.addCallTransition ( label::labelFrom ( i - 1 ), alphabet::Symbol ( alphabet::RankedSymbol < > { symbol } ), label::labelFrom ( i ), alphabet::symbolFrom ( 'T' ) );
}
i++;
}
res.addFinalState ( label::labelFrom ( i - 1 ) );
return res;
}
auto ExactPatternMatchingAutomatonPrefixRankedBarPattern = ExactPatternMatchingAutomaton::RegistratorWrapper < automaton::VisiblyPushdownNPDA < >, tree::PrefixRankedBarPattern > ( ExactPatternMatchingAutomaton::construct );
automaton::NFTA ExactPatternMatchingAutomaton::construct ( const tree::RankedTree < > & pattern ) {
return ExactSubtreeMatchingAutomaton::construct ( pattern );
}
auto ExactPatternMatchingAutomatonRankedTree = ExactPatternMatchingAutomaton::RegistratorWrapper < automaton::NFTA, tree::RankedTree < > > ( ExactPatternMatchingAutomaton::construct );
label::Label constructRecursivePattern ( const std::tree < std::ranked_symbol < > > & node, automaton::NFTA & res, const std::ranked_symbol < > & subtreeWildcard, const label::Label & loopState, int & nextState ) {
if ( node.getData ( ) == subtreeWildcard ) {
label::Label state = label::labelFrom ( nextState++ );
res.addState ( state );
for ( const std::ranked_symbol < > & symbol : res.getInputAlphabet ( ) ) {
std::vector < label::Label > states;
states.reserve ( symbol.getRank ( ).getData ( ) );
for ( unsigned i = 0; i < symbol.getRank ( ).getData ( ); i++ )
states.push_back ( loopState );
res.addTransition ( symbol, states, state );
}
return state;
} else {
std::vector < label::Label > states;
states.reserve ( node.getData ( ).getRank ( ).getData ( ) );
for ( const std::tree < std::ranked_symbol < > > & child : node.getChildren ( ) )
states.push_back ( constructRecursivePattern ( child, res, subtreeWildcard, loopState, nextState ) );
label::Label state = label::labelFrom ( nextState++ );
res.addState ( state );
res.addTransition ( node.getData ( ), states, state );
return state;
}
}
automaton::NFTA ExactPatternMatchingAutomaton::construct ( const tree::RankedPattern < > & pattern ) {
std::set < std::ranked_symbol < > > alphabet = pattern.getAlphabet ( );
alphabet.erase ( pattern.getSubtreeWildcard ( ) );
automaton::NFTA res;
res.setInputAlphabet ( alphabet );
int nextState = 0;
label::Label loopState = label::labelFrom ( nextState++ );
res.addState ( loopState );
for ( const std::ranked_symbol < > & symbol : res.getInputAlphabet ( ) ) {
std::vector < label::Label > states;
states.reserve ( symbol.getRank ( ).getData ( ) );
for ( unsigned i = 0; i < symbol.getRank ( ).getData ( ); i++ )
states.push_back ( loopState );
res.addTransition ( symbol, states, loopState );
}
res.addFinalState ( constructRecursivePattern ( pattern.getContent ( ), res, pattern.getSubtreeWildcard ( ), loopState, nextState ) );
return res;
}
auto ExactPatternMatchingAutomatonRankedPattern = ExactPatternMatchingAutomaton::RegistratorWrapper < automaton::NFTA, tree::RankedPattern < > > ( ExactPatternMatchingAutomaton::construct );
} /* namespace exact */
} /* namespace arbology */