diff --git a/Language/public/ContextFreeAutomata.hpp b/Language/public/ContextFreeAutomata.hpp index e9a0b9f..d4bd6e7 100644 --- a/Language/public/ContextFreeAutomata.hpp +++ b/Language/public/ContextFreeAutomata.hpp @@ -39,37 +39,39 @@ namespace tp { while (advancedIdx < size) { tAlphabetType& symbol = *(stream + advancedIdx); - const Action& action = mTable.get({ ualni(symbol), mCurrentState }); + if (!(symbol >= mRange.mBegin && symbol < mRange.mEnd)) { + return { false, advancedIdx, nullptr }; + } - switch (action.type) { - case Action::TRAP: return { false, advancedIdx, nullptr }; - case Action::REDUCE: - { - StackItem* newItem = &mItems.append({}); - for (auto iter : Range(action.num)) { - newItem->leafs.append(mStack.last()); - mCurrentState = mStack.last()->state; - mStack.pop(); - } + const Action& action = mTable.get({ ualni(symbol - mRange.mBegin), mCurrentState }); - if (!mStack.size()) { - if (advancedIdx == size) { - return { true, advancedIdx, newItem }; - } else { - return { false, advancedIdx, {} }; - } - } + if (action.type == Action::TRAP) { + return { false, advancedIdx, nullptr }; + } - mStack.append(&mItems.append({ mCurrentState, {}, {} })); - break; - } - case Action::SHIFT: - { - mStack.last()->symbol = symbol; - mStack.append(&mItems.append({ mCurrentState, {}, {} })); - mCurrentState = action.num; - break; + if (action.type == Action::SHIFT) { + mStack.last()->symbol = symbol; + mStack.append(&mItems.append({ mCurrentState, {}, {} })); + mCurrentState = action.num; + } + + if (mTable.get({ 0, mCurrentState }).type == Action::REDUCE) { + StackItem* newItem = &mItems.append({}); + for (auto iter : Range(action.num)) { + newItem->leafs.append(mStack.last()); + mCurrentState = mStack.last()->state; + mStack.pop(); + } + + if (!mStack.size()) { + if (advancedIdx == size) { + return { true, advancedIdx, newItem }; + } else { + return { false, advancedIdx, {} }; } + } + + mStack.append(&mItems.append({ mCurrentState, {}, {} })); } advancedIdx++; @@ -79,7 +81,47 @@ namespace tp { } public: - void construct(const FiniteStateAutomation& automata) {} + typedef FiniteStateAutomation Automata; + typedef Automata::State AutomataState; + + void construct(const Automata& automata) { + mRange = automata.getAlphabetRange(); + + const ualni numStates = automata.numStates(); + const ualni numSymbols = mRange.idxDiff(); + + mTable.reserve({ numSymbols, numStates }); + mTable.assign(Action{ Action::TRAP, 0 }); + + Map states; + ualni stateIndex = 0; + for (auto state : *automata.getStates()) { + states.put(state.data(), { stateIndex }); + stateIndex++; + } + + stateIndex = 0; + for (auto state : *automata.getStates()) { + if (state.data() == automata.getStartState()) { + mStartState = stateIndex; + } + + if (state->isAccepting()) { + ASSERT(state->getTransitions().size() == 0) + for (auto symbolIndex : Range(numSymbols)) { + mTable.set({ stateIndex, symbolIndex }, { Action::REDUCE, state->getStateVal() }); + } + } else { + for (auto transition : *state->getTransitions()) { + ualni symbolIndex = ualni(transition->getSymbol()) - mRange.mBegin; + ualni targetStateIndex = states.get(transition->getState()); + mTable.set({ stateIndex, symbolIndex }, { Action::SHIFT, targetStateIndex }); + } + } + + stateIndex++; + } + } private: Buffer2D mTable; @@ -89,5 +131,7 @@ namespace tp { ualni mStartState = 0; ualni mCurrentState = 0; + + Range mRange = { 0, 0 }; }; }