indention start

This commit is contained in:
bronku 2025-11-25 13:53:50 +01:00
parent 1c21aede4b
commit 5062a9b588
12 changed files with 268 additions and 48 deletions

65
src/indent_helper.hpp Normal file
View file

@ -0,0 +1,65 @@
#pragma once
#include <stack>
class IndentHelper
{
std::stack<int> indent_stack;
int pending_dedents = 0;
public:
IndentHelper() { indent_stack.push(0); }
int processLine(int spaces)
{
int current = indent_stack.top();
if (spaces > current)
{
indent_stack.push(spaces);
return 1;
}
if (spaces == current)
{
return 0;
}
pending_dedents = 0;
while (indent_stack.top() > spaces)
{
indent_stack.pop();
pending_dedents++;
}
if (indent_stack.top() != spaces)
{
throw std::runtime_error("Indentation error");
}
return -1;
}
bool hasPendingDedents() const
{
return pending_dedents > 0;
}
void consumePendingDedent()
{
if (pending_dedents > 0)
{
pending_dedents--;
}
}
int flushAllDedents()
{
int total_dedents = 0;
while (indent_stack.size() > 1)
{
indent_stack.pop();
total_dedents++;
}
return total_dedents;
}
};

View file

@ -5,28 +5,64 @@
%{
#include "scanner.hpp"
#include "indent_helper.hpp"
IndentHelper indent_helper;
bool at_line_start = true;
%}
%%
def { return yy::parser::token::TOK_KW_DEF;}
if { return yy::parser::token::TOK_KW_IF;}
return { return yy::parser::token::TOK_KW_RETURN;}
for { return yy::parser::token::TOK_KW_FOR;}
in { return yy::parser::token::TOK_KW_IF;}
\n { return yy::parser::token::TOK_NEWLINE; }
\( { return yy::parser::token::TOK_L_PAREN; }
\) { return yy::parser::token::TOK_R_PAREN; }
\: { return yy::parser::token::TOK_COLON; }
\= { return yy::parser::token::TOK_ASSIGN; }
\+ { return yy::parser::token::TOK_PLUS; }
\- { return yy::parser::token::TOK_MINUS; }
\" { yymore(); BEGIN(STRING); }
[0-9]+ { yylval->as<std::string>() = yytext; return yy::parser::token::TOK_NUMBER; }
[_a-zA-Z]+ { yylval->as<std::string>() = yytext; return yy::parser::token::TOK_IDENTIFIER; }
<<EOF>> { return yy::parser::token::TOK_EOF; }
. { /* the last rule, ignore anything else (there should be nothing) */}
<STRING>\"\" { yymore(); }
<STRING>\" { BEGIN(INITIAL); yylval->as<std::string>() = yytext; return yy::parser::token::TOK_STRING; }
<STRING>. { yymore(); }
%%
^[ \t]* {
if (!at_line_start) {
REJECT;
}
at_line_start = false;
int spaces = 0;
for (int i = 0; i < yyleng; i++)
spaces += (yytext[i] == '\t') ? 8 : 1;
int result = indent_helper.processLine(spaces);
if (result > 0) return yy::parser::token::TOK_INDENT;
if (result < 0) return yy::parser::token::TOK_DEDENT;
}
\n {
at_line_start = true;
return yy::parser::token::TOK_NEWLINE;
}
def { return yy::parser::token::TOK_KW_DEF; }
if { return yy::parser::token::TOK_KW_IF; }
return { return yy::parser::token::TOK_KW_RETURN; }
for { return yy::parser::token::TOK_KW_FOR; }
in { return yy::parser::token::TOK_KW_IN; }
\( { return yy::parser::token::TOK_L_PAREN; }
\) { return yy::parser::token::TOK_R_PAREN; }
\: { return yy::parser::token::TOK_COLON; }
\= { return yy::parser::token::TOK_ASSIGN; }
\+ { return yy::parser::token::TOK_PLUS; }
\- { return yy::parser::token::TOK_MINUS; }
\" { yymore(); BEGIN(STRING); }
<STRING>\"\" { yymore(); }
<STRING>\" { BEGIN(INITIAL); yylval->as<std::string>() = yytext; return yy::parser::token::TOK_STRING; }
<STRING>. { yymore(); }
[0-9]+ { yylval->as<std::string>() = yytext; return yy::parser::token::TOK_NUMBER; }
[A-Za-z_][A-Za-z0-9_]* { yylval->as<std::string>() = yytext; return yy::parser::token::TOK_IDENTIFIER; }
<<EOF>> {
if (indent_helper.hasPendingDedents()) {
indent_helper.consumeDedent();
return yy::parser::token::TOK_DEDENT;
}
int d;
if ((d = indent_helper.flushDedent()) != 0) return yy::parser::token::TOK_DEDENT;
return yy::parser::token::TOK_EOF;
}
. { /* ignore other characters */ }

View file

@ -29,7 +29,7 @@
%token <int> NUMBER
%token ASSIGN PLUS MINUS L_PAREN R_PAREN COLON
%token KW_DEF KW_IF KW_RETURN KW_FOR KW_IN
%token EOF NEWLINE INDENT_UP INDENT_DOWN
%token EOF NEWLINE INDENT DEDENT
%%