Skip to content
Snippets Groups Projects
Commit 0fbb3030 authored by Jan Trávníček's avatar Jan Trávníček
Browse files

NFA String parser and composer

parent 37d302bb
No related branches found
No related tags found
No related merge requests found
...@@ -122,7 +122,40 @@ EpsilonNFA FiniteAutomatonFromStringParser::parseEpsilonNFA() { ...@@ -122,7 +122,40 @@ EpsilonNFA FiniteAutomatonFromStringParser::parseEpsilonNFA() {
NFA FiniteAutomatonFromStringParser::parseNFA() { NFA FiniteAutomatonFromStringParser::parseNFA() {
NFA res; NFA res;
   
return res; FiniteAutomatonFromStringLexer::Token token = m_FiniteAutomatonLexer.token();
if(token.type != FiniteAutomatonFromStringLexer::TokenType::NFA) {
throw alib::AlibException();
}
std::vector<alphabet::Symbol> symbols;
next() || m_SymbolParser.first() || m_SymbolParser.m_LabelParser.first();
token = m_FiniteAutomatonLexer.token();
while(token.type != FiniteAutomatonFromStringLexer::TokenType::NEW_LINE) {
alphabet::Symbol symbol = m_SymbolParser.parse();
res.addInputSymbol(symbol);
symbols.push_back(symbol);
next() || m_SymbolParser.first() || m_SymbolParser.m_LabelParser.first();
token = m_FiniteAutomatonLexer.token();
}
token = m_FiniteAutomatonLexer.token();
if(token.type != FiniteAutomatonFromStringLexer::TokenType::NEW_LINE) throw alib::AlibException();
next() || m_LabelParser.first();
parseNFATransition(res, symbols);
token = m_FiniteAutomatonLexer.token();
while(token.type == FiniteAutomatonFromStringLexer::TokenType::NEW_LINE) {
next() || m_LabelParser.first();
token = m_FiniteAutomatonLexer.token();
if(token.type == FiniteAutomatonFromStringLexer::TokenType::TEOF) break;
parseNFATransition(res, symbols);
token = m_FiniteAutomatonLexer.token();
}
return res;
} }
   
DFA FiniteAutomatonFromStringParser::parseDFA() { DFA FiniteAutomatonFromStringParser::parseDFA() {
...@@ -190,4 +223,62 @@ void FiniteAutomatonFromStringParser::parseEpsilonNFATransition(EpsilonNFA& res, ...@@ -190,4 +223,62 @@ void FiniteAutomatonFromStringParser::parseEpsilonNFATransition(EpsilonNFA& res,
if(iter != symbols.end()) throw alib::AlibException(); if(iter != symbols.end()) throw alib::AlibException();
} }
   
void FiniteAutomatonFromStringParser::parseNFATransition(NFA& res, const std::vector<alphabet::Symbol>& symbols) {
bool initial = false;
bool final = false;
FiniteAutomatonFromStringLexer::Token token = m_FiniteAutomatonLexer.token();
if(token.type == FiniteAutomatonFromStringLexer::TokenType::IN) {
initial = true;
next() || m_LabelParser.first();
token = m_FiniteAutomatonLexer.token();
if(token.type == FiniteAutomatonFromStringLexer::TokenType::OUT) {
final = true;
next() || m_LabelParser.first();
}
} else if(token.type == FiniteAutomatonFromStringLexer::TokenType::OUT) {
final = true;
next() || m_LabelParser.first();
token = m_FiniteAutomatonLexer.token();
if(token.type == FiniteAutomatonFromStringLexer::TokenType::IN) {
initial = true;
next() || m_LabelParser.first();
}
}
State from(m_LabelParser.parse());
res.addState(from);
if(initial) res.addInitialState(from);
if(final) res.addFinalState(from);
next() || m_LabelParser.first();
std::vector<alphabet::Symbol>::const_iterator iter = symbols.begin();
do {
if(iter == symbols.end()) throw alib::AlibException();
token = m_FiniteAutomatonLexer.token();
if(token.type != FiniteAutomatonFromStringLexer::TokenType::NONE) {
do {
State to(m_LabelParser.parse());
res.addState(to);
res.addTransition(from, *iter, to);
next() || m_LabelParser.first();
token = m_FiniteAutomatonLexer.token();
if(token.type != FiniteAutomatonFromStringLexer::TokenType::SEPARATOR) break;
next() || m_LabelParser.first();
} while(true);
} else {
next() || m_LabelParser.first();
token = m_FiniteAutomatonLexer.token();
}
iter++;
} while(token.type != FiniteAutomatonFromStringLexer::TokenType::NEW_LINE);
if(iter != symbols.end()) throw alib::AlibException();
}
} /* namespace automaton */ } /* namespace automaton */
...@@ -27,8 +27,8 @@ class FiniteAutomatonFromStringParser { ...@@ -27,8 +27,8 @@ class FiniteAutomatonFromStringParser {
NFA parseNFA(); NFA parseNFA();
DFA parseDFA(); DFA parseDFA();
void parseEpsilonNFATransition(EpsilonNFA& res, const std::vector<std::variant<string::Epsilon, alphabet::Symbol> >& symbols); void parseEpsilonNFATransition(EpsilonNFA& res, const std::vector<std::variant<string::Epsilon, alphabet::Symbol> >& symbols);
void parseNFATransition(NFA& res, const std::vector<alphabet::Symbol> symbols); void parseNFATransition(NFA& res, const std::vector<alphabet::Symbol>& symbols);
void parseDFATransition(DFA& res, const std::vector<alphabet::Symbol> symbols); void parseDFATransition(DFA& res, const std::vector<alphabet::Symbol>& symbols);
public: public:
FiniteAutomatonFromStringParser(std::stringstream& input); FiniteAutomatonFromStringParser(std::stringstream& input);
   
......
...@@ -6,6 +6,24 @@ ...@@ -6,6 +6,24 @@
   
namespace automaton { namespace automaton {
   
void FiniteAutomatonToStringComposer::composeTransitionsFromState(std::stringstream& out, const NFA& automaton, const State& from) const {
std::map<std::pair<State, alphabet::Symbol>, std::set<State> > symbolTransitionsFromState = automaton.getTransitionsFromState(from);
for(const alphabet::Symbol& inputSymbol : automaton.getInputAlphabet()) {
const std::map<std::pair<State, alphabet::Symbol>, std::set<State> >::iterator toStates = symbolTransitionsFromState.find(std::make_pair(from, inputSymbol));
if(toStates == symbolTransitionsFromState.end() || toStates->second.size() == 0) {
out << " -";
} else {
bool sign = false;
for(const State& to : toStates->second) {
label::LabelToStringComposer composer;
out << (sign ? "|" : " ") << composer.compose(to.getName());
sign = true;
}
}
}
}
void FiniteAutomatonToStringComposer::composeTransitionsFromState(std::stringstream& out, const EpsilonNFA& automaton, const State& from) const { void FiniteAutomatonToStringComposer::composeTransitionsFromState(std::stringstream& out, const EpsilonNFA& automaton, const State& from) const {
std::map<std::pair<State, alphabet::Symbol>, std::set<State> > symbolTransitionsFromState = automaton.getSymbolTransitionsFromState(from); std::map<std::pair<State, alphabet::Symbol>, std::set<State> > symbolTransitionsFromState = automaton.getSymbolTransitionsFromState(from);
   
...@@ -46,6 +64,28 @@ std::string FiniteAutomatonToStringComposer::compose(const DFA& automaton) const ...@@ -46,6 +64,28 @@ std::string FiniteAutomatonToStringComposer::compose(const DFA& automaton) const
std::string FiniteAutomatonToStringComposer::compose(const NFA& automaton) const { std::string FiniteAutomatonToStringComposer::compose(const NFA& automaton) const {
std::stringstream out; std::stringstream out;
   
out << "NFA";
for(auto iterSymbol = automaton.getInputAlphabet().begin(); iterSymbol != automaton.getInputAlphabet().end(); iterSymbol++) {
alphabet::SymbolToStringComposer composer;
out << " " << composer.compose(*iterSymbol);
}
out << std::endl;
for(auto iterState = automaton.getStates().begin(); iterState != automaton.getStates().end(); iterState++) {
if(automaton.getInitialStates().find(*iterState) != automaton.getInitialStates().end()) {
out << ">";
}
if(automaton.getFinalStates().find(*iterState) != automaton.getFinalStates().end()) {
out << "<";
}
label::LabelToStringComposer composer;
out << composer.compose(iterState->getName());
composeTransitionsFromState(out, automaton, *iterState);
out << std::endl;
}
   
return out.str(); return out.str();
} }
......
...@@ -20,6 +20,7 @@ class FiniteAutomatonToStringComposer : public AutomatonBase::const_visitor_type ...@@ -20,6 +20,7 @@ class FiniteAutomatonToStringComposer : public AutomatonBase::const_visitor_type
void Visit(void*, const PDA& automaton) const; void Visit(void*, const PDA& automaton) const;
void Visit(void*, const OneTapeDTM& automaton) const; void Visit(void*, const OneTapeDTM& automaton) const;
   
void composeTransitionsFromState(std::stringstream& out, const NFA& automaton, const State& from) const;
void composeTransitionsFromState(std::stringstream& out, const EpsilonNFA& automaton, const State& from) const; void composeTransitionsFromState(std::stringstream& out, const EpsilonNFA& automaton, const State& from) const;
   
public: public:
......
...@@ -89,26 +89,52 @@ void AutomatonTest::testDFAParser() { ...@@ -89,26 +89,52 @@ void AutomatonTest::testDFAParser() {
} }
   
void AutomatonTest::FSMStringParserTest() { void AutomatonTest::FSMStringParserTest() {
std::string input = "ENFA a b c d #E\n" {
">0 3|4 5 1|3|4 - 2\n" std::string input = "ENFA a b c d #E\n"
"1 2 - - - -\n" ">0 3|4 5 1|3|4 - 2\n"
"2 3 - - - -\n" "1 2 - - - -\n"
"3 - - 4 - -\n" "2 3 - - - -\n"
"4 - 5 - - 5\n" "3 - - 4 - -\n"
"<5 - - - - 3\n"; "4 - 5 - - 5\n"
std::stringstream inputs(input); "<5 - - - - 3\n";
std::stringstream inputs(input);
automaton::FiniteAutomatonFromStringParser parser(inputs);
automaton::Automaton automaton = parser.parseValue(); automaton::FiniteAutomatonFromStringParser parser(inputs);
automaton::Automaton automaton = parser.parseValue();
automaton::FiniteAutomatonToStringComposer composer;
std::string output = composer.compose(automaton); automaton::FiniteAutomatonToStringComposer composer;
std::stringstream outputs(output); std::string output = composer.compose(automaton);
std::stringstream outputs(output);
CPPUNIT_ASSERT( input == output );
CPPUNIT_ASSERT( input == output );
automaton::FiniteAutomatonFromStringParser parser2(outputs);
automaton::Automaton automaton2 = parser2.parseValue(); automaton::FiniteAutomatonFromStringParser parser2(outputs);
automaton::Automaton automaton2 = parser2.parseValue();
CPPUNIT_ASSERT( automaton == automaton2 );
CPPUNIT_ASSERT( automaton == automaton2 );
}
{
std::string input = "NFA a b c d\n"
">0 3|4 5 1|3|4 -\n"
"1 2 - - -\n"
"2 3 - - -\n"
"3 - - 4 -\n"
"4 - 5 - -\n"
"<5 - - - 3\n";
std::stringstream inputs(input);
automaton::FiniteAutomatonFromStringParser parser(inputs);
automaton::Automaton automaton = parser.parseValue();
automaton::FiniteAutomatonToStringComposer composer;
std::string output = composer.compose(automaton);
std::stringstream outputs(output);
CPPUNIT_ASSERT( input == output );
automaton::FiniteAutomatonFromStringParser parser2(outputs);
automaton::Automaton automaton2 = parser2.parseValue();
CPPUNIT_ASSERT( automaton == automaton2 );
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment