86 lines
No EOL
1.6 KiB
C++
86 lines
No EOL
1.6 KiB
C++
#pragma once
|
|
#include <stack>
|
|
enum class IndentAction
|
|
{
|
|
Indent,
|
|
Dedent,
|
|
None
|
|
};
|
|
|
|
constexpr int TAB_WIDTH = 8;
|
|
constexpr char TAB = '\t';
|
|
|
|
class IndentStack
|
|
{
|
|
std::stack<int> indent_stack;
|
|
int dedent_queue = 0;
|
|
|
|
public:
|
|
IndentStack() { indent_stack.push(0); }
|
|
|
|
IndentAction updateIndentation(int spaces)
|
|
{
|
|
int current = indent_stack.top();
|
|
|
|
if (spaces == current)
|
|
{
|
|
return IndentAction::None;
|
|
}
|
|
|
|
if (spaces > current)
|
|
{
|
|
indent_stack.push(spaces);
|
|
return IndentAction::Indent;
|
|
}
|
|
|
|
while (!indent_stack.empty() && indent_stack.top() > spaces)
|
|
{
|
|
indent_stack.pop();
|
|
dedent_queue++;
|
|
}
|
|
|
|
if (dedent_queue > 0)
|
|
{
|
|
dedent_queue--;
|
|
return IndentAction::Dedent;
|
|
}
|
|
|
|
return IndentAction::None;
|
|
}
|
|
|
|
bool popDedent()
|
|
{
|
|
if (dedent_queue <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
dedent_queue--;
|
|
return true;
|
|
}
|
|
|
|
static int calculateColumn(const char *text, int length)
|
|
{
|
|
int spaces = 0;
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
if (text[i] == TAB)
|
|
{
|
|
spaces += TAB_WIDTH - (spaces % TAB_WIDTH);
|
|
continue;
|
|
}
|
|
spaces++;
|
|
}
|
|
return spaces;
|
|
}
|
|
|
|
bool hasRemainingDedents()
|
|
{
|
|
return dedent_queue > 0;
|
|
}
|
|
|
|
IndentAction closeBlock()
|
|
{
|
|
// Force indentation reset at EOF
|
|
return updateIndentation(0);
|
|
}
|
|
}; |