{"id":482676,"date":"2026-06-07T07:21:59","date_gmt":"2026-06-07T07:21:59","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=482676"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=482676","title":{"rendered":"\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u0432\u043e\u0435\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 Rust #2: \u041f\u0430\u0440\u0441\u0435\u0440 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440!<\/p>\n<h2>\u0427\u0442\u043e \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c?<\/h2>\n<p>\u041c\u044b \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043f\u0430\u0440\u0441\u0435\u0440 \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a\u0438\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439: <code>1+2*(2+8)*2*a+3<\/code>. \u0421\u043d\u0430\u0447\u0430\u043b\u043e \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0430\u0440\u0441\u0435\u0440 \u0434\u043b\u044f \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439, \u0430 \u043f\u043e\u0441\u043b\u0435 \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u0437\u0430\u0439\u043c\u0435\u043c\u0441\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f\u043c\u0438 \u0438 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c\u0438. \u041a\u0430\u043a \u043f\u0438\u0441\u0430\u043b \u0440\u0430\u043d\u0435\u0435, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0430\u0440\u0441\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u0441\u043f\u0443\u0441\u043a\u0430, \u0438 \u0442\u0430\u043c \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432. \u0421\u043d\u0430\u0447\u0430\u043b\u043e <code>*\/<\/code>, \u0430 \u043f\u043e\u0442\u043e\u043c <code>+-<\/code>. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u0430\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0430: <code>primary<\/code> -&gt; <code>unary<\/code> -&gt; <code>additive<\/code> -&gt; <code>multiplicative<\/code> -&gt; <code>comparison<\/code> -&gt; <code>logical<\/code>. <\/p>\n<p>\u0421\u0430\u043c\u0438 \u043e\u0431\u044c\u0435\u043a\u0442\u044b \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0431\u0443\u0434\u0443\u0442 \u0442\u0438\u043f\u0430 enum Expr. \u0411\u0443\u0434\u0443\u0442 \u0442\u0430\u043a\u0438\u0435 \u0442\u0438\u043f\u044b:<\/p>\n<ol>\n<li>\n<p><strong>Expr::Num(f64)<\/strong> &#8212; \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u0447\u0438\u0441\u043b\u043e, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 <code>primary<\/code><\/p>\n<\/li>\n<li>\n<p>\u0395xpr::Bool(bool) &#8212; \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 <code>primary<\/code><\/p>\n<\/li>\n<li>\n<p><strong>Expr::Str(String)<\/strong> &#8212; \u043b\u0438\u0442\u0435\u0440\u0430\u043b \u0441\u0442\u0440\u043e\u043a\u0438, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 <code>primary<\/code><\/p>\n<\/li>\n<li>\n<p><strong>Expr::Id(String)<\/strong> &#8212; \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 <code>primary<\/code><\/p>\n<\/li>\n<li>\n<p><strong>Expr::Unary(UnaryOp, Box&lt;Expr&gt;)<\/strong> &#8212; \u0443\u043d\u0430\u0440\u043d\u0432\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0438 \u043d\u043e\u0432\u043e\u0435 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 &#8212; UnaryOp: <strong>Neg<\/strong> (-) \u0438 <strong>Not<\/strong> (!). \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 <code>unary<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>Expr::Arith(Box&lt;Expr&gt;, ArithOp, Box&lt;Expr&gt;)<\/strong> &#8212; \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f. \u0422\u0443\u0442 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u043c \u0435\u0449\u0435 \u043e\u0434\u043d\u043e \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 &#8212; ArithOp: <strong>Add, Sub, Mul \u0438 Div<\/strong>. \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 <code>multiplicative<\/code> \u0438 <code>additive<\/code><\/p>\n<\/li>\n<li>\n<p><strong>Expr::Comp(Box&lt;Expr&gt;, CompOp, Box&lt;Expr&gt;)<\/strong> &#8212; \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0442\u0430 \u0436\u0435, \u043d\u043e \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u043d\u043e\u0432\u043e\u0435 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 &#8212; CompOp: <strong>Gt<\/strong> (&gt;), <strong>Ge<\/strong> (&gt;=), <strong>Lt<\/strong> (&lt;), <strong>Le<\/strong> (&lt;=), <strong>Eq<\/strong> (==), <strong>Ne<\/strong> (!=). \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 <code>comparison<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>Expr::Logic(Box&lt;Expr&gt;, LogicOp, Box&lt;Expr&gt;) <\/strong>&#8212; \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435. \u0422\u0443\u0442 \u0442\u0430\u043a\u0436\u0435 \u043d\u043e\u0432\u043e\u0435 \u043f\u0435\u0440\u0435\u0447\u0442\u0441\u043b\u0435\u043d\u0438\u0435 &#8212; LogicOp: <strong>And<\/strong> (&amp;&amp;) \u0438 <strong>Or<\/strong> (||). \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 <code>logical<\/code><\/p>\n<\/li>\n<\/ol>\n<p>\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u043b, \u043d\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u044e\u0441\u044c. <\/p>\n<p><strong>primary<\/strong> &#8212; \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c, \u043c\u043e\u0436\u0435\u0442 \u043b\u0438 \u044d\u0442\u043e\u0442 \u0442\u043e\u043a\u0435\u0433 \u0431\u044b\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0438. \u042d\u0442\u043e \u043c\u043e\u0436\u0433\u0443\u0442 \u0431\u044b\u0442\u044c: \u0447\u0438\u0441\u043b\u0430, \u0441\u0442\u0440\u043e\u043a\u0438, \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b, \u0432\u044b\u0437\u043e\u0432\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0441\u043a\u043e\u0431\u043a\u0438 (\u0422\u043e\u0447\u043d\u0435\u0435, \u0438\u0445 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435). \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c Num, Str, Id. \u0421\u0447\u0438\u0442\u0430\u044f \u0441\u043a\u043e\u0431\u043a\u0438, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043b\u044e\u0431\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435.<\/p>\n<p><strong>unary<\/strong> &#8212; \u0442\u0443\u0442 \u043c\u044b \u0431\u0435\u0440\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>!<\/code>,  \u0442\u043e \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0435\u0433\u043e, \u0432\u044b\u0437\u0432\u0432\u0430\u0435\u043c <code>primary<\/code>, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c <code>Expr::Unary<\/code>.<\/p>\n<p><strong>multiplicative<\/strong> &#8212; \u0442\u0443\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u0432\u0441\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441 \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u0438 \u0434\u0435\u043b\u0435\u043d\u0438\u0435\u043c \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0432\u044b\u0440\u0430\u044d\u0435\u043d\u0438\u0435. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c <code>Expr::Arith<\/code><\/p>\n<p><strong>additive<\/strong> &#8212; \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0432\u044b\u0447\u0438\u0442\u0430\u043d\u0438\u044f. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c <code>Expr::Arith<\/code><\/p>\n<h2>\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u043f\u0438\u0441\u0430\u0442\u044c!<\/h2>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c &#8212; <strong>parser<\/strong>. \u0422\u0430\u043c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u0444\u0430\u0439\u043b\u044b <strong>expr.rs<\/strong>, <strong>parser.rs<\/strong> \u0438 <strong>mod.rs<\/strong>. \u0421\u043d\u0430\u0447\u0430\u043b\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u043d\u0430\u043f\u0438\u0448\u0435\u043c <strong>mod.rs<\/strong>. (\u041d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u043e, \u0434\u0430?)<\/p>\n<p>\u041f\u043e\u043a\u0430\u0436\u0443 \u0441\u0440\u0430\u0437\u0443 \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u0439.<\/p>\n<details class=\"spoiler\">\n<summary>parser\/mod.rs<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"rust\">pub mod expr;mod parser;pub use parser::Parser;#[derive(Debug, Clone)]pub struct Info {    pub line: usize,    pub offset: usize,    pub len: usize,}#[macro_export]macro_rules! info {    ($line:expr, $offset:expr, $len:expr) =&gt; {        $crate::parser::Info {            line: $line,            offset: $offset,            len: $len,        }    };    ($tkn:expr) =&gt; {        info!($tkn.line, $tkn.offset, $tkn.len)    };}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f <strong>Expr<\/strong>, \u043d\u0430\u043c \u0442\u043e\u0436\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f, \u0438 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 <strong>Info<\/strong>. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0435\u0435, \u043c\u044b \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0442\u043b\u0430\u0434\u043a\u0443 \u0432 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0438\u0442\u0430\u0442\u043e\u0440\u0435, \u0430 \u0442\u0430\u043a \u043a\u0430\u043a \u0438 \u0441\u0442\u0435\u0439\u0442\u043c\u0435\u043d\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430\u043c\u0438, \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0435\u0433\u043e \u0432 <strong>mod.rs<\/strong>. \u0422\u0430\u043a\u0436\u0435 \u0442\u0443\u0442 \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043c\u0430\u043a\u0440\u043e\u0441, \u043e\u043d \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043e\u0431\u044c\u0435\u043a\u0442 <strong>Info<\/strong>. \u0410 \u0434\u043b\u0438\u043d\u043d\u044b\u0439, \u0433\u0434\u0435 \u043c\u044b \u0432 \u0440\u0443\u0447\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u043c\u044b \u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0434\u043b\u044f \u0441\u0442\u0435\u0439\u0442\u043c\u0435\u043d\u0442\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0438 \u0438\u0445 \u043e\u0442\u043b\u0430\u0436\u0438\u0432\u0430\u0442\u044c.<\/p>\n<details class=\"spoiler\">\n<summary>parser\/expr.rs<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"rust\">use super::Info;pub type BExpr = Box&lt;Expr&gt;;#[derive(Debug, Clone)]pub enum Expr {    Num(f64, Info),    Str(String, Info),    Id(String, Info),    Bool(bool, Info),    Unary(UnaryOp, BExpr, Info),    Arith(BExpr, ArithOp, BExpr, Info),    Comp(BExpr, CompOp, BExpr, Info),    Logic(BExpr, LogicOp, BExpr, Info),}impl Expr {    pub fn info(&amp;self) -&gt; Info {        match self {            Expr::Str(_, info) =&gt; info.clone(),            Expr::Num(_, info) =&gt; info.clone(),            Expr::Id(_, info) =&gt; info.clone(),            Expr::Bool(_, info) =&gt; info.clone(),            Expr::Arith(_, _, _, info) =&gt; info.clone(),            Expr::Comp(_, _, _, info) =&gt; info.clone(),            Expr::Logic(_, _, _, info) =&gt; info.clone(),            Expr::Unary(_, _, info) =&gt; info.clone(),        }    }}#[derive(Debug, Clone)]pub enum ArithOp {    Add, \/\/ +    Sub, \/\/ -    Mul, \/\/ *    Div, \/\/ \/}#[derive(Debug, Clone)]pub enum CompOp {    Gt, \/\/ &gt;    Ge, \/\/ &gt;=    Lt, \/\/ &lt;    Le, \/\/ &lt;=    Eq, \/\/ ==    Ne, \/\/ !=}#[derive(Debug, Clone)]pub enum LogicOp {    And, \/\/ &amp;&amp;    Or,  \/\/ ||}#[derive(Debug, Clone)]pub enum UnaryOp {    Not, \/\/ !    Neg, \/\/ -}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u042f \u0441\u043e\u0437\u0434\u0430\u043b \u0442\u0438\u043f <strong>BExpr<\/strong>, \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043d\u0435 \u043f\u0438\u0441\u0430\u0442\u044c <strong>Box&lt;Expr&gt;<\/strong>. \u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435 \u0442\u0443\u0442 \u0435\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432: <strong>ArithOp<\/strong>, <strong>CompOp<\/strong>, <strong>LogicOp<\/strong>. \u0422\u0430\u043a\u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u043f\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 &#8212; Expr. \u042f \u0440\u0430\u043d\u0435\u0435 \u0443\u0436\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u044d\u0442\u043e, \u0442\u0430\u043a \u0447\u0442\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c\u0441\u044f \u043d\u0435 \u0431\u0443\u0434\u0443. \u041c\u0435\u0442\u043e\u0434 <code>info<\/code> \u0442\u0443\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442 \u0438\u043d\u0444\u043e \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0432\u0432\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0438\u0445 \u0443\u0434\u043e\u0431\u043d\u0435\u0435. (\u0423\u0432\u0438\u0434\u0438\u0442\u0438 \u0432\u043e\u043e\u0431\u0449\u0435\u043c)<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0441\u0442\u0443\u043a\u0442\u0443\u0440\u0443 Parser.<\/p>\n<details class=\"spoiler\">\n<summary>parser\/parser.rs<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"rust\">use super::expr::{ArithOp, BExpr, CompOp, Expr, LogicOp};use crate::lexer::token::{TKind, Token};pub struct Parser&lt;'a&gt; {    pos: usize,    tokens: Vec&lt;Token&gt;,    lines: Vec&lt;&amp;'a str&gt;,}impl&lt;'a&gt; Parser&lt;'a&gt; {    pub fn new(tokens: Vec&lt;Token&gt;, source: &amp;'a str) -&gt; Self {        let lines: Vec&lt;&amp;str&gt; = source.lines().collect();        Self {            tokens,            pos: 0,            lines,        }    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u0417\u0430\u0440\u0430\u043d\u0435\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c <strong>Expr<\/strong> \u0438 \u0435\u0433\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 <strong>Token<\/strong> \u0438 <strong>TKind<\/strong> (\u0432\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c <strong>TokenKind<\/strong>). \u0412 \u043c\u0435\u0442\u043e\u0434 new \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0442\u043e\u043a\u0435\u043d\u044b, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0435\u043c \u0441\u0442\u0440\u043e\u0438\u0442\u044c <strong>AST<\/strong> (Abstract Syntax Tree) \u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0441\u0442\u0440\u043e\u043a\u0438. lines \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0442\u0430\u043a\u0436\u0435 \u0434\u043b\u044f \u043e\u0448\u0438\u0431\u043e\u043a, \u043a\u0430\u043a \u0438 \u0432 \u043b\u0435\u043a\u0441\u0435\u0440\u0435.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b. \u0418\u0445 \u0431\u0443\u0434\u0435\u0442 \u043c\u0435\u043d\u044c\u0448\u0435 \u0438 \u0431\u0443\u0434\u0443 \u043f\u0440\u043e\u0449\u0435 (\u043d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435).<\/p>\n<details class=\"spoiler\">\n<summary>parser\/parser.rs: Parser<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"rust\">use std::mem::discriminant;...fn check(&amp;mut self, kind: TKind) -&gt; bool {    if discriminant(&amp;self.peek(0).kind) == discriminant(&amp;kind) {        self.advance(1);        true    } else {        false    }}fn error(&amp;self, msg: &amp;str, token: Token) -&gt; String {    let line = self.lines[token.line];    let header = format!(\"Error in {}:{} - {msg}\", token.line, token.offset);    let err_line = format!(\"{} | {line}\", token.line);    let point = format!(        \"{} | {}{}\",        \" \".repeat(token.line.to_string().len()),        \" \".repeat(token.offset),        \"^\".repeat(token.len),    );    format!(\"{header}\\n{err_line}\\n{point}\\n\")}fn peek(&amp;self, offset: i8) -&gt; Token {    let idx = self.pos + offset as usize;    self.tokens.get(idx).unwrap().clone()}fn advance(&amp;mut self, offset: u8) {    self.pos += offset as usize;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u0412 <code>advance<\/code> \u043c\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e <code>self.pos<\/code>. <\/p>\n<p>\u0412 <code>peek<\/code> \u044f \u0440\u0435\u0448\u0438\u043b \u0443\u0431\u0440\u0430\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043b <code>unwrap<\/code>. \u0421\u043d\u043e\u0432\u0430 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0443: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0435\u0433\u043e \u043d\u0430 \u0441\u0432\u043e\u0439 \u0441\u0442\u0440\u0430\u0445 \u0438 \u0440\u0438\u0441\u043a, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u043e\u0432. \u041d\u043e \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430, \u043c\u044b \u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0435\u0433\u043e.<\/p>\n<p>\u0412 <code>error<\/code> \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043a\u0435\u043d, \u0438 \u0431\u0443\u0434\u0435\u043c \u0431\u0440\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0438\u0437 \u043d\u0435\u0433\u043e.<\/p>\n<p><code>check<\/code> \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043b\u0438 \u0442\u0438\u043f \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043e\u043c\u0443, \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0443\u0441\u043f\u0435\u0445\u0430 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0435\u0433\u043e \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c <strong>true<\/strong>, \u0430 \u0432 \u0438\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c <strong>false<\/strong>. <code>discriminant<\/code> \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d, \u0447\u0442\u043e\u0431\u044b \u0441\u0440\u0430\u043d\u0438\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0438\u043f \u0442\u043e\u043a\u0435\u043d\u0430, \u0430 \u043d\u0435 \u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435. <\/p>\n<h2>\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0430\u0440\u0441\u0438\u043d\u0433!<\/h2>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 <code>primary<\/code>.<\/p>\n<details class=\"spoiler\">\n<summary>parser\/parser.rs: Parser.primary<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"rust\">fn primary(&amp;mut self) -&gt; Expr {    let current = self.peek(0);    match current.kind {        TKind::NumLit(n) =&gt; {            self.advance(1);            Expr::Num(n, info!(current))        }        TKind::StrLit(s) =&gt; {            self.advance(1);            Expr::Str(s, info!(current))        }        TKind::Id(id) =&gt; {            self.advance(1);            Expr::Id(id, info!(current))        }        TKind::Bool(truth) =&gt; {            self.advance(1);            Expr::Bool(truth, info!(current))        }        _ =&gt; panic!(\"{}\", self.error(\"Unexpected token in primary\", current)),    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u041c\u044b \u0431\u0435\u0440\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0435\u0433\u043e. \u0415\u0441\u043b\u0438 \u043e\u043d \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0432 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0438, \u0442\u043e \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0435\u0433\u043e \u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043e\u0431\u044c\u0435\u043a\u0442 <strong>Expr<\/strong>. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435 \u0432\u0430\u043b\u0438\u0434\u043d\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430 \u043f\u0430\u043d\u0438\u043a\u0443\u0435\u043c \u043d\u0430 \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u044b\u0439 \u0442\u043e\u043a\u0435\u043d. \u0421\u043a\u043e\u0431\u043a\u0438 \u0442\u0430\u043a\u0436\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0437\u0434\u0435\u0441\u044c, \u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0438\u0445 \u043f\u043e\u0437\u0436\u0435.<\/p>\n<details class=\"spoiler\">\n<summary>parser\/parser.rs: Parser.unary<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"rust\">fn unary(&amp;mut self) -&gt; Expr {    let current = self.peek(0);    match current.kind {        TKind::Minus =&gt; {            self.advance(1);            let primary = self.primary();            let info = primary.info();            let info = info!(info.line, info.offset - 1, info.len + 1);            Expr::Unary(UnaryOp::Neg, Box::new(primary), info)        }        TKind::Bang =&gt; {            self.advance(1);            let primary = self.primary();            let info = primary.info();            let info = info!(info.line, info.offset - 1, info.len + 1);            Expr::Unary(UnaryOp::Not, Box::new(primary), info)        }        _ =&gt; self.primary(),    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0443\u0442 \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e &#8212; \u0438\u043b\u0438 <code>!<\/code>, \u0442\u043e \u0441\u043e\u043e\u0442\u0430\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c <code>Expr::Unary<\/code>, \u0432 \u0438\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043e\u0431\u044b\u0447\u043d\u044b\u0439 primary. \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0432 \u0432\u043e\u0437\u043c\u0435\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0441 <code>TKind::Minus<\/code>.<\/p>\n<pre><code class=\"rust\">TKind::Minus =&gt; {    self.advance(1);    let primary = self.primary();    let info = primary.info();    let info = info!(info.line, info.offset - 1, info.len + 1);    Expr::Unary(UnaryOp::Neg, Box::new(primary), info)}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041c\u044b \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d (\u043c\u0438\u043d\u0443\u0441) \u0438 \u0431\u0435\u0440\u0435\u043c primary. \u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c <strong>Info<\/strong>. \u041f\u0440\u043e\u0441\u0442\u043e \u0432\u0437\u044f\u0442\u044c <code>info!(primary)<\/code> \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u0438\u043d\u0443\u0441 \u0442\u043e\u0436\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0445\u043e\u0434\u0438\u0442\u044c \u0432 <strong>Info<\/strong>. \u0422\u0430\u043a \u0447\u0442\u043e \u0431\u0435\u0440\u0435\u043c Info \u0438\u0437 primary, \u0432 \u043c\u0430\u043a\u0440\u043e\u0441 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u043d\u043e\u043c\u0435\u0440 \u0441\u0442\u0440\u043e\u043a\u0438, \u043e\u0442\u0441\u0442\u0443\u043f \u043e\u0442 \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u0442\u0440\u043e\u043a\u0438 &#8212; 1. \u041e\u0442\u043d\u0438\u043c\u0430\u0435\u043c 1, \u0442\u0430\u043a \u043a\u0430\u043a primary \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u0443\u043d\u0430\u0440\u043d\u043e\u0433\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430, \u0438 \u0442\u0430\u043c \u043c\u044b \u0437\u0430\u0445\u0432\u0430\u0442\u0438\u043c \u0438 \u0441\u0430\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440. \u0412 \u0434\u043b\u0438\u043d\u043d\u0443 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0434\u043b\u0438\u043d\u043d\u0443 <code>primary<\/code> + 1, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0440\u043e\u0432\u043d\u044f\u0442\u044c. \u0412 \u043a\u043e\u043d\u0446\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u0439 primary \u0438 <strong>Info<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438. \u0421 <strong>TKind<\/strong> \u043b\u043e\u0433\u0438\u043a\u0430 \u0441\u0445\u043e\u0436\u0430, \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>UnaryOp::Not<\/code>.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0438 <code>multiplicative<\/code>.<\/p>\n<pre><code class=\"rust\">fn multiplicative(&amp;mut self) -&gt; Expr {    let mut left = self.unary();    loop {        let op_token = self.peek(0);        let op = match op_token.kind {            TKind::Star =&gt; ArithOp::Mul,            TKind::Slash =&gt; ArithOp::Div,            _ =&gt; break,        };        self.advance(1);        let right = self.unary();        left = Expr::Arith(Box::new(left), op, Box::new(right), info!(op_token))    }    left}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c <strong>left<\/strong>, \u043a\u0443\u0434\u0430 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c <code>self.unary<\/code>, \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043b\u0435\u0432\u044b\u043c \u043e\u043f\u0435\u0440\u0430\u043d\u0434\u043e\u043c. \u0414\u0430\u043b\u0435\u0435 \u0432 \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0446\u0438\u043a\u043b\u0435: \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u0437\u043d\u0430\u043a \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0434\u0435\u043b\u0435\u043d\u0438\u044f, \u0442\u043e \u0432\u043e\u0437\u0432\u043e\u0449\u0430\u0435\u043c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 <strong>ArithOp<\/strong>, \u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u043b\u044e\u0431\u043e\u0439 \u0434\u0440\u0443\u0433\u043e\u0439 \u0442\u043e\u043a\u0435\u043d, \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u0445\u043e\u0434\u0438\u043c \u0438\u0437 \u0446\u0438\u043a\u043b\u0430 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c <strong>left<\/strong>.<\/p>\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440, \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0435\u0433\u043e \u0438 \u043f\u0430\u0440\u0441\u0438\u043c \u043f\u0440\u0430\u0432\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u043d\u0434. \u041f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c <strong>left<\/strong>, \u043a\u0430\u043a \u043b\u0435\u0432\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u043d\u0434 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u0430\u043c <strong>left<\/strong>, \u0430 \u0434\u043b\u044f \u043f\u0440\u0430\u0432\u043e\u0433\u043e \u043d\u0430\u0448 \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u0441\u043f\u0430\u0440\u0448\u0435\u043d\u044b\u0439 <strong>right<\/strong>. \u0412 <strong>info<\/strong> \u044f \u0440\u0435\u0448\u0438\u043b \u043a\u043b\u0430\u0441\u0442\u044c \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430. \u0422\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u043c\u0435\u043d\u044c\u0448\u0435 \u0437\u0430\u043c\u0430\u0440\u043e\u0447\u0435\u043a \u043f\u043e \u043f\u043e\u0432\u043e\u0434\u0443 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043e\u0448\u0438\u0431\u043e\u043a, \u0438 \u043c\u0435\u043d\u044c\u0448\u0435 \u043a\u043e\u0434\u0430.<\/p>\n<p>\u0423 <code>additive<\/code> \u043b\u043e\u0433\u0438\u043a\u0430 \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u0442\u0430 \u0436\u0435, \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u043d\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435.<\/p>\n<pre><code class=\"rust\">fn additive(&amp;mut self) -&gt; Expr {    let mut left = self.multiplicative();    loop {        let op_token = self.peek(0);        let op = match op_token.kind {            TKind::Plus =&gt; ArithOp::Add,            TKind::Minus =&gt; ArithOp::Sub,            _ =&gt; break,        };        self.advance(1);        let right = self.multiplicative();        left = Expr::Arith(Box::new(left), op, Box::new(right), info!(op_token))    }    left}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u043b\u044f \u043e\u0431\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 expr, \u0442\u0443\u0434\u0430 \u043c\u044b, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0442\u0435\u0440\u043d\u0430\u0440\u043d\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440, \u043d\u043e \u043f\u043e\u043a\u0430 \u0431\u0435\u0437 \u043d\u0435\u0433\u043e:<\/p>\n<pre><code class=\"rust\">fn expr(&amp;mut self) -&gt; Expr {    self.additive()}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418 \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u043d\u043e\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 &#8212; <code>parse_exprs<\/code>. \u041e\u043d \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0435\u0433\u043e \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u0438 \u043e\u0442\u043b\u0430\u0434\u043a\u0438.<\/p>\n<pre><code class=\"rust\">pub fn parse_exprs(&amp;mut self) -&gt; Vec&lt;Expr&gt; {    let mut exprs = vec![];    while self.peek(0).kind != TKind::Eof {        let expr = self.expr();        exprs.push(expr);    }    exprs}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0443 \u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u0442\u0435\u0441\u0442 \u0432 \u043f\u0430\u043f\u043a\u0435 tests &#8212; <strong>parsert.rs<\/strong><\/p>\n<pre><code class=\"rust\">use guidzy::lexer::Lexer;use guidzy::parser::Parser;#[test]fn main() {    let source = \"2 + 2 * 2\"    .trim();    let tokens = Lexer::new(source).tokenize();    println!(\"Source: {}\\nTokens:\", source);    for tkn in &amp;tokens {        println!(\"{:?}\", tkn);    }    let exprs = Parser::new(tokens, source).parse_exprs();    println!(\"Expressions:\");    for ex in exprs {        println!(\"{:?}\", ex);    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0442\u0435\u0441\u0442\u0430 \u0441 \u0432\u044b\u0432\u043e\u0434\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <strong>cargo test &#8212; &#8212;nocapture<\/strong>. \u0412\u044b\u0432\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u043e\u0432\u044b\u043c:<\/p>\n<pre><code>Source: 2 + 2 * 2Tokens:Token { kind: NumLit(2.0), len: 1, pos: 0, line: 0, offset: 0 }Token { kind: Plus, len: 1, pos: 2, line: 0, offset: 2 }Token { kind: NumLit(2.0), len: 1, pos: 4, line: 0, offset: 4 }Token { kind: Star, len: 1, pos: 6, line: 0, offset: 6 }Token { kind: NumLit(2.0), len: 1, pos: 8, line: 0, offset: 8 }Token { kind: Eof, len: 1, pos: 9, line: 0, offset: 9 }Expressions:Arith(Num(2.0, Info { line: 0, offset: 0, len: 1 }), Add, Arith(Num(2.0, Info { line: 0, offset: 4, len: 1 }), Mul, Num(2.0, Info { line: 0, offset: 8, len: 1 }), Info { line: 0, offset: 6, len: 1 }), Info { line: 0, offset: 2, len: 1 })<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0421\u043e\u0433\u043b\u0430\u0441\u0438\u0442\u0435\u0441\u044c, \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043d\u0435\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 \u0432\u044b\u0432\u043e\u0434? \u0427\u0442\u043e\u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0433\u043e \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0442\u0440\u0435\u0439\u0442 <code>fmt::Display<\/code> \u0434\u043b\u044f <strong>Expr<\/strong> \u0438 \u0432\u0441\u0435\u0445 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432:<\/p>\n<details class=\"spoiler\">\n<summary>parser\/expr.rs<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"rust\">use std::fmt;...impl fmt::Display for ArithOp {    fn fmt(&amp;self, f: &amp;mut fmt::Formatter&lt;'_&gt;) -&gt; fmt::Result {        match self {            ArithOp::Add =&gt; write!(f, \"+\"),            ArithOp::Sub =&gt; write!(f, \"-\"),            ArithOp::Mul =&gt; write!(f, \"*\"),            ArithOp::Div =&gt; write!(f, \"\/\"),        }    }}impl fmt::Display for CompOp {    fn fmt(&amp;self, f: &amp;mut fmt::Formatter&lt;'_&gt;) -&gt; fmt::Result {        match self {            CompOp::Gt =&gt; write!(f, \"&gt;\"),            CompOp::Ge =&gt; write!(f, \"&gt;=\"),            CompOp::Lt =&gt; write!(f, \"&lt;\"),            CompOp::Le =&gt; write!(f, \"&lt;=\"),            CompOp::Eq =&gt; write!(f, \"==\"),            CompOp::Ne =&gt; write!(f, \"!=\"),        }    }}impl fmt::Display for LogicOp {    fn fmt(&amp;self, f: &amp;mut fmt::Formatter&lt;'_&gt;) -&gt; fmt::Result {        match self {            LogicOp::And =&gt; write!(f, \"&amp;&amp;\"),            LogicOp::Or =&gt; write!(f, \"||\"),        }    }}impl fmt::Display for UnaryOp {    fn fmt(&amp;self, f: &amp;mut fmt::Formatter&lt;'_&gt;) -&gt; fmt::Result {        match self {            UnaryOp::Neg =&gt; write!(f, \"-\"),            UnaryOp::Not =&gt; write!(f, \"!\"),        }    }}impl fmt::Display for Expr {    fn fmt(&amp;self, f: &amp;mut fmt::Formatter&lt;'_&gt;) -&gt; fmt::Result {        match self {            Expr::Num(n, _) =&gt; write!(f, \"{n}\"),            Expr::Str(s, _) =&gt; write!(f, \"\\\"{s}\\\"\"),            Expr::Id(id, _) =&gt; write!(f, \"{id}\"),            Expr::Bool(b, _) =&gt; write!(f, \"{b}\"),            Expr::Arith(l, op, r, _) =&gt; write!(f, \"({l} {op} {r})\"),            Expr::Comp(l, op, r, _) =&gt; write!(f, \"({l} {op} {r})\"),            Expr::Logic(l, op, r, _) =&gt; write!(f, \"({l} {op} {r})\"),            Expr::Unary(op, expr, _) =&gt; write!(f, \"{op}{expr}\"),        }    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u042f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0440\u0430\u0437\u0443 \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u0441 \u043d\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u044d\u0442\u043e\u043c\u0443. \u0412\u044b\u0432\u043e\u0434 \u0442\u0435\u043f\u0435\u0440\u044c \u0442\u0430\u043a\u043e\u0432:<\/p>\n<pre><code>Source: 2 + 2 * 2Tokens:Token { kind: NumLit(2.0), len: 1, pos: 0, line: 0, offset: 0 }Token { kind: Plus, len: 1, pos: 2, line: 0, offset: 2 }Token { kind: NumLit(2.0), len: 1, pos: 4, line: 0, offset: 4 }Token { kind: Star, len: 1, pos: 6, line: 0, offset: 6 }Token { kind: NumLit(2.0), len: 1, pos: 8, line: 0, offset: 8 }Token { kind: Eof, len: 1, pos: 9, line: 0, offset: 9 }Expressions:(2 + (2 * 2))<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h2>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f<\/h2>\n<p>\u0422\u0443\u0442 \u0432\u0441\u0435 \u043f\u0440\u043e\u0441\u0442\u043e, \u043b\u043e\u0433\u0438\u043a\u0430 \u0442\u0430\u043a\u0430\u044f \u0436\u0435 \u043a\u0430\u043a \u0438 \u0432 <code>additive<\/code> \u0438 <code>multiplicative<\/code>, \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0434\u0440\u0443\u0433\u0438\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0434\u0440\u0443\u0433\u043e\u0439 \u0442\u0438\u043f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f.<\/p>\n<details class=\"spoiler\">\n<summary>parser\/parser.rs: Parser<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"rust\">fn logical(&amp;mut self) -&gt; Expr {    let mut left = self.comparison();    loop {        let op_token = self.peek(0);        let op = match op_token.kind {            TKind::And =&gt; LogicOp::And,            TKind::Or =&gt; LogicOp::Or,            _ =&gt; break,        };        self.advance(1);        let right = self.comparison();        left = Expr::Logic(Box::new(left), op, Box::new(right), info!(op_token))    }    left}fn comparison(&amp;mut self) -&gt; Expr {    let mut left = self.additive();    loop {        let op_token = self.peek(0);        let op = match op_token.kind {            TKind::Gt =&gt; CompOp::Gt,            TKind::Ge =&gt; CompOp::Ge,            TKind::Lt =&gt; CompOp::Lt,            TKind::Le =&gt; CompOp::Le,            TKind::Eq =&gt; CompOp::Eq,            TKind::Ne =&gt; CompOp::Ne,            _ =&gt; break,        };        self.advance(1);        let right = self.additive();        left = Expr::Comp(Box::new(left), op, Box::new(right), info!(op_token))    }    left}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041e\u0431\u043d\u043e\u0432\u0438\u043c \u0442\u0435\u0441\u0442 tests\/parsert.rs<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"rust\">use guidzy::lexer::Lexer;use guidzy::parser::Parser;#[test]fn main() {    let source = \"2 + 2 * 2 &gt; 4 \/ 2 + 2 &amp;&amp; true != false\"    .trim();    let tokens = Lexer::new(source).tokenize();    println!(\"Source: {}\\nTokens:\", source);    for tkn in &amp;tokens {        println!(\"{:?}\", tkn);    }    let exprs = Parser::new(tokens, source).parse_exprs();    println!(\"Expressions:\");    for ex in exprs {        println!(\"{}\", ex);    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u0412\u044b\u0432\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u0438\u043c:<\/p>\n<pre><code>Source: 2 + 2 * 2 &gt; 4 \/ 2 + 2 &amp;&amp; true != falseTokens:Token { kind: NumLit(2.0), len: 1, pos: 0, line: 0, offset: 0 }Token { kind: Plus, len: 1, pos: 2, line: 0, offset: 2 }Token { kind: NumLit(2.0), len: 1, pos: 4, line: 0, offset: 4 }Token { kind: Star, len: 1, pos: 6, line: 0, offset: 6 }Token { kind: NumLit(2.0), len: 1, pos: 8, line: 0, offset: 8 }Token { kind: Gt, len: 1, pos: 10, line: 0, offset: 10 }Token { kind: NumLit(4.0), len: 1, pos: 12, line: 0, offset: 12 }Token { kind: Slash, len: 1, pos: 14, line: 0, offset: 14 }Token { kind: NumLit(2.0), len: 1, pos: 16, line: 0, offset: 16 }Token { kind: Plus, len: 1, pos: 18, line: 0, offset: 18 }Token { kind: NumLit(2.0), len: 1, pos: 20, line: 0, offset: 20 }Token { kind: And, len: 2, pos: 22, line: 0, offset: 22 }Token { kind: Bool(true), len: 6, pos: 25, line: 0, offset: 25 }Token { kind: Ne, len: 2, pos: 30, line: 0, offset: 30 }Token { kind: Bool(false), len: 7, pos: 33, line: 0, offset: 33 }Token { kind: Eof, len: 1, pos: 38, line: 0, offset: 38 }Expressions:(((2 + (2 * 2)) &gt; ((4 \/ 2) + 2)) &amp;&amp; (true != false))<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u043a \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043a\u043e\u0431\u043a\u0438. \u0412 <code>primary<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u043e\u0432\u0443\u044e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443:<\/p>\n<pre><code class=\"rust\">TKind::LParen =&gt; {    self.advance(1);    let expr = self.expr();    if !self.check(TKind::RParen) {        panic!(            \"{}\",            self.error(&amp;format!(\"Expected ')', found {:?}\", current), current)        );    }    expr}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u0443\u0442 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043b\u0435\u0432\u0443\u044e \u0441\u043a\u043e\u0431\u043a\u0443, \u043f\u043e\u0441\u043b\u0435 \u0441\u043a\u043e\u0431\u043a\u0438 \u043f\u0430\u0440\u0441\u0438\u043c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0442\u043e\u043a\u0435\u043d \u043d\u0430 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0443\u044e \u0441\u043a\u043e\u0431\u043a\u0443. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u043d\u0435 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u0441\u043a\u043e\u0431\u043a\u0430, \u0442\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443, \u0432 \u0438\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435.<\/p>\n<details class=\"spoiler\">\n<summary>\u041e\u0431\u043d\u043e\u0432\u0438\u043c \u0442\u0435\u0441\u0442 tests\/parsert.rs<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"rust\">use guidzy::lexer::Lexer;use guidzy::parser::Parser;#[test]fn main() {    let source = \"2 + 2 * 2 &gt; 4 \/ 2 + 2 &amp;&amp; true != false(2 + 2) * 2\"    .trim();    let tokens = Lexer::new(source).tokenize();    println!(\"Source: {}\\nTokens:\", source);    for tkn in &amp;tokens {        println!(\"{:?}\", tkn);    }    let exprs = Parser::new(tokens, source).parse_exprs();    println!(\"Expressions:\");    for ex in exprs {        println!(\"{}\", ex);    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u0418 \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u044b\u0432\u043e\u0434 \u0442\u0430\u043a\u043e\u0439:<\/p>\n<pre><code>Source: 2 + 2 * 2 &gt; 4 \/ 2 + 2 &amp;&amp; true != false(2 + 2) * 2Tokens:Token { kind: NumLit(2.0), len: 1, pos: 0, line: 0, offset: 0 }Token { kind: Plus, len: 1, pos: 2, line: 0, offset: 2 }Token { kind: NumLit(2.0), len: 1, pos: 4, line: 0, offset: 4 }Token { kind: Star, len: 1, pos: 6, line: 0, offset: 6 }Token { kind: NumLit(2.0), len: 1, pos: 8, line: 0, offset: 8 }Token { kind: Gt, len: 1, pos: 10, line: 0, offset: 10 }Token { kind: NumLit(4.0), len: 1, pos: 12, line: 0, offset: 12 }Token { kind: Slash, len: 1, pos: 14, line: 0, offset: 14 }Token { kind: NumLit(2.0), len: 1, pos: 16, line: 0, offset: 16 }Token { kind: Plus, len: 1, pos: 18, line: 0, offset: 18 }Token { kind: NumLit(2.0), len: 1, pos: 20, line: 0, offset: 20 }Token { kind: And, len: 2, pos: 22, line: 0, offset: 22 }Token { kind: Bool(true), len: 6, pos: 25, line: 0, offset: 25 }Token { kind: Ne, len: 2, pos: 30, line: 0, offset: 30 }Token { kind: Bool(false), len: 7, pos: 33, line: 0, offset: 33 }Token { kind: LParen, len: 1, pos: 39, line: 1, offset: 0 }Token { kind: NumLit(2.0), len: 1, pos: 40, line: 1, offset: 1 }Token { kind: Plus, len: 1, pos: 42, line: 1, offset: 3 }Token { kind: NumLit(2.0), len: 1, pos: 44, line: 1, offset: 5 }Token { kind: RParen, len: 1, pos: 45, line: 1, offset: 6 }Token { kind: Star, len: 1, pos: 47, line: 1, offset: 8 }Token { kind: NumLit(2.0), len: 1, pos: 49, line: 1, offset: 10 }Token { kind: Eof, len: 1, pos: 50, line: 1, offset: 11 }Expressions:(((2 + (2 * 2)) &gt; ((4 \/ 2) + 2)) &amp;&amp; (true != false))((2 + 2) * 2)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h2>\u0418\u0442\u043e\u0433<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0430\u0440\u0441\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0430\u0440\u0441\u0438\u0442 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u043e \u0441\u043a\u043e\u0431\u043a\u0430\u043c\u0438 \u0438 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \ud83d\ude00<\/p>\n<p>\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0443\u0436\u0435 \u0431\u0443\u0434\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u0430\u0440\u0441\u0435\u0440 \u0434\u043b\u044f \u0441\u0442\u0435\u0439\u0442\u043c\u0435\u043d\u0442\u043e\u0432.<\/p>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 <a href=\"https:\/\/github.com\/KiquarSL\/Gudzy\/tree\/c31bf133ac5cfda1df6eac59f3b2f4f5ddf25812\" rel=\"noopener noreferrer nofollow\">\u044d\u0442\u043e\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438.<\/a><\/p>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1044502\/\">https:\/\/habr.com\/ru\/articles\/1044502\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440!\u0427\u0442\u043e \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c?\u041c\u044b \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043f\u0430\u0440\u0441\u0435\u0440 \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a\u0438\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439: 1+2*(2+8)*2*a+3. \u0421\u043d\u0430\u0447\u0430\u043b\u043e \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0430\u0440\u0441\u0435\u0440 \u0434\u043b\u044f \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439, \u0430 \u043f\u043e\u0441\u043b\u0435 \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u0437\u0430\u0439\u043c\u0435\u043c\u0441\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f\u043c\u0438 \u0438 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c\u0438. \u041a\u0430\u043a \u043f\u0438\u0441\u0430\u043b \u0440\u0430\u043d\u0435\u0435, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0430\u0440\u0441\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u043e\u043c \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u0441\u043f\u0443\u0441\u043a\u0430, \u0438 \u0442\u0430\u043c \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432. \u0421\u043d\u0430\u0447\u0430\u043b\u043e *\/, \u0430 \u043f\u043e\u0442\u043e\u043c +-. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u0430\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0430: primary -&gt; unary -&gt; additive -&gt; multiplicative -&gt; comparison -&gt; logical. \u0421\u0430\u043c\u0438 \u043e\u0431\u044c\u0435\u043a\u0442\u044b \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0431\u0443\u0434\u0443\u0442 \u0442\u0438\u043f\u0430 enum Expr. \u0411\u0443\u0434\u0443\u0442 \u0442\u0430\u043a\u0438\u0435 \u0442\u0438\u043f\u044b:Expr::Num(f64) &#8212; \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u0447\u0438\u0441\u043b\u043e, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 primary\u0395xpr::Bool(bool) &#8212; \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 primaryExpr::Str(String) &#8212; \u043b\u0438\u0442\u0435\u0440\u0430\u043b \u0441\u0442\u0440\u043e\u043a\u0438, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 primaryExpr::Id(String) &#8212; \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 primaryExpr::Unary(UnaryOp, Box&lt;Expr&gt;) &#8212; \u0443\u043d\u0430\u0440\u043d\u0432\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0438 \u043d\u043e\u0432\u043e\u0435 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 &#8212; UnaryOp: Neg (-) \u0438 Not (!). \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 unary.Expr::Arith(Box&lt;Expr&gt;, ArithOp, Box&lt;Expr&gt;) &#8212; \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f. \u0422\u0443\u0442 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u043c \u0435\u0449\u0435 \u043e\u0434\u043d\u043e \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 &#8212; ArithOp: Add, Sub, Mul \u0438 Div. \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 multiplicative \u0438 additiveExpr::Comp(Box&lt;Expr&gt;, CompOp, Box&lt;Expr&gt;) &#8212; \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0442\u0430 \u0436\u0435, \u043d\u043e \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u043d\u043e\u0432\u043e\u0435 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 &#8212; CompOp: Gt (&gt;), Ge (&gt;=), Lt (&lt;), Le (&lt;=), Eq (==), Ne (!=). \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 comparison.Expr::Logic(Box&lt;Expr&gt;, LogicOp, Box&lt;Expr&gt;) &#8212; \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435. \u0422\u0443\u0442 \u0442\u0430\u043a\u0436\u0435 \u043d\u043e\u0432\u043e\u0435 \u043f\u0435\u0440\u0435\u0447\u0442\u0441\u043b\u0435\u043d\u0438\u0435 &#8212; LogicOp: And (&amp;&amp;) \u0438 Or (||). \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 logical\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u043b, \u043d\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u044e\u0441\u044c. primary &#8212; \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c, \u043c\u043e\u0436\u0435\u0442 \u043b\u0438 \u044d\u0442\u043e\u0442 \u0442\u043e\u043a\u0435\u0433 \u0431\u044b\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0438. \u042d\u0442\u043e \u043c\u043e\u0436\u0433\u0443\u0442 \u0431\u044b\u0442\u044c: \u0447\u0438\u0441\u043b\u0430, \u0441\u0442\u0440\u043e\u043a\u0438, \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b, \u0432\u044b\u0437\u043e\u0432\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0441\u043a\u043e\u0431\u043a\u0438 (\u0422\u043e\u0447\u043d\u0435\u0435, \u0438\u0445 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435). \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c Num, Str, Id. \u0421\u0447\u0438\u0442\u0430\u044f \u0441\u043a\u043e\u0431\u043a\u0438, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043b\u044e\u0431\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435.unary &#8212; \u0442\u0443\u0442 \u043c\u044b \u0431\u0435\u0440\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, !,  \u0442\u043e \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0435\u0433\u043e, \u0432\u044b\u0437\u0432\u0432\u0430\u0435\u043c primary, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c Expr::Unary.multiplicative &#8212; \u0442\u0443\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u0432\u0441\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441 \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u0438 \u0434\u0435\u043b\u0435\u043d\u0438\u0435\u043c \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0432\u044b\u0440\u0430\u044d\u0435\u043d\u0438\u0435. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c Expr::Arithadditive &#8212; \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0432\u044b\u0447\u0438\u0442\u0430\u043d\u0438\u044f. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c Expr::Arith\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u043f\u0438\u0441\u0430\u0442\u044c!\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c &#8212; parser. \u0422\u0430\u043c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u0444\u0430\u0439\u043b\u044b expr.rs, parser.rs \u0438 mod.rs. \u0421\u043d\u0430\u0447\u0430\u043b\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u043d\u0430\u043f\u0438\u0448\u0435\u043c mod.rs. (\u041d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u043e, \u0434\u0430?)\u041f\u043e\u043a\u0430\u0436\u0443 \u0441\u0440\u0430\u0437\u0443 \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u0439.parser\/mod.rspub mod expr;mod parser;pub use parser::Parser;#[derive(Debug, Clone)]pub struct Info {    pub line: usize,    pub offset: usize,    pub len: usize,}#[macro_export]macro_rules! info {    ($line:expr, $offset:expr, $len:expr) =&gt; {        $crate::parser::Info {            line: $line,            offset: $offset,            len: $len,        }    };    ($tkn:expr) =&gt; {        info!($tkn.line, $tkn.offset, $tkn.len)    };}\u0414\u043b\u044f Expr, \u043d\u0430\u043c \u0442\u043e\u0436\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f, \u0438 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 Info. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0435\u0435, \u043c\u044b \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0442\u043b\u0430\u0434\u043a\u0443 \u0432 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0438\u0442\u0430\u0442\u043e\u0440\u0435, \u0430 \u0442\u0430\u043a \u043a\u0430\u043a \u0438 \u0441\u0442\u0435\u0439\u0442\u043c\u0435\u043d\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430\u043c\u0438, \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0435\u0433\u043e \u0432 mod.rs. \u0422\u0430\u043a\u0436\u0435 \u0442\u0443\u0442 \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043c\u0430\u043a\u0440\u043e\u0441, \u043e\u043d \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043e\u0431\u044c\u0435\u043a\u0442 Info. \u0410 \u0434\u043b\u0438\u043d\u043d\u044b\u0439, \u0433\u0434\u0435 \u043c\u044b \u0432 \u0440\u0443\u0447\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u043c\u044b \u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0434\u043b\u044f \u0441\u0442\u0435\u0439\u0442\u043c\u0435\u043d\u0442\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0438 \u0438\u0445 \u043e\u0442\u043b\u0430\u0436\u0438\u0432\u0430\u0442\u044c.parser\/expr.rsuse super::Info;pub type BExpr = Box&lt;Expr&gt;;#[derive(Debug, Clone)]pub enum Expr {    Num(f64, Info),    Str(String, Info),    Id(String, Info),    Bool(bool, Info),    Unary(UnaryOp, BExpr, Info),    Arith(BExpr, ArithOp, BExpr, Info),    Comp(BExpr, CompOp, BExpr, Info),    Logic(BExpr, LogicOp, BExpr, Info),}impl Expr {    pub fn info(&amp;self) -&gt; Info {        match self {            Expr::Str(_, info) =&gt; info.clone(),            Expr::Num(_, info) =&gt; info.clone(),            Expr::Id(_, info) =&gt; info.clone(),            Expr::Bool(_, info) =&gt; info.clone(),            Expr::Arith(_, _, _, info) =&gt; info.clone(),            Expr::Comp(_, _, _, info) =&gt; info.clone(),            Expr::Logic(_, _, _, info) =&gt; info.clone(),            Expr::Unary(_, _, info) =&gt; info.clone(),        }    }}#[derive(Debug, Clone)]pub enum ArithOp {    Add, \/\/ +    Sub, \/\/ &#8212;    Mul, \/\/ *    Div, \/\/ \/}#[derive(Debug, Clone)]pub enum CompOp {    Gt, \/\/ &gt;    Ge, \/\/ &gt;=    Lt, \/\/ &lt;    Le, \/\/ &lt;=    Eq, \/\/ ==    Ne, \/\/ !=}#[derive(Debug, Clone)]pub enum LogicOp {    And, \/\/ &amp;&amp;    Or,  \/\/ ||}#[derive(Debug, Clone)]pub enum UnaryOp {    Not, \/\/ !    Neg, \/\/ -}\u042f \u0441\u043e\u0437\u0434\u0430\u043b \u0442\u0438\u043f BExpr, \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043d\u0435 \u043f\u0438\u0441\u0430\u0442\u044c Box&lt;Expr&gt;. \u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435 \u0442\u0443\u0442 \u0435\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432: ArithOp, CompOp, LogicOp. \u0422\u0430\u043a\u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u043f\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 &#8212; Expr. \u042f \u0440\u0430\u043d\u0435\u0435 \u0443\u0436\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u044d\u0442\u043e, \u0442\u0430\u043a \u0447\u0442\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c\u0441\u044f \u043d\u0435 \u0431\u0443\u0434\u0443. \u041c\u0435\u0442\u043e\u0434 info \u0442\u0443\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442 \u0438\u043d\u0444\u043e \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0432\u0432\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0438\u0445 \u0443\u0434\u043e\u0431\u043d\u0435\u0435. (\u0423\u0432\u0438\u0434\u0438\u0442\u0438 \u0432\u043e\u043e\u0431\u0449\u0435\u043c)\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0441\u0442\u0443\u043a\u0442\u0443\u0440\u0443 Parser.parser\/parser.rsuse super::expr::{ArithOp, BExpr, CompOp, Expr, LogicOp};use crate::lexer::token::{TKind, Token};pub struct Parser&lt;&#8216;a&gt; {    pos: usize,    tokens: Vec&lt;Token&gt;,    lines: Vec&lt;&amp;&#8217;a str&gt;,}impl&lt;&#8216;a&gt; Parser&lt;&#8216;a&gt; {    pub fn new(tokens: Vec&lt;Token&gt;, source: &amp;&#8217;a str) -&gt; Self {        let lines: Vec&lt;&amp;str&gt; = source.lines().collect();        Self {            tokens,            pos: 0,            lines,        }    }}\u0417\u0430\u0440\u0430\u043d\u0435\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c Expr \u0438 \u0435\u0433\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 Token \u0438 TKind (\u0432\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c TokenKind). \u0412 \u043c\u0435\u0442\u043e\u0434 new \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0442\u043e\u043a\u0435\u043d\u044b, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0435\u043c \u0441\u0442\u0440\u043e\u0438\u0442\u044c AST (Abstract Syntax Tree) \u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0441\u0442\u0440\u043e\u043a\u0438. lines \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0442\u0430\u043a\u0436\u0435 \u0434\u043b\u044f \u043e\u0448\u0438\u0431\u043e\u043a, \u043a\u0430\u043a \u0438 \u0432 \u043b\u0435\u043a\u0441\u0435\u0440\u0435.\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b. \u0418\u0445 \u0431\u0443\u0434\u0435\u0442 \u043c\u0435\u043d\u044c\u0448\u0435 \u0438 \u0431\u0443\u0434\u0443 \u043f\u0440\u043e\u0449\u0435 (\u043d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435).parser\/parser.rs: Parseruse std::mem::discriminant;&#8230;fn check(&amp;mut self, kind: TKind) -&gt; bool {    if discriminant(&amp;self.peek(0).kind) == discriminant(&amp;kind) {        self.advance(1);        true    } else {        false    }}fn error(&amp;self, msg: &amp;str, token: Token) -&gt; String {    let line = self.lines[token.line];    let header = format!(&#171;Error in {}:{} &#8212; {msg}&#187;, token.line, token.offset);    let err_line = format!(&#171;{} | {line}&#187;, token.line);    let point = format!(        &#171;{} | {}{}&#187;,        &#187; &#171;.repeat(token.line.to_string().len()),        &#187; &#171;.repeat(token.offset),        &#171;^&#187;.repeat(token.len),    );    format!(&#171;{header}\\n{err_line}\\n{point}\\n&#187;)}fn peek(&amp;self, offset: i8) -&gt; Token {    let idx = self.pos + offset as usize;    self.tokens.get(idx).unwrap().clone()}fn advance(&amp;mut self, offset: u8) {    self.pos += offset as usize;}\u0412 advance \u043c\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e self.pos. \u0412 peek \u044f \u0440\u0435\u0448\u0438\u043b \u0443\u0431\u0440\u0430\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043b unwrap. \u0421\u043d\u043e\u0432\u0430 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0443: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0435\u0433\u043e \u043d\u0430 \u0441\u0432\u043e\u0439 \u0441\u0442\u0440\u0430\u0445 \u0438 \u0440\u0438\u0441\u043a, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u043e\u0432. \u041d\u043e \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430, \u043c\u044b \u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0435\u0433\u043e.\u0412 error \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043a\u0435\u043d, \u0438 \u0431\u0443\u0434\u0435\u043c \u0431\u0440\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0438\u0437 \u043d\u0435\u0433\u043e.check \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043b\u0438 \u0442\u0438\u043f \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043e\u043c\u0443, \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0443\u0441\u043f\u0435\u0445\u0430 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0435\u0433\u043e \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c true, \u0430 \u0432 \u0438\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c false. discriminant \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d, \u0447\u0442\u043e\u0431\u044b \u0441\u0440\u0430\u043d\u0438\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0438\u043f \u0442\u043e\u043a\u0435\u043d\u0430, \u0430 \u043d\u0435 \u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435. \u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0430\u0440\u0441\u0438\u043d\u0433!\u041d\u0430\u0447\u043d\u0435\u043c \u0441 primary.parser\/parser.rs: Parser.primaryfn primary(&amp;mut self) -&gt; Expr {    let current = self.peek(0);    match current.kind {        TKind::NumLit(n) =&gt; {            self.advance(1);            Expr::Num(n, info!(current))        }        TKind::StrLit(s) =&gt; {            self.advance(1);            Expr::Str(s, info!(current))        }        TKind::Id(id) =&gt; {            self.advance(1);            Expr::Id(id, info!(current))        }        TKind::Bool(truth) =&gt; {            self.advance(1);            Expr::Bool(truth, info!(current))        }        _ =&gt; panic!(&#171;{}&#187;, self.error(&#171;Unexpected token in primary&#187;, current)),    }}\u041c\u044b \u0431\u0435\u0440\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0435\u0433\u043e. \u0415\u0441\u043b\u0438 \u043e\u043d \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0432 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0438, \u0442\u043e \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0435\u0433\u043e \u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043e\u0431\u044c\u0435\u043a\u0442 Expr. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435 \u0432\u0430\u043b\u0438\u0434\u043d\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430 \u043f\u0430\u043d\u0438\u043a\u0443\u0435\u043c \u043d\u0430 \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u044b\u0439 \u0442\u043e\u043a\u0435\u043d. \u0421\u043a\u043e\u0431\u043a\u0438 \u0442\u0430\u043a\u0436\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0437\u0434\u0435\u0441\u044c, \u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0438\u0445 \u043f\u043e\u0437\u0436\u0435.parser\/parser.rs: Parser.unaryfn unary(&amp;mut self) -&gt; Expr {    let current = self.peek(0);    match current.kind {        TKind::Minus =&gt; {            self.advance(1);            let primary = self.primary();            let info = primary.info();            let info = info!(info.line, info.offset &#8212; 1, info.len + 1);            Expr::Unary(UnaryOp::Neg, Box::new(primary), info)        }        TKind::Bang =&gt; {            self.advance(1);            let primary = self.primary();            let info = primary.info();            let info = info!(info.line, info.offset &#8212; 1, info.len + 1);            Expr::Unary(UnaryOp::Not, Box::new(primary), info)        }        _ =&gt; self.primary(),    }}\u0422\u0443\u0442 \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e &#8212; \u0438\u043b\u0438 !, \u0442\u043e \u0441\u043e\u043e\u0442\u0430\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c Expr::Unary, \u0432 \u0438\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043e\u0431\u044b\u0447\u043d\u044b\u0439 primary. \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0432 \u0432\u043e\u0437\u043c\u0435\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0441 TKind::Minus.TKind::Minus =&gt; {    self.advance(1);    let primary = self.primary();    let info = primary.info();    let info = info!(info.line, info.offset &#8212; 1, info.len + 1);    Expr::Unary(UnaryOp::Neg, Box::new(primary), info)}\u041c\u044b \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0442\u043e\u043a\u0435\u043d (\u043c\u0438\u043d\u0443\u0441) \u0438 \u0431\u0435\u0440\u0435\u043c primary. \u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c Info. \u041f\u0440\u043e\u0441\u0442\u043e \u0432\u0437\u044f\u0442\u044c info!(primary) \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u0438\u043d\u0443\u0441 \u0442\u043e\u0436\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0445\u043e\u0434\u0438\u0442\u044c \u0432 Info. \u0422\u0430\u043a \u0447\u0442\u043e \u0431\u0435\u0440\u0435\u043c Info \u0438\u0437 primary, \u0432 \u043c\u0430\u043a\u0440\u043e\u0441 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u043d\u043e\u043c\u0435\u0440 \u0441\u0442\u0440\u043e\u043a\u0438, \u043e\u0442\u0441\u0442\u0443\u043f \u043e\u0442 \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u0442\u0440\u043e\u043a\u0438 &#8212; 1. \u041e\u0442\u043d\u0438\u043c\u0430\u0435\u043c 1, \u0442\u0430\u043a \u043a\u0430\u043a primary \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u0443\u043d\u0430\u0440\u043d\u043e\u0433\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430, \u0438 \u0442\u0430\u043c \u043c\u044b \u0437\u0430\u0445\u0432\u0430\u0442\u0438\u043c \u0438 \u0441\u0430\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440. \u0412 \u0434\u043b\u0438\u043d\u043d\u0443 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0434\u043b\u0438\u043d\u043d\u0443 primary + 1, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0440\u043e\u0432\u043d\u044f\u0442\u044c. \u0412 \u043a\u043e\u043d\u0446\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u044b\u0439 primary \u0438 Info, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438. \u0421 TKind \u043b\u043e\u0433\u0438\u043a\u0430 \u0441\u0445\u043e\u0436\u0430, \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c UnaryOp::Not.\u0422\u0435\u043f\u0435\u0440\u044c \u0438 multiplicative.fn multiplicative(&amp;mut self) -&gt; Expr {    let mut left = self.unary();    loop {        let op_token = self.peek(0);        let op = match op_token.kind {            TKind::Star =&gt; ArithOp::Mul,            TKind::Slash =&gt; ArithOp::Div,            _ =&gt; break,        };        self.advance(1);        let right = self.unary();        left = Expr::Arith(Box::new(left), op,&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-482676","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/482676","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=482676"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/482676\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=482676"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=482676"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=482676"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}