#include #include #include #include "dbc.hpp" #include #include "ansi_parser.hpp" using namespace fmt; %%{ machine foo; action tstart { start = fpc; } action number { auto [ptr, ec] = std::from_chars(start, fpc, value); dbc::check(ec == std::errc(), "error in number parsing"); } action color24b { } action is_fg { target = color; } action is_bg { target = bgcolor; } action out { write(bgcolor, color, fc); } action reset_fg { color = default_fg; } action reset_bg { bgcolor = default_bg; } action red { target.r = value; } action blue { target.g = value; } action green { target.b = value; } action start { value = 0; } action end { } ESC = 0x1B; start = ESC "["; fg = "38;" %is_fg; bg = "48;" %is_bg; reset = ("39" %reset_fg | "49" %reset_bg); num = digit+ >tstart %number; color256 = "5;"; color24b = "2;"; ansi = ( start %start ( reset | (fg|bg) color24b num %red ";" num %blue ";" num %green %color24b ) "m" %end ); other = (any+ @out -- ESC)*; main := (other :> ansi)**; }%% %% write data; bool parse_ansi(std::string_view codes, sf::Color default_fg, sf::Color default_bg, WriteCB write) { const char *start = NULL; int cs = 0; unsigned int value = 0; const char *p = codes.data(); const char *pe = p + codes.size(); const char *eof = pe; sf::Color bgcolor(default_bg); sf::Color color(default_fg); sf::Color &target = bgcolor; %% write init; %% write exec; return p - pe == 0; }