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_ */