diff --git a/alib2algo/src/grammar/parsing/LR0Parser.cpp b/alib2algo/src/grammar/parsing/LR0Parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6571b73c2e000cc6a41bd3d3bc8bbd4e092d467a --- /dev/null +++ b/alib2algo/src/grammar/parsing/LR0Parser.cpp @@ -0,0 +1,67 @@ +/* + * LR0Parser.cpp + * + * Created on: 2. 5. 2016 + * Author: Martin Kocicka + */ + +#include "LR0Parser.h" + +#include "LRParser.h" + +#include <automaton/FSM/DFA.h> +#include <automaton/common/State.h> +#include <grammar/ContextFree/CFG.h> +#include <label/LR0ItemsLabel.h> + +#include <queue> + +namespace grammar { + +namespace parsing { + +automaton::DFA LR0Parser::getAutomaton ( grammar::CFG originalGrammar ) { + grammar::CFG augmentedGrammar = LRParser::getAugmentedGrammar ( originalGrammar ); + alphabet::Symbol initialSymbol = augmentedGrammar.getInitialSymbol ( ); + const std::map < alphabet::Symbol, std::set < std::vector < alphabet::Symbol > > > & rules = augmentedGrammar.getRules ( ); + + LR0Items initialItems; + initialItems[initialSymbol].insert ( { 0, *rules.find ( initialSymbol ) -> second.begin ( ) } ); + + automaton::State initialState ( label::Label ( label::LR0ItemsLabel ( LRParser::getClosure ( initialItems, augmentedGrammar ) ) ) ); + + automaton::DFA lr0Automaton ( initialState ); + lr0Automaton.addInputSymbols ( augmentedGrammar.getNonterminalAlphabet ( ) ); + lr0Automaton.addInputSymbols ( augmentedGrammar.getTerminalAlphabet ( ) ); + + std::queue < automaton::State > itemsToProcess; + itemsToProcess.push ( initialState ); + while ( !itemsToProcess.empty ( ) ) { + automaton::State currentState = itemsToProcess.front ( ); + label::LR0ItemsLabel & currentLabel = static_cast < label::LR0ItemsLabel & > ( currentState.getName ( ) . getData ( ) ); + itemsToProcess.pop ( ); + + for ( const alphabet::Symbol & symbol : lr0Automaton.getInputAlphabet ( ) ) { + LR0Items nextStateItems = LRParser::getNextStateItems ( currentLabel.getItems ( ), symbol, augmentedGrammar ); + if ( !nextStateItems.empty ( ) ) { + label::LR0ItemsLabel nextStateLabel ( nextStateItems ); + + automaton::State nextState ( ( label::Label ( nextStateLabel ) ) ); + std::set < automaton::State > ::iterator stateIterator = lr0Automaton.getStates ( ) . find ( nextState ); + if ( stateIterator == lr0Automaton.getStates ( ) . end ( ) ) { + lr0Automaton.addState ( nextState ); + lr0Automaton.addTransition ( currentState, symbol, nextState ); + itemsToProcess.push ( nextState ); + } else { + lr0Automaton.addTransition ( currentState, symbol, *stateIterator ); + } + } + } + } + + return lr0Automaton; +} + +} /* namespace parsing */ + +} /* namespace grammar */ diff --git a/alib2algo/src/grammar/parsing/LR0Parser.h b/alib2algo/src/grammar/parsing/LR0Parser.h new file mode 100644 index 0000000000000000000000000000000000000000..08b8010d9a751698ec29627d522395e7c0074bc0 --- /dev/null +++ b/alib2algo/src/grammar/parsing/LR0Parser.h @@ -0,0 +1,27 @@ +/* + * LR0Parser.h + * + * Created on: 2. 5. 2016 + * Author: Martin Kocicka + */ + +#ifndef LR_0_PARSER_H_ +#define LR_0_PARSER_H_ + +#include <automaton/FSM/DFA.h> +#include <grammar/ContextFree/CFG.h> + +namespace grammar { + +namespace parsing { + +class LR0Parser { +public: + static automaton::DFA getAutomaton ( grammar::CFG originalGrammar ); +}; + +} /* namespace parsing */ + +} /* namespace grammar */ + +#endif /* LR_0_PARSER_H_ */