{"id":183444,"date":"2026-09-23T16:54:23","date_gmt":"2026-09-23T14:54:23","guid":{"rendered":"https:\/\/prohoster.info\/blog\/news\/pervyj-vypusk-scan-biblioteki-razbora-teksta-dlya-c-s-postroeniem-konechnogo-avtomata-pri-kompilyaczii"},"modified":"2026-09-23T16:54:29","modified_gmt":"2026-09-23T14:54:29","slug":"first-release-of-scan-a-c-text-parsing-library-with-compile-time-finite-automaton-construction","status":"publish","type":"post","link":"https:\/\/prohoster.info\/de\/blog\/news\/first-release-of-scan-a-c-text-parsing-library-with-compile-time-finite-automaton-construction","title":{"rendered":"Erste Ver\u00f6ffentlichung von scan, einer Textanalysebibliothek f\u00fcr C++ mit Endzustandsautomatisierung w\u00e4hrend der Kompilierung","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>\u041e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u044b\u043f\u0443\u0441\u043a \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 scan  (0.1.0), \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u044e\u0449\u0435\u0439 \u0442\u0435\u043a\u0441\u0442 \u0432 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0443, \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u043c\u0443 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435  \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438. \u0428\u0430\u0431\u043b\u043e\u043d \u0438\u043b\u0438 \u0444\u043e\u0440\u043c\u0430\u0442 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 C++ \u0438  \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0432 \u0440\u0430\u0437\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0439 \u0434\u0435\u0442\u0435\u0440\u043c\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442 (tagged deterministic finite automaton, TDFA), \u043e\u0431\u0445\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u043c \u0432 \u043a\u043e\u0434 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 C++. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0448\u0435\u043d\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430. \u041a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 C++23 \u0438 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0435\u0439 GPLv3.         import scan;       \/\/ \u0421\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u043b\u0438 \u0432\u0441\u044f \u0441\u0442\u0440\u043e\u043a\u0430. \u041a\u0430\u0436\u0434\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 &#8212; \u0435\u0449\u0451 \u0438 \u0430\u0434\u0430\u043f\u0442\u043e\u0440 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430.     scan::match&lt;&#171;[a-z]+@[a-z.]+&#187;>(address);     address | scan::match&lt;&#171;[a-z]+@[a-z.]+&#187;>;       \/\/ \u0421 \u0433\u0440\u0443\u043f\u043f\u0430\u043c\u0438.     const auto found = scan::match&lt;&#171;([0-9]+)-([a-z]+)&#187;>(&#171;42-abc&#187;);     found.get&lt;1>().to_view();            \/\/ &#171;42&#187;       \/\/ \u041d\u0430\u0447\u0430\u043b\u043e \u0441\u0442\u0440\u043e\u043a\u0438, \u0437\u0430\u043d\u044f\u0442\u043e\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u043c, \u0438 \u043f\u0435\u0440\u0432\u043e\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435 \u0433\u0434\u0435 \u0443\u0433\u043e\u0434\u043d\u043e.     scan::starts_with&lt;&#171;[a-z]+&#187;>(&#171;abc123&#187;).whole().to_view();   \/\/ &#171;abc&#187;     scan::search&lt;&#171;[0-9]+&#187;>(&#171;id=4210x&#187;).to_view();              \/\/ &#171;4210&#187;       \/\/ \u0412\u0441\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f \u0438 \u043a\u0443\u0441\u043a\u0438 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438 &#8212; \u043b\u0435\u043d\u0438\u0432\u044b\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f.     for (const auto&#038; one : text | scan::search_all&lt;&#171;[a-z]+&#187;>) { &#8230; }     const auto fields = &#171;a,bb,,ccc&#187; | scan::split&lt;&#171;,&#187;> | std::ranges::to&lt;std::vector>();       \/\/ \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0430 \u043d\u0435 \u0442\u0435\u043a\u0441\u0442.     struct row { int id; std::string_view name; };     const row one = scan::scan&lt;&#171;{},{[a-z]+}&#187;>(line);       \/\/ \u0421\u043f\u0438\u0441\u043e\u043a, \u0441\u0443\u043c\u043c\u0430 \u0442\u0438\u043f\u043e\u0432, \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u0430\u044f \u0444\u043e\u0440\u043c\u0430.     struct all { std::vector&lt;int> values; std::variant&lt;int, std::string_view> tail; };     const all got = scan::scan&lt;&#171;{{}{*,?}} {{[0-9]+}|{[a-z]+}}&#187;>(&#171;1,2,3 abc&#187;);       \/\/ \u041d\u0430\u0447\u0430\u043b\u043e \u0432\u0432\u043e\u0434\u0430 \u0438 \u0442\u043e, \u0447\u0442\u043e \u043e\u0442 \u043d\u0435\u0433\u043e \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c.     const auto [value, rest] = scan::scan_prefix&lt;&#171;{},{}&#187;>(line).take&lt;point>();       \/\/ \u041f\u043e \u0437\u0430\u043f\u0438\u0441\u0438 \u0437\u0430 \u0440\u0430\u0437, \u0438\u0437 \u0447\u0435\u0433\u043e \u0443\u0433\u043e\u0434\u043d\u043e.     for (const row&#038; one : scan::each&lt;&#171;{},{[a-z]+}&#92;&#92;n&#187;>(text).of&lt;row>()) { &#8230; }          <\/p>\n<p>\u0414\u0438\u0430\u043f\u0430\u0437\u043e\u043d, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u043b\u0438\u0448\u044c \u043e\u0434\u043d\u0430\u0436\u0434\u044b, \u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0431\u0435\u0437 \u0431\u0443\u0444\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438, \u043f\u043e\u043b\u044f \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u043f\u043e \u043c\u0435\u0440\u0435 \u043f\u043e\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432. \u0421\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0443\u0434\u0435\u0440\u0436\u0430\u0442\u044c, \u0448\u0430\u0431\u043b\u043e\u043d \u0437\u0430\u0434\u0430\u0451\u0442 \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438; \u0442\u0430\u043c, \u0433\u0434\u0435 \u0442\u0430\u043a\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u043d\u0435\u0442, \u0447\u0442\u0435\u043d\u0438\u0435 \u043e\u0442\u043a\u043b\u043e\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438.         std::istringstream source(&#171;set speed 42&#92;&#92;nset gain 7&#92;&#92;n&#187;);     source &gt; std::noskipws;     struct command { scan::held&lt;16> name; int value; };     for (const command&#038; one :          scan::each&lt;&#171;set {[a-z]+} {[0-9]+}&#92;&#92;n&#187;>(std::views::istream&lt;char>(source))              .of&lt;command>()) { &#8230; }      <b>\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c.   <\/b>  <\/p>\n<p>\u0417\u0430\u043c\u0435\u0440\u044b \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u044b \u043d\u0430 Ryzen 9 9950X, clang 22.1.8 \u0441 libc++, -O3 -march=native,LTO. \u0422\u0440\u0438\u0434\u0446\u0430\u0442\u044c \u0434\u0432\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0437\u0430 \u043f\u0440\u043e\u0445\u043e\u0434, \u043c\u0435\u0434\u0438\u0430\u043d\u0430 \u0441\u0435\u043c\u0438 \u043f\u0440\u043e\u0445\u043e\u0434\u043e\u0432.       &#171;([a-z]+),([a-z]+),([a-z]+),([a-z]+),([a-z]+)&#187;    &#171;alpha,bravo,charlie,delta,echo&#187;         scan::scan&lt;f>.sentinel()      477 \u043d\u0441       re2c                          554 \u043d\u0441       scan::scan&lt;f>                 659 \u043d\u0441       CTRE                          717 \u043d\u0441       RE2                         15986 \u043d\u0441       \u0442\u0435 \u0436\u0435 \u043f\u044f\u0442\u044c \u043f\u043e\u043b\u0435\u0439, \u043f\u043e \u0434\u0432\u0435\u0441\u0442\u0438 \u0431\u0443\u043a\u0432 \u043a\u0430\u0436\u0434\u043e\u0435         scan::scan&lt;f>.sentinel()     57.8 \u043d\u0441       re2c                          637 \u043d\u0441       CTRE                          692 \u043d\u0441       RE2                         11751 \u043d\u0441       &#171;first.last@subdomain.example.com&#187;   \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u043d\u0438\u0435, \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u0442\u0441\u044f         scan::match&lt;p>.sentinel().scalar()   436 \u043d\u0441       scan::match&lt;p>.scalar()              545 \u043d\u0441       re2c                                1186 \u043d\u0441       RE2                                 2616 \u043d\u0441       CTRE                               14339 \u043d\u0441        <b>\u0421\u0432\u0451\u0440\u0442\u043a\u0430 \u0433\u0440\u0443\u043f\u043f \u043f\u043e \u0445\u043e\u0434\u0443 \u0440\u0430\u0437\u0431\u043e\u0440\u0430  <\/b>    <\/p>\n<p>\u0422\u0438\u043f\u0443 \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442\u0441\u044f, \u043a \u043a\u0430\u043a\u043e\u0439 \u0438\u0437 \u0435\u0433\u043e \u0433\u0440\u0443\u043f\u043f \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0441\u0438\u043c\u0432\u043e\u043b, \u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u043c\u0435\u0441\u0442\u0435: \u043d\u0438 \u043e\u0434\u043d\u0430 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044f \u0446\u0438\u043a\u043b\u0430 \u043d\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f, \u043d\u0438 \u043e\u0434\u043d\u043e\u0439 \u043f\u043e\u0434\u0441\u0442\u0440\u043e\u043a\u0438 \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f.          struct tally { unsigned long value = 0; };     struct reading { tally number; std::string_view tail; };       template &lt;>     struct scan::scanner&lt;tally> {       static constexpr std::string_view pattern() { return R&#187;(&#92;&#92;(((_+)(X|Y)*)*&#92;&#92;))&#187;; }       struct state_type { unsigned long total = 0; unsigned place = 0, marks = 0; };       static constexpr state_type begin_groups() { return {}; }       static constexpr void opened_group(state_type&#038; one, scan::group_at&lt;0>) {         one.place = 0; one.marks = 0;       }       static constexpr void closed_group(state_type&#038; one, scan::group_at&lt;0>) {         unsigned long weight = 1;         for (unsigned step = 1; step &lt; one.place; ++step) weight *= 10;         one.total += weight * one.marks;       }       static constexpr void push_group(state_type&#038; one, scan::group_at&lt;1>, char) {         ++one.place;       }       static constexpr void push_group(state_type&#038; one, scan::group_at&lt;2>, char letter) {         one.marks += letter == &#8216;Y&#8217; ? 2u : 1u;       }       static constexpr tally finish_groups(state_type one) { return {one.total}; }     };       const reading got =         scan::scan&lt;&#171;value={}{[a-z]*}&#187;>(&#171;value=(__X_XX)abcdefgh&#187;).of&lt;reading>();     \/\/ got.number.value == 12, got.tail == &#171;abcdefgh&#187;      <center>        heap  scan::scan&lt;f>.scalar()  \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0435  \u0432\u0440\u0443\u0447\u043d\u0443\u044e  scan::scan&lt;f>          10  141 ns  41.4 ns  42.5 ns  170 ns      100  439 ns  341 ns  392 ns  1176 ns      1000  3314 ns  3170 ns  3797 ns  11887 ns        <\/center>      <b>\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u044b \u0438 \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440\u044b  <\/b>    <\/p>\n<p>\u041b\u044e\u0431\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0435\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b &#8212; \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440, \u043f\u0443\u043b, \u0430\u0440\u0435\u043d\u0443, \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e \u0435\u0449\u0451 &#8212; \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0432 \u0442\u043e\u0442 \u0432\u044b\u0437\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435. \u0422\u0438\u043f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0435 \u0442\u0435\u0440\u044f\u0435\u0442\u0441\u044f: \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u043a\u0430\u043d\u0435\u0440\u0430 \u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u0435\u0433\u043e \u0445\u0443\u043a \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u043c\u0438 \u043f\u043e \u043d\u0435\u043c\u0443, \u0442\u0430\u043a \u0447\u0442\u043e \u0432 \u0441\u043a\u0430\u043d\u0435\u0440\u0435 \u043d\u0435 \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442 \u043d\u0438 \u043e\u0434\u0438\u043d \u0442\u0438\u043f \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0435\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b.         struct arena {       std::pmr::memory_resource* where = nullptr;       std::pmr::memory_resource* resource() const { return where; }     };       struct numbers { std::pmr::vector&lt;int> values; };     struct both { numbers left; numbers right; };       template &lt;>     struct scan::scanner&lt;numbers> {       static constexpr std::string_view pattern() { return &#171;([0-9]+)(?:,([0-9]+))*&#187;; }         template &lt;class Told>       struct state { std::pmr::vector&lt;int> values; int running = 0; };         static state&lt;scan::default_context_t> begin_groups() { return {}; }         template &lt;class Told>         requires requires(const Told&#038; one) { one.resource(); }       static state&lt;Told> begin_groups(const Told&#038; told) {         return {std::pmr::vector&lt;int>(told.resource()), 0};       }         template &lt;class Told, std::size_t Which>       static void push_group(state&lt;Told>&#038; one, scan::group_at&lt;Which>, char digit) {         one.running = one.running * 10 + (digit &#8212; &#8216;0&#8217;);       }       template &lt;class Told, std::size_t Which>       static void closed_group(state&lt;Told>&#038; one, scan::group_at&lt;Which>) {         one.values.push_back(one.running);         one.running = 0;       }       template &lt;class Told>         static numbers finish_groups(state&lt;Told> one) { return {std::move(one.values)}; }     };       std::pmr::monotonic_buffer_resource bytes;     const arena mine{&#038;bytes};       scan::scan&lt;&#171;{} {}&#187;>(text).of&lt;both>(mine);                            \/\/ \u043e\u0434\u0438\u043d \u043d\u0430 \u043e\u0431\u0430 \u043c\u0435\u0441\u0442\u0430     scan::scan&lt;&#171;{} {}&#187;>(text).of&lt;both>(mine, scan::default_context);     \/\/ \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u043d\u0430 \u043c\u0435\u0441\u0442\u043e     scan::scan&lt;&#171;{} {}&#187;>(text).of&lt;both>({mine, scan::default_context});   \/\/ \u0442\u043e \u0436\u0435 \u0432 \u0441\u043a\u043e\u0431\u043a\u0430\u0445     const both got = scan::scan&lt;&#171;{} {}&#187;>(text).with(mine);       \/\/ \u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0443 \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u044b\u0442\u044c \u0441\u0432\u043e\u0438\u043c \u0442\u0438\u043f\u043e\u043c: \u0430\u043b\u043b\u043e\u043a\u0430\u0442\u043e\u0440 \u0434\u043e\u0445\u043e\u0434\u0438\u0442 \u0434\u043e \u0442\u043e\u0433\u043e,     \/\/ \u0447\u0442\u043e \u0441\u0442\u0440\u043e\u0438\u0442 \u0447\u0442\u0435\u043d\u0438\u0435.     struct two { std::pmr::string name; std::pmr::string tail; };     const two kept = scan::scan&lt;&#171;{[a-z]+} {[a-z]+}&#187;>(text).of&lt;(         std::pmr::polymorphic_allocator&lt;>(&#038;bytes));      <\/p>\n<p>\u0425\u0443\u043a \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0441\u0430\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0435\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u0430 \u043d\u0435 \u043a\u043e\u043f\u0438\u044e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435  \u043c\u043e\u0436\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0435\u0433\u043e \u0430\u0434\u0440\u0435\u0441: \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0436\u0438\u0432\u0451\u0442 \u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0436\u0435, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u044b\u0437\u043e\u0432, \u0430 \u0432\u0441\u0451 \u0447\u0442\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 \u044d\u0442\u043e\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430.    <b>\u041f\u0440\u043e\u0447\u0438\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438  <\/b>  <\/p>\n<ul>\n<li class=l> \u0414\u0432\u0430 \u0441\u043b\u043e\u044f: \u0441\u043b\u043e\u0439 \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 (match, starts_with, search, search_all, split) \u0438 \u0441\u043b\u043e\u0439 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432, \u0433\u0434\u0435 &#171;{}&#187; &#8212; \u043f\u043e\u043b\u0435, \u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0441\u0442\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442 \u043f\u043e\u043b\u044f \u0441\u0430\u043c\u043e\u0433\u043e \u0442\u0438\u043f\u0430.\n<li class=l> \u041f\u0440\u0430\u0432\u0438\u043b\u043e \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e\u0441\u0442\u0438 &#8212; leftmost-first, \u043a\u0430\u043a \u0432 Perl, RE2 \u0438 CTRE.\n<li class=l> \u0412\u0441\u0451 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u043e\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u0432 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u043d\u044b\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u0445.\n<li class=l> \u041d\u0435\u0442 lookaround, \u043e\u0431\u0440\u0430\u0442\u043d\u044b\u0445 \u0441\u0441\u044b\u043b\u043e\u043a \u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 Unicode; \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0441 \u0431\u0430\u0439\u0442\u0430\u043c\u0438.\n<li class=l> \u041d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u044b, \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f.  <\/ul>\n<p>  <b>\u0421\u0431\u043e\u0440\u043a\u0430<\/b>    <\/p>\n<p>\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0432 clang \u0438 GCC. \u041c\u043e\u0434\u0443\u043b\u0438 C++ \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b: \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b  \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b (include\/), \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0438\u0437 \u0442\u0435\u0445 \u0436\u0435 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0443\u0442\u0438\u043b\u0438\u0442\u0430  demodulizer &#8212; \u043a\u0430\u0436\u0434\u044b\u0439 push \u0432 main \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442, \u043b\u0438\u043d\u043a\u0443\u0435\u0442 \u0438 \u043a\u043e\u043c\u043c\u0438\u0442\u0438\u0442 \u0438\u0445 \u043e\u0431\u0440\u0430\u0442\u043d\u043e. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c, Boost.PFR, \u043d\u0435 \u043d\u0443\u0436\u043d\u0430 \u043f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0451\u043d\u043d\u044b\u0445 binding packs \u0438\u0437 C++26.         FetchContent_Declare(scan       GIT_REPOSITORY https:\/\/github.com\/j4niwzis\/scan.git       GIT_TAG        v0.1.0)     FetchContent_MakeAvailable(scan)     target_link_libraries(mine PRIVATE scan::scan)<br \/>\n<br \/>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/www.opennet.ru\/opennews\/art.shtml?num=66327\">opennet.ru<\/a> <\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u044b\u043f\u0443\u0441\u043a \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 scan (0.1.0), \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u044e\u0449\u0435\u0439 \u0442\u0435\u043a\u0441\u0442 \u0432 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0443, \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u043c\u0443 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438. \u0428\u0430\u0431\u043b\u043e\u043d \u0438\u043b\u0438 \u0444\u043e\u0440\u043c\u0430\u0442 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 C++ \u0438 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0432 \u0440\u0430\u0437\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0439 \u0434\u0435\u0442\u0435\u0440\u043c\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442 (tagged deterministic finite automaton, TDFA), \u043e\u0431\u0445\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u043c \u0432 \u043a\u043e\u0434 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 C++. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":10,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[702],"tags":[],"class_list":["post-183444","post","type-post","status-publish","format-standard","hentry","category-news"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u044b\u043f\u0443\u0441\u043a \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 scan (0.1.0), \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u044e\u0449\u0435\u0439 \u0442\u0435\u043a\u0441\u0442 \u0432 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0443, \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u043c\u0443 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Alexander Kovalev\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/de\/blog\/news\/first-release-of-scan-a-c-text-parsing-library-with-compile-time-finite-automaton-construction\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041f\u0435\u0440\u0432\u044b\u0439 \u0432\u044b\u043f\u0443\u0441\u043a scan, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u0442\u0435\u043a\u0441\u0442\u0430 \u0434\u043b\u044f C++ \u0441 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435\u043c \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0430 \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u044b\u043f\u0443\u0441\u043a \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 scan (0.1.0), \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u044e\u0449\u0435\u0439 \u0442\u0435\u043a\u0441\u0442 \u0432 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0443, \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u043c\u0443 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/de\/blog\/news\/first-release-of-scan-a-c-text-parsing-library-with-compile-time-finite-automaton-construction\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-09-23T14:54:23+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-09-23T14:54:29+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Die erste Ausgabe von scan, einer Textanalysebibliothek f\u00fcr C++, die bei der Kompilierung einen endlichen Automaten aufbaut | ProHoster","description":"Die erste Ausgabe der Bibliothek scan (0.1.0) wurde ver\u00f6ffentlicht, die Texte anhand eines zur Compile-Zeit bekannten Musters analysiert.","canonical_url":"https:\/\/prohoster.info\/de\/blog\/news\/first-release-of-scan-a-c-text-parsing-library-with-compile-time-finite-automaton-construction","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"de_DE","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041f\u0435\u0440\u0432\u044b\u0439 \u0432\u044b\u043f\u0443\u0441\u043a scan, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u0442\u0435\u043a\u0441\u0442\u0430 \u0434\u043b\u044f C++ \u0441 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435\u043c \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0430 \u043f\u0440\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 | ProHoster","og:description":"\u041e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u044b\u043f\u0443\u0441\u043a \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 scan (0.1.0), \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u044e\u0449\u0435\u0439 \u0442\u0435\u043a\u0441\u0442 \u0432 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0443, \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u043c\u0443 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438.","og:url":"https:\/\/prohoster.info\/de\/blog\/news\/first-release-of-scan-a-c-text-parsing-library-with-compile-time-finite-automaton-construction","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2026-09-23T14:54:23+00:00","article:modified_time":"2026-09-23T14:54:29+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":[],"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/183444","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/10"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=183444"}],"version-history":[{"count":1,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/183444\/revisions"}],"predecessor-version":[{"id":183445,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/183444\/revisions\/183445"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=183444"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=183444"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=183444"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}