cfg accepting

This commit is contained in:
IlyaShurupov 2024-02-08 11:30:15 +03:00 committed by Ilya Shurupov
parent 2ebf650381
commit 7a685e0634
2 changed files with 95 additions and 17 deletions

View file

@ -15,11 +15,79 @@ namespace tp {
ualni num = 0; // state to shift (shift action) or pop count (reduce action) ualni num = 0; // state to shift (shift action) or pop count (reduce action)
}; };
Buffer2D<Action> mTable; public:
struct StackItem {
ualni state = 0;
tAlphabetType symbol;
Buffer<StackItem*> leafs;
};
struct AcceptResult {
bool accepted = false;
ualni advancedIdx = 0;
const StackItem* ast = nullptr;
};
public: public:
ContextFreeAutomata() = default; ContextFreeAutomata() = default;
AcceptResult accept(const tAlphabetType* stream, ualni size) {
mCurrentState = mStartState;
mStack.append(&mItems.append({ mCurrentState, {}, {} }));
ualni advancedIdx = 0;
while (advancedIdx < size) {
tAlphabetType& symbol = *(stream + advancedIdx);
const Action& action = mTable.get({ ualni(symbol), mCurrentState });
switch (action.type) {
case Action::TRAP: return { false, advancedIdx, nullptr };
case Action::REDUCE:
{
StackItem* newItem = &mItems.append({});
for (auto iter : Range<ualni>(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, {}, {} }));
break;
}
case Action::SHIFT:
{
mStack.last()->symbol = symbol;
mStack.append(&mItems.append({ mCurrentState, {}, {} }));
mCurrentState = action.num;
break;
}
}
advancedIdx++;
}
return { false, advancedIdx, nullptr };
}
public:
void construct(const FiniteStateAutomation<tAlphabetType, tStateType>& automata) {} void construct(const FiniteStateAutomation<tAlphabetType, tStateType>& automata) {}
private:
Buffer2D<Action> mTable;
Buffer<StackItem> mItems;
Buffer<StackItem*> mStack;
ualni mStartState = 0;
ualni mCurrentState = 0;
}; };
} }

View file

@ -7,21 +7,19 @@
namespace tp { namespace tp {
template <typename tAlphabetType, typename tStateType, tStateType tFailedStateVal> template <typename tAlphabetType, typename tStateType>
class RegularAutomata { class RegularAutomata {
public:
Buffer2D<ualni> mTable; struct AcceptResult {
Buffer<Pair<bool, tStateType>> mStates; bool accepted = false;
ualni advancedIdx = 0;
ualni mCurrentState = 0; tStateType state = tStateType();
ualni mStartState = 0; };
Range<tAlphabetType> mSymbolRange = { 0, 0 };
public: public:
RegularAutomata() = default; RegularAutomata() = default;
Pair<tStateType, ualni> accept(const tAlphabetType* stream, ualni size) { AcceptResult accept(const tAlphabetType* stream, ualni size) {
mCurrentState = mStartState; mCurrentState = mStartState;
ualni advancedIdx = 0; ualni advancedIdx = 0;
@ -30,28 +28,33 @@ namespace tp {
tAlphabetType& symbol = *(stream + advancedIdx); tAlphabetType& symbol = *(stream + advancedIdx);
if (!(symbol >= mSymbolRange.mBegin && symbol < mSymbolRange.mEnd)) { if (!(symbol >= mSymbolRange.mBegin && symbol < mSymbolRange.mEnd)) {
return { tFailedStateVal, advancedIdx }; return { false, advancedIdx, {} };
} }
mCurrentState = mTable.get({ (ualni) (symbol - mSymbolRange.mBegin), mCurrentState }); mCurrentState = mTable.get({ (ualni) (symbol - mSymbolRange.mBegin), mCurrentState });
if (mCurrentState == mStates.size()) {
return false;
}
if (mStates[mCurrentState].first) { if (mStates[mCurrentState].first) {
return { mStates[mCurrentState].second, advancedIdx }; return { true, advancedIdx, mStates[mCurrentState].second };
} }
advancedIdx++; advancedIdx++;
} }
return { tFailedStateVal, advancedIdx }; return { false, advancedIdx, {} };
} }
public:
void construct(const FiniteStateAutomation<tAlphabetType, tStateType>& automata) { void construct(const FiniteStateAutomation<tAlphabetType, tStateType>& automata) {
const auto range = automata.getAlphabetRange(); const auto range = automata.getAlphabetRange();
mSymbolRange = { tAlphabetType(range.mBegin), tAlphabetType(range.mEnd) }; mSymbolRange = { tAlphabetType(range.mBegin), tAlphabetType(range.mEnd) };
auto range_len = ualni(mSymbolRange.mEnd - mSymbolRange.mBegin); auto range_len = ualni(mSymbolRange.mEnd - mSymbolRange.mBegin);
auto sizeX = range_len ? range_len : 1; auto sizeX = range_len ? range_len : 1;
auto sizeY = (ualni) (automata.numStates() + 1); auto sizeY = (ualni) (automata.numStates());
mTable.reserve({ sizeX, sizeY }); mTable.reserve({ sizeX, sizeY });
mTable.assign(automata.numStates()); mTable.assign(automata.numStates());
@ -63,8 +66,6 @@ namespace tp {
idx++; idx++;
} }
mStates[automata.numStates()] = { true, tFailedStateVal };
idx = 0; idx = 0;
for (auto state : *automata.getStates()) { for (auto state : *automata.getStates()) {
if (&state.data() == automata.getStartState()) { if (&state.data() == automata.getStartState()) {
@ -87,5 +88,14 @@ namespace tp {
stateIdx++; stateIdx++;
} }
} }
private:
Buffer2D<ualni> mTable;
Buffer<Pair<bool, tStateType>> mStates;
ualni mCurrentState = 0;
ualni mStartState = 0;
Range<tAlphabetType> mSymbolRange = { 0, 0 };
}; };
} }