vak: (Знайка)
[personal profile] vak
Для C++ появилась и развивается реализация универсального парсера. Это вместо YACC, Bison и прочих PEGTL.

Проект: github.com/jwtowner/lug

Пример реализации Бейсика на Си++. Меньше пятисот строк кода: github.com/jwtowner/lug/blob/master/samples/basic/basic.cpp

Простой калькулятор:
using namespace lug::language;

int i;
double e, l, n, r, s;
double v[26];

extern rule Expr;

implicit_space_rule BLANK = lexeme[ *"[ \t]"_rx ];

rule EOL    = lexeme[ "[\n\r;]"_rx ];
rule ID     = lexeme[ "[a-zA-Z]"_rx  <[](syntax m) -> int { return static_cast<int>(lug::unicode::tolower(static_cast<char32_t>(m.str().at(0))) - U'a'); } ];
rule NUMBER = lexeme[ ( ~"[-+]"_rx > +"[0-9]"_rx > ~('.' > +"[0-9]"_rx) )
                                     <[](syntax m) -> double { return std::stod(std::string{m}); } ];
rule Value  = n%NUMBER               <[]{ return n; }
            | i%ID > !"="_sx         <[]{ return v[i]; }
            | '(' > e%Expr > ')'     <[]{ return e; };
rule Prod   = l%Value > *(
                  '*' > r%Value      <[]{ l *= r; }
                | '/' > r%Value      <[]{ l /= r; }
            )                        <[]{ return l; };
rule Sum    = l%Prod > *(
                  '+' > r%Prod       <[]{ l += r; }
                | '-' > r%Prod       <[]{ l -= r; }
            )                        <[]{ return l; };
rule Expr   = i%ID > '=' > s%Sum     <[]{ return v[i] = s; }
            | s%Sum                  <[]{ return s; };
rule Stmt   = ( (   "exit"_isx
                  | "quit"_isx )     <[]{ std::exit(EXIT_SUCCESS); }
                | e%Expr             <[]{ std::cout << e << "\n"; }
            ) > EOL
            | *( !EOL > any ) > EOL  <[]{ std::cout << "SYNTAX ERROR\n"; };

grammar Grammar = start(Stmt > eoi);

Date: 2025-03-27 18:30 (UTC)
sab123: (Default)
From: [personal profile] sab123
Еще есть Antler. Он умеет даже обходы дерева делать, но сам парсер в нем - LL.

Date: 2025-03-27 20:34 (UTC)
vlad_m: (Default)
From: [personal profile] vlad_m
Только он, как я понимаю, генератор исходников, а тут прелесть в том, что грамматика описывается сразу на cpp. И, значит, фрагменты кода, который надо исполнять по свёртке конструкции, вставляются естественным образом, а не через $$, $1 и т.д.

Date: 2025-03-27 22:55 (UTC)
sab123: (Default)
From: [personal profile] sab123
О, прикольно, я не сразу понял, что это скармливается сразу в компилятор, а не в кодогенератор сначала.

Date: 2025-03-27 21:55 (UTC)
juan_gandhi: (Default)
From: [personal profile] juan_gandhi
Напоминает наши скальные - но как-то гораздо компактнее у вас!

Date: 2025-03-28 10:14 (UTC)
chaource: (Default)
From: [personal profile] chaource
А вотъ ща мы на Скалѣ это сдѣлаемъ! Черезъ макросы!

Date: 2025-03-28 11:23 (UTC)
juan_gandhi: (Default)
From: [personal profile] juan_gandhi
s/return std::stod(std::string{m});/s"$m".toDouble/

И макросовъ не нать.
Edited Date: 2025-03-28 11:24 (UTC)

Date: 2025-03-28 09:11 (UTC)
mikerrr: (Default)
From: [personal profile] mikerrr
Скобочки раздражают))

Date: 2025-03-28 09:19 (UTC)
ufm: (Default)
From: [personal profile] ufm
Всё таки Бэкус-Наур и LALR(1) - наше всё. Т.е. никуда мы от yacc/bison не денемся. :)