ps_parser/
parser.rs

1mod command;
2mod error;
3mod predicates;
4mod script_result;
5mod stream_message;
6mod token;
7mod value;
8mod variables;
9use std::collections::HashMap;
10
11pub(crate) use command::CommandError;
12use command::{Command, CommandElem};
13pub(crate) use stream_message::StreamMessage;
14use value::{
15    ClassProperties, ClassType, MethodName, Param, RuntimeObjectTrait, ScriptBlock, ValResult,
16};
17use variables::{Scope, SessionScope};
18type ParserResult<T> = core::result::Result<T, ParserError>;
19use error::ParserError;
20type PestError = pest::error::Error<Rule>;
21use pest::Parser;
22use pest_derive::Parser;
23use predicates::{ArithmeticPred, BitwisePred, LogicalPred, StringPred};
24pub use script_result::{PsValue, ScriptResult};
25pub use token::{CommandToken, ExpressionToken, MethodToken, StringExpandableToken, Token, Tokens};
26pub(crate) use value::Val;
27use value::ValType;
28pub use variables::Variables;
29use variables::{VarName, VariableError};
30
31use crate::parser::{command::CommandOutput, value::RuntimeError};
32
33type Pair<'i> = ::pest::iterators::Pair<'i, Rule>;
34type Pairs<'i> = ::pest::iterators::Pairs<'i, Rule>;
35
36pub(crate) const NEWLINE: &str = "\n";
37
38macro_rules! unexpected_token {
39    ($pair:expr) => {
40        panic!("Unexpected token: {:?}", $pair.as_rule())
41    };
42}
43
44macro_rules! check_rule {
45    ($pair:expr, $rule:pat) => {
46        if !matches!($pair.as_rule(), $rule) {
47            panic!(
48                "Unexpected token: {:?}, instead of {}",
49                $pair.as_rule(),
50                stringify!($rule)
51            );
52        }
53    };
54}
55
56macro_rules! not_implemented {
57    ($token:expr) => {
58        Err(ParserError::NotImplemented(format!(
59            "Not implemented: {:?}",
60            $token.as_rule()
61        )))
62    };
63}
64
65#[derive(Default, Clone)]
66pub(crate) struct Results {
67    output: Vec<StreamMessage>,
68    deobfuscated: Vec<String>,
69}
70
71impl Results {
72    fn new() -> Self {
73        Self {
74            output: Vec::new(),
75            deobfuscated: Vec::new(),
76        }
77    }
78}
79
80#[derive(Parser)]
81#[grammar = "powershell.pest"]
82pub struct PowerShellSession {
83    variables: Variables,
84    tokens: Tokens,
85    errors: Vec<ParserError>,
86    results: Vec<Results>,
87    skip_error: u32,
88}
89
90impl Default for PowerShellSession {
91    fn default() -> Self {
92        Self::new()
93    }
94}
95
96impl<'a> PowerShellSession {
97    /// Creates a new PowerShell parsing session with default settings.
98    ///
99    /// The session is initialized with built-in variables like `$true`,
100    /// `$false`, `$null`, and special variables like `$?` for error status
101    /// tracking.
102    ///
103    /// # Returns
104    ///
105    /// A new `PowerShellSession` instance ready for script evaluation.
106    ///
107    /// # Examples
108    ///
109    /// ```rust
110    /// use ps_parser::PowerShellSession;
111    ///
112    /// let mut session = PowerShellSession::new();
113    /// let result = session.safe_eval("$true").unwrap();
114    /// assert_eq!(result, "True");
115    /// ```
116    pub fn new() -> Self {
117        Self {
118            variables: Variables::new(),
119            tokens: Tokens::new(),
120            errors: Vec::new(),
121            results: Vec::new(),
122            skip_error: 0,
123        }
124    }
125
126    /// Creates a new PowerShell session with the provided variables.
127    ///
128    /// This constructor allows you to initialize the session with a custom set
129    /// of variables, such as environment variables or variables loaded from
130    /// configuration files.
131    ///
132    /// # Arguments
133    ///
134    /// * `variables` - A `Variables` instance containing the initial variable
135    ///   set.
136    ///
137    /// # Returns
138    ///
139    /// A new `PowerShellSession` instance with the provided variables.
140    ///
141    /// # Examples
142    ///
143    /// ```rust
144    /// use ps_parser::{PowerShellSession, Variables};
145    ///
146    /// let env_vars = Variables::env();
147    /// let mut session = PowerShellSession::new().with_variables(env_vars);
148    /// let username = session.safe_eval("$env:USERNAME").unwrap();
149    /// ```
150    pub fn with_variables(mut self, variables: Variables) -> Self {
151        self.variables = variables;
152        self
153    }
154
155    /// Safely evaluates a PowerShell script and returns the output as a string.
156    ///
157    /// This method parses and evaluates the provided PowerShell script,
158    /// handling errors gracefully and returning the result as a formatted
159    /// string. It's the recommended method for simple script evaluation.
160    ///
161    /// # Arguments
162    ///
163    /// * `script` - A string slice containing the PowerShell script to
164    ///   evaluate.
165    ///
166    /// # Returns
167    ///
168    /// * `Result<String, ParserError>` - The output of the script evaluation,
169    ///   or an error if parsing/evaluation fails.
170    ///
171    /// # Examples
172    ///
173    /// ```rust
174    /// use ps_parser::PowerShellSession;
175    ///
176    /// let mut session = PowerShellSession::new();
177    ///
178    /// // Simple arithmetic
179    /// let result = session.safe_eval("1 + 2 * 3").unwrap();
180    /// assert_eq!(result, "7");
181    ///
182    /// // Variable assignment and retrieval
183    /// let result = session.safe_eval("$name = 'World'; \"Hello $name\"").unwrap();
184    /// assert_eq!(result, "Hello World");
185    /// ```
186    pub fn safe_eval(&mut self, script: &str) -> Result<String, ParserError> {
187        let script_res = self.parse_input(script)?;
188        Ok(script_res.result().to_string())
189    }
190
191    pub fn deobfuscate_script(&mut self, script: &str) -> Result<String, ParserError> {
192        self.push_scope_session();
193        let script_res = self.parse_input(script)?;
194        self.pop_scope_session();
195        Ok(script_res.deobfuscated().to_string())
196    }
197
198    pub fn env_variables(&self) -> HashMap<String, PsValue> {
199        self.variables
200            .get_env()
201            .into_iter()
202            .map(|(k, v)| (k, v.into()))
203            .collect()
204    }
205
206    pub fn session_variables(&self) -> HashMap<String, PsValue> {
207        self.variables
208            .get_global()
209            .into_iter()
210            .map(|(k, v)| (k, v.into()))
211            .collect()
212    }
213
214    /// Parses and evaluates a PowerShell script, returning detailed results.
215    ///
216    /// This method provides comprehensive information about the parsing and
217    /// evaluation process, including the final result, generated output,
218    /// any errors encountered, and the tokenized representation of the
219    /// script. It's particularly useful for debugging and deobfuscation.
220    ///
221    /// # Arguments
222    ///
223    /// * `input` - A string slice containing the PowerShell script to parse and
224    ///   evaluate.
225    ///
226    /// # Returns
227    ///
228    /// * `Result<ScriptResult, ParserError>` - A detailed result containing the
229    ///   evaluation outcome, output, errors, and tokens, or a parsing error if
230    ///   the script is malformed.
231    ///
232    /// # Examples
233    ///
234    /// ```rust
235    /// use ps_parser::PowerShellSession;
236    ///
237    /// let mut session = PowerShellSession::new();
238    /// let script_result = session.parse_input("$a = 42; Write-Output $a").unwrap();
239    ///
240    /// println!("Final result: {:?}", script_result.result());
241    /// println!("Generated output: {:?}", script_result.output());
242    /// println!("Parsing errors: {:?}", script_result.errors());
243    /// println!("Deobfuscated code: {:?}", script_result.deobfuscated());
244    /// ```
245    pub fn parse_input(&mut self, input: &str) -> Result<ScriptResult, ParserError> {
246        self.variables.init();
247        let (script_last_output, mut result) = self.parse_subscript(input)?;
248        self.variables.clear_script_functions();
249        Ok(ScriptResult::new(
250            script_last_output,
251            std::mem::take(&mut result.output),
252            std::mem::take(&mut result.deobfuscated),
253            std::mem::take(&mut self.tokens),
254            std::mem::take(&mut self.errors),
255            self.variables
256                .script_scope()
257                .into_iter()
258                .map(|(k, v)| (k, v.into()))
259                .collect(),
260        ))
261    }
262
263    pub(crate) fn parse_subscript(&mut self, input: &str) -> Result<(Val, Results), ParserError> {
264        let mut pairs = PowerShellSession::parse(Rule::program, input)?;
265        //create new scope for script
266        self.results.push(Results::new());
267
268        let program_token = pairs.next().expect("");
269
270        let mut script_last_output = Val::default();
271
272        if let Rule::program = program_token.as_rule() {
273            let mut pairs = program_token.into_inner();
274            let _script_param_block_token = pairs.next().unwrap();
275            if let Some(named_blocks) = pairs.peek()
276                && named_blocks.as_rule() == Rule::named_blocks
277            {
278                //todo
279                let _ = pairs.next();
280            }
281            for token in pairs {
282                let token_str = token.as_str();
283                match token.as_rule() {
284                    Rule::statement_terminator => continue,
285                    Rule::EOI => break,
286                    _ => {}
287                };
288
289                let result = self.eval_statement(token.clone());
290                self.variables.set_status(result.is_ok());
291
292                if let Ok(Val::NonDisplayed(_)) = &result {
293                    continue;
294                }
295
296                script_last_output = match result {
297                    Ok(val) => {
298                        if val != Val::Null {
299                            self.add_output_statement(val.display().into());
300                            self.add_deobfuscated_statement(val.cast_to_script());
301                        }
302
303                        val
304                    }
305                    Err(e) => {
306                        self.errors.push(e);
307                        self.add_deobfuscated_statement(token_str.into());
308                        Val::Null
309                    }
310                };
311            }
312        }
313
314        Ok((script_last_output, self.results.pop().unwrap_or_default()))
315    }
316
317    fn add_function(
318        &mut self,
319        name: String,
320        func: ScriptBlock,
321        scope: Option<Scope>,
322    ) -> ParserResult<Val> {
323        // let func_str= func.to_function(&name, &scope);
324        // self.add_deobfuscated_statement(func_str);
325
326        if let Some(Scope::Global) = &scope {
327            self.variables.add_global_function(name.clone(), func);
328        } else {
329            self.variables.add_script_function(name.clone(), func);
330        }
331
332        Err(ParserError::Skip)
333    }
334
335    pub(crate) fn parse_function_statement(&mut self, token: Pair<'a>) -> ParserResult<Val> {
336        check_rule!(token, Rule::function_statement);
337
338        let mut pair = token.into_inner();
339
340        let function_keyword_token = pair.next().unwrap();
341        check_rule!(function_keyword_token, Rule::function_keyword);
342
343        let mut next_token = pair.next().unwrap();
344        let scope = if next_token.as_rule() == Rule::scope_keyword {
345            let scope = Scope::from(next_token.as_str());
346            next_token = pair.next().unwrap();
347            Some(scope)
348        } else {
349            None
350        };
351
352        let function_name_token = next_token;
353        check_rule!(function_name_token, Rule::function_name);
354        let fname = function_name_token.as_str().to_ascii_lowercase();
355
356        let Some(mut next_token) = pair.next() else {
357            //empty function
358            return self.add_function(fname, ScriptBlock::empty(), scope);
359        };
360
361        let params = if next_token.as_rule() == Rule::parameter_list {
362            let param_list = self.parse_parameter_list(next_token)?;
363            if let Some(token) = pair.next() {
364                next_token = token;
365            } else {
366                return self.add_function(fname, ScriptBlock::empty(), scope);
367            }
368
369            param_list
370        } else {
371            Vec::new()
372        };
373        check_rule!(next_token, Rule::script_block);
374
375        let mut script_block = self.parse_script_block(next_token)?;
376
377        if script_block.params.0.is_empty() {
378            script_block = script_block.with_params(params);
379        }
380
381        self.add_function(fname, script_block, scope)
382    }
383
384    pub(crate) fn eval_if_statement(&mut self, token: Pair<'a>) -> ParserResult<Val> {
385        check_rule!(token, Rule::if_statement);
386
387        //collect tokens from each case
388        self.if_statement_collect_tokens(token.clone());
389
390        let mut pair = token.into_inner();
391        let condition_token = pair.next().unwrap();
392        let true_token = pair.next().unwrap();
393        let condition_val = self.eval_pipeline(condition_token.clone())?;
394        let res = if condition_val.cast_to_bool() {
395            self.eval_statement_block(true_token)?
396        } else if let Some(mut token) = pair.next() {
397            if token.as_rule() == Rule::elseif_clauses {
398                for else_if in token.into_inner() {
399                    let mut pairs = else_if.into_inner();
400                    let condition_token = pairs.next().unwrap();
401                    let statement_token = pairs.next().unwrap();
402                    let condition_val = self.eval_pipeline(condition_token)?;
403                    if condition_val.cast_to_bool() {
404                        return self.eval_statement_block(statement_token);
405                    }
406                }
407                let Some(token2) = pair.next() else {
408                    return Ok(Val::Null);
409                };
410                token = token2;
411            }
412            if token.as_rule() == Rule::else_condition {
413                let statement_token = token.into_inner().next().unwrap();
414                self.eval_statement_block(statement_token)?
415            } else {
416                Val::Null
417            }
418        } else {
419            Val::Null
420        };
421
422        Ok(res)
423    }
424
425    pub(crate) fn if_statement_collect_tokens(&mut self, token: Pair<'a>) {
426        //we want collect tokens from each case, but we need to preserve all variables
427        //to consider: maybe instead of collecting tokens, we should return whole
428        // deobfuscated if statement
429        let results = self.results.clone();
430        let current_variables = self.variables.clone();
431        if let Err(err) = self.impl_if_statement_collect_tokens(token.clone()) {
432            log::debug!("Error during if_statement_collect_tokens: {:?}", err);
433        }
434        self.variables = current_variables;
435        self.results = results;
436    }
437
438    pub(crate) fn impl_if_statement_collect_tokens(&mut self, token: Pair<'a>) -> ParserResult<()> {
439        check_rule!(token, Rule::if_statement);
440
441        let mut pair = token.into_inner();
442        let condition_token = pair.next().unwrap();
443        let true_token = pair.next().unwrap();
444        let _condition_val = self.eval_pipeline(condition_token.clone())?;
445        if let Err(err) = self.eval_statement_block(true_token) {
446            log::debug!(
447                "Error during if_statement_collect_tokens (true block): {:?}",
448                err
449            );
450        }
451        if let Some(mut token) = pair.next() {
452            if token.as_rule() == Rule::elseif_clauses {
453                for else_if in token.into_inner() {
454                    let mut pairs = else_if.into_inner();
455                    let condition_token = pairs.next().unwrap();
456                    let statement_token = pairs.next().unwrap();
457                    let _condition_val = self.eval_pipeline(condition_token)?;
458
459                    if let Err(err) = self.eval_statement_block(statement_token) {
460                        log::debug!(
461                            "Error during if_statement_collect_tokens (else if block): {:?}",
462                            err
463                        );
464                    }
465                }
466                let Some(token2) = pair.next() else {
467                    return Ok(());
468                };
469                token = token2;
470            }
471            if token.as_rule() == Rule::else_condition {
472                let statement_token = token.into_inner().next().unwrap();
473                if let Err(err) = self.eval_statement_block(statement_token) {
474                    log::debug!(
475                        "Error during if_statement_collect_tokens (else block): {:?}",
476                        err
477                    );
478                }
479            }
480        }
481        Ok(())
482    }
483
484    fn eval_flow_control_statement(&mut self, token: Pair<'a>) -> ParserResult<Val> {
485        check_rule!(token, Rule::flow_control_statement);
486        let token = token.into_inner().next().unwrap();
487
488        Ok(match token.as_rule() {
489            Rule::flow_control_label_statement => Val::Null, //TODO
490            Rule::flow_control_pipeline_statement => {
491                let token = token.into_inner().next().unwrap();
492                //todo: throw, return or exit
493                if let Some(pipeline_token) = token.into_inner().next() {
494                    self.eval_pipeline(pipeline_token)?
495                } else {
496                    Val::Null
497                }
498            }
499            _ => unexpected_token!(token),
500        })
501    }
502
503    fn parse_class_statement(&mut self, token: Pair<'a>) -> ParserResult<Val> {
504        check_rule!(token, Rule::class_statement);
505        let mut pair = token.into_inner();
506
507        let class_name_token = pair.next().unwrap();
508        check_rule!(class_name_token, Rule::simple_name);
509        let class_name = class_name_token.as_str().to_string();
510
511        let mut properties = ClassProperties::new();
512        let mut methods: HashMap<String, ScriptBlock> = HashMap::new();
513
514        for member_token in pair {
515            match member_token.as_rule() {
516                Rule::class_property_definition => {
517                    let prop_pair = member_token.into_inner();
518
519                    // we don't want care about attributes here. It's todo in future
520                    let mut prop_pair = prop_pair.skip_while(|p| p.as_rule() == Rule::attribute);
521
522                    let mut token = prop_pair.next().unwrap();
523                    let _is_static = if token.as_rule() == Rule::class_attribute_static {
524                        token = prop_pair.next().unwrap();
525                        true
526                    } else {
527                        false
528                    };
529
530                    let _is_hidden = if token.as_rule() == Rule::class_attribute_hidden {
531                        token = prop_pair.next().unwrap();
532                        true
533                    } else {
534                        false
535                    };
536
537                    let ttype = if token.as_rule() == Rule::type_literal {
538                        let ttype = self.get_valtype_from_type_literal(token)?;
539                        token = prop_pair.next().unwrap();
540                        Some(ttype)
541                    } else {
542                        None
543                    };
544                    check_rule!(token, Rule::variable);
545                    let var_name = Self::parse_variable(token)?;
546                    let default_val = if let Some(expression_token) = prop_pair.next() {
547                        Some(self.eval_expression(expression_token)?)
548                    } else {
549                        None
550                    };
551                    properties.add_property(var_name.name, ttype, default_val);
552                }
553                Rule::class_method_definition => {
554                    let prop_pair = member_token.into_inner();
555
556                    // we don't want care about attributes here. It's todo in future
557                    let mut prop_pair = prop_pair.skip_while(|p| p.as_rule() == Rule::attribute);
558
559                    let mut token = prop_pair.next().unwrap();
560                    let _is_static = if token.as_rule() == Rule::class_attribute_static {
561                        token = prop_pair.next().unwrap();
562                        true
563                    } else {
564                        false
565                    };
566
567                    let _is_hidden = if token.as_rule() == Rule::class_attribute_hidden {
568                        token = prop_pair.next().unwrap();
569                        true
570                    } else {
571                        false
572                    };
573
574                    let _ttype = if token.as_rule() == Rule::type_literal {
575                        let ttype = self.eval_type_literal(token)?.ttype();
576                        token = prop_pair.next().unwrap();
577                        Some(ttype)
578                    } else {
579                        None
580                    };
581                    check_rule!(token, Rule::simple_name);
582                    let method_name = token.as_str().to_ascii_lowercase();
583
584                    let mut token = prop_pair.next().unwrap();
585                    let parameters = if token.as_rule() == Rule::parameter_list {
586                        let params = self.parse_parameter_list(token)?;
587                        token = prop_pair.next().unwrap();
588                        params
589                    } else {
590                        vec![]
591                    };
592                    check_rule!(token, Rule::script_block);
593
594                    let method_name = MethodName::new(method_name.as_str(), &parameters);
595                    let script_block = self.parse_script_block(token)?.with_params(parameters);
596                    methods.insert(method_name.full_name().to_string(), script_block);
597                }
598                _ => unexpected_token!(member_token),
599            }
600        }
601        let class_type = ClassType::new(class_name.clone(), properties, HashMap::new(), methods);
602        if let Ok(mut value) = value::RUNTIME_TYPE_MAP.try_lock() {
603            value.insert(
604                class_name.to_ascii_lowercase(),
605                Box::new(class_type.clone()),
606            );
607        }
608        Ok(Val::Null)
609    }
610
611    fn eval_statement(&mut self, token: Pair<'a>) -> ParserResult<Val> {
612        match token.as_rule() {
613            Rule::pipeline => self.eval_pipeline(token),
614            Rule::if_statement => self.eval_if_statement(token),
615            Rule::flow_control_statement => self.eval_flow_control_statement(token),
616            Rule::function_statement => self.parse_function_statement(token),
617            Rule::statement_terminator => Ok(Val::Null),
618            Rule::class_statement => self.parse_class_statement(token),
619            Rule::EOI => Ok(Val::Null),
620            _ => {
621                not_implemented!(token)
622            }
623        }
624    }
625
626    fn safe_eval_sub_expr(&mut self, token: Pair<'a>) -> ParserResult<Val> {
627        check_rule!(token, Rule::sub_expression);
628        let Some(inner_token) = token.into_inner().next() else {
629            return Ok(Val::Null);
630        };
631        let mut inner_val = self.eval_pipeline(inner_token)?;
632        if let Val::ScriptText(script) = &mut inner_val {
633            *script = format!("$({})", script);
634            //self.tokens.push(Token::SubExpression(script.clone()));
635        }
636        Ok(inner_val)
637    }
638
639    fn eval_statement_block(&mut self, token: Pair<'a>) -> ParserResult<Val> {
640        Ok(self
641            .safe_eval_statements(token)?
642            .iter()
643            .last()
644            .cloned()
645            .unwrap_or(Val::Null))
646    }
647
648    fn eval_statements(&mut self, token: Pair<'a>) -> ParserResult<Vec<Val>> {
649        //check_rule!(token, Rule::statements);
650        let pairs = token.into_inner();
651        let mut statements = vec![];
652
653        for token in pairs {
654            let s = self.eval_statement(token)?;
655            statements.push(s);
656        }
657        Ok(statements)
658    }
659
660    fn safe_eval_statements(&mut self, token: Pair<'a>) -> ParserResult<Vec<Val>> {
661        //check_rule!(token, Rule::statements);
662        let pairs = token.into_inner();
663        let mut statements = vec![];
664
665        for token in pairs {
666            match self.eval_statement(token.clone()) {
667                Ok(s) => statements.push(s),
668                Err(err) => {
669                    self.errors.push(err);
670                    statements.push(Val::ScriptText(token.as_str().to_string()));
671                }
672            }
673        }
674        Ok(statements)
675    }
676
677    fn parse_dq(&mut self, token: Pair<'a>) -> ParserResult<String> {
678        let mut res_str = String::new();
679        let pairs = token.into_inner();
680        for token in pairs {
681            let token = token.into_inner().next().unwrap();
682            let s = match token.as_rule() {
683                Rule::variable => self.get_variable(token)?.cast_to_string(),
684                Rule::sub_expression => self.safe_eval_sub_expr(token)?.cast_to_string(),
685                Rule::backtick_escape => token
686                    .as_str()
687                    .strip_prefix("`")
688                    .unwrap_or_default()
689                    .to_string(),
690                _ => token.as_str().to_string(),
691            };
692            res_str.push_str(s.as_str());
693        }
694        Ok(res_str)
695    }
696
697    fn eval_string_literal(&mut self, token: Pair<'a>) -> ParserResult<Val> {
698        check_rule!(token, Rule::string_literal);
699        let mut pair = token.into_inner();
700        let token = pair.next().unwrap();
701        let cloned_token = token.clone();
702
703        let mut is_expandable = false;
704        let res = match token.as_rule() {
705            Rule::doublequoted_string_literal | Rule::doublequoted_multiline_string_literal => {
706                is_expandable = true;
707                self.parse_dq(token)?
708            }
709            Rule::singlequoted_string_literal => {
710                let token_string = token.as_str().to_string();
711                let stripped_prefix = token_string
712                    .strip_prefix("'")
713                    .unwrap_or(token_string.as_str());
714                let stripped_suffix = stripped_prefix.strip_suffix("'").unwrap_or(stripped_prefix);
715                stripped_suffix.to_string()
716            }
717            Rule::singlequoted_multiline_string_literal => {
718                let mut res_str = String::new();
719                let pairs = token.into_inner();
720                for token in pairs {
721                    res_str.push_str(token.as_str());
722                }
723                res_str
724            }
725            _ => unexpected_token!(token),
726        };
727        let ps_token = if is_expandable {
728            Token::string_expandable(cloned_token.as_str().to_string(), res.clone())
729        } else {
730            Token::String(res.clone())
731        };
732        self.tokens.push(ps_token);
733
734        Ok(Val::String(res.into()))
735    }
736
737    fn get_variable(&mut self, token: Pair<'a>) -> ParserResult<Val> {
738        check_rule!(token, Rule::variable);
739        let var_name = Self::parse_variable(token)?;
740        let Some(var) = self.variables.get(&var_name) else {
741            return Err(ParserError::VariableError(VariableError::NotDefined(
742                var_name.name,
743            )));
744        };
745        Ok(var)
746    }
747
748    fn parse_scoped_variable(token: Pair<'a>) -> ParserResult<VarName> {
749        //can be scoped or splatted
750        let mut pairs = token.into_inner();
751        let mut token = pairs.next().unwrap();
752
753        let scope = if token.as_rule() == Rule::scope_keyword {
754            let scope = token.as_str().to_ascii_lowercase();
755            token = pairs.next().unwrap();
756            check_rule!(token, Rule::var_name);
757            Some(Scope::from(scope.as_str()))
758        } else {
759            None
760        };
761        Ok(VarName::new(scope, token.as_str().to_ascii_lowercase()))
762    }
763
764    fn skip_value_access(&mut self, token: Pair<'a>) -> ParserResult<()> {
765        check_rule!(token, Rule::value_access);
766        let mut pair = token.into_inner();
767        let token = pair.next().unwrap();
768        let mut val = self.eval_value(token)?;
769        let _ = self.eval_element_access_ref(pair.next().unwrap(), &mut val)?;
770        Err(ParserError::Skip)
771    }
772
773    // fn get_assignable_variable<'b>(&mut self, pairs: Pairs<'a>, object: &'b mut
774    // Val) -> ParserResult<&'b mut Val> {     let mut var = object;
775    //     for token in pairs {
776    //             let tmp = self.variable_access(token, &mut var)?;
777    //             var = tmp;
778    //     }
779    //     Ok(var)
780    // }
781
782    fn parse_assignable_variable(
783        &mut self,
784        token: Pair<'a>,
785    ) -> ParserResult<(VarName, Option<Pairs<'a>>)> {
786        check_rule!(token, Rule::assignable_variable);
787        let mut pair = token.into_inner();
788        let token = pair.next().unwrap();
789        match token.as_rule() {
790            Rule::variable => {
791                let var_name = Self::parse_variable(token)?;
792
793                Ok((var_name, None))
794            }
795            Rule::variable_access => {
796                let mut pairs = token.into_inner();
797                let var_token = pairs.next().unwrap();
798                let var_name = Self::parse_variable(var_token)?;
799                // let mut object = &mut var;
800                // for token in pairs {
801                //     object = self.variable_access(token, &mut object)?;
802                // }
803                Ok((var_name, Some(pairs)))
804            }
805            Rule::value_access => self
806                .skip_value_access(token)
807                .map(|()| (Default::default(), None)),
808            _ => unexpected_token!(token),
809        }
810    }
811
812    fn parse_variable(token: Pair<'a>) -> ParserResult<VarName> {
813        check_rule!(token, Rule::variable);
814        let mut pair = token.into_inner();
815        let token = pair.next().unwrap();
816
817        Ok(match token.as_rule() {
818            Rule::special_variable => {
819                VarName::new_with_scope(Scope::Special, token.as_str().to_string())
820            }
821            Rule::parenthesized_variable => {
822                Self::parse_variable(token.into_inner().next().unwrap())?
823            }
824            Rule::braced_variable => {
825                let token = token.into_inner().next().unwrap();
826                let var = token.as_str().to_ascii_lowercase();
827                let splits: Vec<&str> = var.split(":").collect();
828                if splits.len() == 2 {
829                    VarName::new_with_scope(Scope::from(splits[0]), splits[1].to_string())
830                } else {
831                    VarName::new(None, var)
832                }
833            }
834            Rule::scoped_variable => Self::parse_scoped_variable(token)?,
835            _ => unexpected_token!(token),
836        })
837    }
838
839    fn eval_expression_with_unary_operator(&mut self, token: Pair<'a>) -> ParserResult<Val> {
840        check_rule!(token, Rule::expression_with_unary_operator);
841        let mut pair = token.into_inner();
842        let token = pair.next().unwrap();
843
844        let res = match token.as_rule() {
845            Rule::pre_inc_expression => {
846                let variable_token = token.into_inner().next().unwrap();
847                let var_name = Self::parse_variable(variable_token)?;
848                let mut var = self.variables.get(&var_name).unwrap_or_default();
849                var.inc()?;
850
851                self.variables.set(&var_name, var.clone())?;
852                var
853            }
854            Rule::pre_dec_expression => {
855                let variable_token = token.into_inner().next().unwrap();
856                let var_name = Self::parse_variable(variable_token)?;
857                let mut var = self.variables.get(&var_name).unwrap_or_default();
858                var.dec()?;
859
860                self.variables.set(&var_name, var.clone())?;
861                var
862            }
863            Rule::cast_expression => self.eval_cast_expression(token)?,
864            Rule::negate_op => {
865                let unary_token = pair.next().unwrap();
866                let unary = self.eval_unary_exp(unary_token)?;
867                Val::Bool(!unary.cast_to_bool())
868            }
869            Rule::bitwise_negate_op => {
870                let unary_token = pair.next().unwrap();
871                let unary = self.eval_unary_exp(unary_token)?;
872                Val::Int(!unary.cast_to_int()?)
873            }
874            _ => unexpected_token!(token),
875        };
876
877        Ok(res)
878    }
879
880    fn eval_argument_list(&mut self, token: Pair<'a>) -> ParserResult<Vec<Val>> {
881        check_rule!(token, Rule::argument_list);
882        let mut pairs = token.into_inner();
883        let token = pairs.next().unwrap();
884
885        self.skip_error += 1;
886
887        let arg = self.eval_expression(token.clone())?;
888        self.skip_error -= 1;
889
890        if let Val::Array(vec) = arg {
891            Ok(vec)
892        } else {
893            Ok(vec![arg])
894        }
895    }
896
897    fn eval_member_access(&mut self, token: Pair<'a>) -> ParserResult<String> {
898        //check_rule!(token, Rule::member_access);
899        let member_name_token = token.into_inner().next().unwrap();
900        let member_name = member_name_token.as_str().to_ascii_lowercase();
901
902        Ok(member_name)
903    }
904
905    fn method_is_static(&mut self, token: Pair<'a>) -> bool {
906        check_rule!(token, Rule::method_invocation);
907        let mut pairs = token.into_inner();
908
909        let access = pairs.next().unwrap();
910        match access.as_rule() {
911            Rule::member_access => false,
912            Rule::static_access => true,
913            _ => unexpected_token!(access),
914        }
915    }
916
917    fn eval_method_invocation(
918        &mut self,
919        token: Pair<'a>,
920        object: &Val,
921    ) -> ParserResult<(String, Vec<Val>)> {
922        check_rule!(token, Rule::method_invocation);
923        let token_string = token.as_str().to_string();
924
925        let mut pairs = token.into_inner();
926
927        let access = pairs.next().unwrap();
928        let method_name = self.eval_member_access(access)?;
929
930        let args = if let Some(token) = pairs.next() {
931            check_rule!(token, Rule::argument_list);
932            match self.eval_argument_list(token) {
933                Ok(args) => args,
934                Err(e) => {
935                    log::debug!("eval_argument_list error: {:?}", e);
936
937                    //nevertheless push the function token
938                    self.tokens.push(Token::method(
939                        token_string.clone(),
940                        object.clone().into(),
941                        method_name.clone(),
942                        Vec::new(),
943                    ));
944                    Err(e)?
945                }
946            }
947        } else {
948            Vec::new()
949        };
950
951        self.tokens.push(Token::method(
952            token_string,
953            object.clone().into(),
954            method_name.clone(),
955            args.clone().iter().map(|arg| arg.clone().into()).collect(),
956        ));
957        Ok((method_name, args))
958    }
959
960    fn eval_element_access_ref<'b>(
961        &mut self,
962        token: Pair<'a>,
963        object: &'b mut Val,
964    ) -> ParserResult<&'b mut Val> {
965        let mut pairs = token.into_inner();
966        let index_token = pairs.next().unwrap();
967        check_rule!(index_token, Rule::expression);
968        let index = self.eval_expression(index_token)?;
969        Ok(object.get_index_ref(index)?)
970    }
971
972    fn eval_element_access(&mut self, token: Pair<'a>, object: &Val) -> ParserResult<Val> {
973        let mut pairs = token.into_inner();
974        let index_token = pairs.next().unwrap();
975        check_rule!(index_token, Rule::expression);
976        let index = self.eval_expression(index_token)?;
977        Ok(object.get_index(index)?)
978    }
979
980    fn variable_access<'b>(
981        &mut self,
982        token: Pair<'a>,
983        object: &'b mut Val,
984    ) -> ParserResult<&'b mut Val> {
985        fn get_member_name(token: Pair<'_>) -> &'_ str {
986            token.into_inner().next().unwrap().as_str()
987        }
988        match token.as_rule() {
989            Rule::static_access => {
990                //todo
991                Err(ParserError::NotImplemented(
992                    "modificable static_member".into(),
993                ))
994            }
995            Rule::member_access => Ok(object.member(get_member_name(token))?),
996            Rule::element_access => Ok(self.eval_element_access_ref(token, object)?),
997            _ => unexpected_token!(token),
998        }
999    }
1000
1001    fn value_access(&mut self, token: Pair<'a>, object: &mut Val) -> ParserResult<Val> {
1002        fn get_member_name(token: Pair<'_>) -> &'_ str {
1003            token.into_inner().next().unwrap().as_str()
1004        }
1005        Ok(match token.as_rule() {
1006            Rule::static_access => {
1007                let Val::RuntimeType(rt) = object else {
1008                    return Err(RuntimeError::MethodNotFound(
1009                        "Readonly static members can only be accessed on types".to_string(),
1010                    )
1011                    .into());
1012                };
1013                rt.readonly_static_member(get_member_name(token))?
1014            }
1015            Rule::member_access => object.readonly_member(get_member_name(token))?.clone(),
1016            Rule::method_invocation => {
1017                let static_method = self.method_is_static(token.clone());
1018                let (function_name, args) = self.eval_method_invocation(token, object)?;
1019                let mangled_name = MethodName::from_args(function_name.as_str(), &args);
1020
1021                if static_method {
1022                    let Val::RuntimeType(rt) = object else {
1023                        return Err(RuntimeError::MethodNotFound(
1024                            "Static method can be called only on type".to_string(),
1025                        )
1026                        .into());
1027                    };
1028
1029                    let mut call = rt.static_method(mangled_name)?;
1030                    call(args)?
1031                } else {
1032                    let mut call = object.method(mangled_name)?;
1033                    call(object, args)?
1034                }
1035            }
1036            Rule::element_access => self.eval_element_access(token, object)?,
1037            _ => unexpected_token!(token),
1038        })
1039    }
1040
1041    fn eval_value_access(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1042        check_rule!(token, Rule::value_access);
1043        let mut pairs = token.into_inner();
1044        let token = pairs.next().unwrap();
1045
1046        let mut object = self.eval_value(token)?;
1047        for token in pairs {
1048            object = self.value_access(token, &mut object)?;
1049        }
1050        log::debug!("Success eval_access: {:?}", object);
1051        Ok(object)
1052    }
1053
1054    fn parse_access(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1055        check_rule!(token, Rule::value_access);
1056        let mut pairs = token.into_inner();
1057        let token = pairs.next().unwrap();
1058
1059        let mut object = self
1060            .eval_value(token.clone())
1061            .map(|v| v.cast_to_script())
1062            .unwrap_or(token.as_str().to_string());
1063
1064        for token in pairs {
1065            match token.as_rule() {
1066                Rule::static_access => {
1067                    object.push_str(token.as_str());
1068                }
1069                Rule::member_access => {
1070                    object.push_str(token.as_str());
1071                }
1072                Rule::method_invocation => {
1073                    let static_method = self.method_is_static(token.clone());
1074                    let (method_name, args) = self
1075                        .eval_method_invocation(token.clone(), &Val::ScriptText(object.clone()))?;
1076                    log::trace!("Method: {:?} {:?}", &method_name, &args);
1077
1078                    let separator = if static_method { "::" } else { "." };
1079                    object = format!(
1080                        "{}{separator}{}({})",
1081                        object,
1082                        method_name.to_ascii_lowercase(),
1083                        args.iter()
1084                            .map(|arg| arg.cast_to_script())
1085                            .collect::<Vec<String>>()
1086                            .join(", ")
1087                    )
1088                }
1089                Rule::element_access => {
1090                    let mut pairs = token.into_inner();
1091                    let index_token = pairs.next().unwrap();
1092                    check_rule!(index_token, Rule::expression);
1093                    let index = self.eval_expression(index_token)?;
1094                    object = format!("{}[{}]", object, index);
1095                }
1096                _ => unexpected_token!(token),
1097            }
1098        }
1099        Ok(Val::String(object.into()))
1100    }
1101
1102    fn eval_primary_expression(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1103        check_rule!(token, Rule::primary_expression);
1104        let mut pair = token.into_inner();
1105        let token = pair.next().unwrap();
1106        let res = match token.as_rule() {
1107            Rule::value_access => match self.eval_value_access(token.clone()) {
1108                Ok(res) => res,
1109                Err(err) => {
1110                    log::debug!("eval_access error: {:?}", err);
1111                    self.errors.push(err);
1112                    self.parse_access(token)?
1113                }
1114            },
1115            Rule::value => self.eval_value(token)?,
1116            Rule::post_inc_expression => {
1117                let variable_token = token.into_inner().next().unwrap();
1118                let var_name = Self::parse_variable(variable_token)?;
1119                let mut var = self.variables.get(&var_name).unwrap_or_default();
1120                let var_to_return = var.clone();
1121
1122                var.inc()?;
1123                self.variables.set(&var_name, var.clone())?;
1124
1125                //if var_to_return.ttype() ==
1126                var_to_return
1127            }
1128            Rule::post_dec_expression => {
1129                let variable_token = token.into_inner().next().unwrap();
1130                let var_name = Self::parse_variable(variable_token)?;
1131                let mut var = self.variables.get(&var_name).unwrap_or_default();
1132                let var_to_return = var.clone();
1133
1134                var.dec()?;
1135                self.variables.set(&var_name, var.clone())?;
1136
1137                var_to_return
1138            }
1139            _ => unexpected_token!(token),
1140        };
1141
1142        Ok(res)
1143    }
1144
1145    fn get_valtype_from_type_literal(&mut self, token: Pair<'a>) -> ParserResult<ValType> {
1146        check_rule!(token, Rule::type_literal);
1147
1148        let token = token.into_inner().next().unwrap();
1149        check_rule!(token, Rule::type_spec);
1150        Ok(ValType::cast(token.as_str())?)
1151    }
1152
1153    fn eval_type_literal(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1154        check_rule!(token, Rule::type_literal);
1155
1156        let token = token.into_inner().next().unwrap();
1157        check_rule!(token, Rule::type_spec);
1158        Ok(ValType::runtime_type_from_str(token.as_str())?)
1159    }
1160
1161    fn parse_script_block(&mut self, token: Pair<'a>) -> ParserResult<ScriptBlock> {
1162        check_rule!(token, Rule::script_block);
1163
1164        let raw_text = token.as_str().to_string();
1165
1166        let mut pairs = token.into_inner();
1167        let Some(token) = pairs.next() else {
1168            return Ok(ScriptBlock::new(vec![], String::new(), raw_text));
1169        };
1170
1171        let params = self.parse_script_param_block(token.clone())?;
1172        //let params_str = token.as_str().to_string();
1173
1174        let script_body = if let Some(token) = pairs.next() {
1175            check_rule!(token, Rule::script_block_body);
1176            token.as_str().to_string()
1177        } else {
1178            String::new()
1179        };
1180        //todo is it necessary?
1181        // Ok(if let Ok(deobfuscated_body) =
1182        // self.deobfuscate_script(&script_body) {
1183        //     ScriptBlock::new(params, deobfuscated_body.clone(),
1184        // format!("{};{}", params_str, deobfuscated_body)) } else {
1185        //     ScriptBlock::new(params, script_body, raw_text)
1186        // })
1187        self.script_block_collect_tokens(&script_body);
1188
1189        Ok(ScriptBlock::new(params, script_body, raw_text))
1190    }
1191
1192    pub(crate) fn script_block_collect_tokens(&mut self, script_body: &str) {
1193        //we want collect tokens from each case, but we need to preserve all variables
1194        //to consider: maybe instead of collecting tokens, we should return whole
1195        // deobfuscated if statement
1196        let results = self.results.clone();
1197        let current_variables = self.variables.clone();
1198        let errors = self.errors.clone();
1199        if let Err(err) = self.parse_subscript(script_body) {
1200            log::debug!("Error during script_block_collect_tokens: {:?}", err);
1201        }
1202        self.variables = current_variables;
1203        self.results = results;
1204        self.errors = errors;
1205    }
1206
1207    fn parse_script_block_expression(&mut self, token: Pair<'a>) -> ParserResult<ScriptBlock> {
1208        check_rule!(token, Rule::script_block_expression);
1209        let mut pairs = token.into_inner();
1210        self.parse_script_block(pairs.next().unwrap())
1211    }
1212
1213    fn eval_hash_key(&mut self, token: Pair<'a>) -> ParserResult<String> {
1214        check_rule!(token, Rule::key_expression);
1215        let mut pairs = token.into_inner();
1216        let key_token = pairs.next().unwrap();
1217
1218        Ok(match key_token.as_rule() {
1219            Rule::simple_name => key_token.as_str().to_ascii_lowercase(),
1220            Rule::unary_exp => self
1221                .eval_unary_exp(key_token)?
1222                .cast_to_string()
1223                .to_ascii_lowercase(),
1224            _ => unexpected_token!(key_token),
1225        })
1226    }
1227
1228    fn eval_hash_entry(&mut self, token: Pair<'a>) -> ParserResult<(String, Val)> {
1229        check_rule!(token, Rule::hash_entry);
1230
1231        let mut pairs = token.into_inner();
1232        let token_key = pairs.next().unwrap();
1233        let token_value = pairs.next().unwrap();
1234        let value = match token_value.as_rule() {
1235            //Rule::statement => self.eval_statement(token_value)?,
1236            Rule::type_literal => self.eval_type_literal(token_value)?,
1237            _ => self.eval_statement(token_value)?,
1238        };
1239
1240        Ok((self.eval_hash_key(token_key)?, value))
1241    }
1242
1243    fn eval_hash_literal(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1244        check_rule!(token, Rule::hash_literal_expression);
1245        let pairs = token.into_inner();
1246        let mut hash = HashMap::new();
1247        for token in pairs {
1248            let (key, value) = self.eval_hash_entry(token)?;
1249            hash.insert(key, value);
1250        }
1251        Ok(Val::HashTable(hash))
1252    }
1253
1254    fn eval_value(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1255        check_rule!(token, Rule::value);
1256        let mut pair = token.into_inner();
1257        let token = pair.next().unwrap();
1258
1259        let res = match token.as_rule() {
1260            Rule::parenthesized_expression => {
1261                let token = token.into_inner().next().unwrap();
1262                self.safe_eval_pipeline(token)?
1263            }
1264            Rule::sub_expression | Rule::array_expression => {
1265                let statements = self.eval_statements(token)?;
1266                if statements.len() == 1 {
1267                    if let Val::Array(_) = statements[0] {
1268                        statements[0].clone()
1269                    } else {
1270                        Val::Array(statements)
1271                    }
1272                } else {
1273                    Val::Array(statements)
1274                }
1275            }
1276            Rule::script_block_expression => {
1277                Val::ScriptBlock(self.parse_script_block_expression(token)?)
1278            }
1279            Rule::hash_literal_expression => self.eval_hash_literal(token)?,
1280            Rule::string_literal => self.eval_string_literal(token)?,
1281            Rule::number_literal => self.eval_number_literal(token)?,
1282            Rule::type_literal => self.eval_type_literal(token)?,
1283            Rule::variable => self.get_variable(token)?,
1284            _ => unexpected_token!(token),
1285        };
1286        log::debug!("eval_value - res: {:?}", res);
1287        Ok(res)
1288    }
1289
1290    fn eval_number_literal(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1291        check_rule!(token, Rule::number_literal);
1292        let mut negate = false;
1293        let mut pairs = token.into_inner();
1294        let mut token = pairs.next().unwrap();
1295
1296        //first handle prefix sign: + or -
1297        if token.as_rule() == Rule::minus {
1298            negate = true;
1299            token = pairs.next().unwrap();
1300        } else if token.as_rule() == Rule::plus {
1301            token = pairs.next().unwrap();
1302        }
1303
1304        let mut val = self.eval_number(token)?;
1305
1306        if negate {
1307            val.neg()?;
1308        }
1309
1310        if let Some(unit) = pairs.next() {
1311            let unit = unit.as_str().to_ascii_lowercase();
1312            let unit_int = match unit.as_str() {
1313                "k" => 1024,
1314                "m" => 1024 * 1024,
1315                "g" => 1024 * 1024 * 1024,
1316                "t" => 1024 * 1024 * 1024 * 1024,
1317                "p" => 1024 * 1024 * 1024 * 1024 * 1024,
1318                _ => 1,
1319            };
1320            val.mul(Val::Int(unit_int))?;
1321        }
1322        Ok(val)
1323    }
1324
1325    fn eval_number(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1326        check_rule!(token, Rule::number);
1327        let mut pairs = token.into_inner();
1328        let token = pairs.next().unwrap();
1329        let v = match token.as_rule() {
1330            Rule::decimal_integer => {
1331                let int_val = token.into_inner().next().unwrap();
1332                Val::Int(int_val.as_str().parse::<i64>().unwrap())
1333            }
1334            Rule::hex_integer => {
1335                let int_val = token.into_inner().next().unwrap();
1336                Val::Int(i64::from_str_radix(int_val.as_str(), 16).unwrap())
1337            }
1338            Rule::float => {
1339                let float_str = token.as_str().trim();
1340                Val::Float(float_str.parse::<f64>()?)
1341                //todo: handle all border cases
1342            }
1343            _ => unexpected_token!(token),
1344        };
1345        Ok(v)
1346    }
1347
1348    fn eval_unary_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1349        check_rule!(token, Rule::unary_exp);
1350        let token = token.into_inner().next().unwrap();
1351        match token.as_rule() {
1352            Rule::expression_with_unary_operator => self.eval_expression_with_unary_operator(token),
1353            Rule::primary_expression => self.eval_primary_expression(token),
1354            _ => unexpected_token!(token),
1355        }
1356    }
1357
1358    fn eval_array_literal_exp_special_case(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1359        check_rule!(token, Rule::array_literal_exp_special_case);
1360        let mut pairs = token.into_inner();
1361        let token = pairs.next().unwrap();
1362
1363        let val = self.eval_array_literal_exp(token)?;
1364        Ok(Val::Array(vec![val]))
1365    }
1366
1367    fn safe_parse_arg(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1368        Ok(if self.skip_error > 0 {
1369            match self.eval_unary_exp(token.clone()) {
1370                Ok(val) => val,
1371                Err(err) => {
1372                    self.errors.push(err);
1373                    Val::ScriptText(token.as_str().to_string())
1374                }
1375            }
1376        } else {
1377            self.eval_unary_exp(token.clone())?
1378        })
1379    }
1380
1381    fn eval_array_literal_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1382        check_rule!(token, Rule::array_literal_exp);
1383        let mut arr = Vec::new();
1384        let mut pairs = token.into_inner();
1385        let token = pairs.next().unwrap();
1386
1387        //if array literal starts with ',' we must eval single element as array too
1388        if let Rule::array_literal_exp_special_case = token.as_rule() {
1389            return self.eval_array_literal_exp_special_case(token);
1390        }
1391
1392        arr.push(self.safe_parse_arg(token)?);
1393        for token in pairs {
1394            arr.push(self.safe_parse_arg(token)?);
1395        }
1396
1397        Ok(if arr.len() == 1 {
1398            arr[0].clone()
1399        } else {
1400            Val::Array(arr)
1401        })
1402    }
1403
1404    fn eval_range_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1405        fn range(mut left: i64, right: i64) -> Vec<Val> {
1406            let mut v = Vec::new();
1407            if left <= right {
1408                loop {
1409                    v.push(left);
1410                    if left == right {
1411                        break;
1412                    }
1413                    left += 1;
1414                }
1415            } else {
1416                loop {
1417                    v.push(left);
1418                    if left == right {
1419                        break;
1420                    }
1421                    left -= 1;
1422                }
1423            }
1424            v.into_iter().map(Val::Int).collect()
1425        }
1426        check_rule!(token, Rule::range_exp);
1427        let mut pairs = token.into_inner();
1428        let token = pairs.next().unwrap();
1429        let res = match token.as_rule() {
1430            Rule::decimal_integer => {
1431                let int_val = token.into_inner().next().unwrap();
1432                let left = int_val.as_str().parse::<i64>().unwrap();
1433                let token = pairs.next().unwrap();
1434                let right = self.eval_array_literal_exp(token)?.cast_to_int()?;
1435                Val::Array(range(left, right))
1436            }
1437            Rule::array_literal_exp => {
1438                let res = self.eval_array_literal_exp(token)?;
1439                if let Some(token) = pairs.next() {
1440                    let left = res.cast_to_int()?;
1441                    let right = self.eval_array_literal_exp(token)?.cast_to_int()?;
1442                    Val::Array(range(left, right))
1443                } else {
1444                    res
1445                }
1446            }
1447            _ => unexpected_token!(token),
1448        };
1449
1450        Ok(res)
1451    }
1452
1453    fn eval_format_impl(&mut self, format: Val, mut pairs: Pairs<'a>) -> ParserResult<Val> {
1454        fn format_with_vec(fmt: &str, args: Vec<Val>) -> ParserResult<String> {
1455            fn strange_special_case(fmt: &str, n: i64) -> String {
1456                fn split_digits(n: i64) -> Vec<u8> {
1457                    n.abs() // ignore sign for digit splitting
1458                        .to_string()
1459                        .chars()
1460                        .filter_map(|c| c.to_digit(10).map(|opt| opt as u8))
1461                        .collect()
1462                }
1463
1464                //"{0:31sdfg,0100a0b00}" -f 578 evals to 310100a5b78
1465                let mut digits = split_digits(n);
1466                digits.reverse();
1467                let mut fmt_vec = fmt.as_bytes().to_vec();
1468                fmt_vec.reverse();
1469
1470                let mut i = 0;
1471                for digit in digits {
1472                    while i < fmt_vec.len() {
1473                        if fmt_vec[i] != b'0' {
1474                            i += 1
1475                        } else {
1476                            fmt_vec[i] = digit + b'0';
1477                            break;
1478                        }
1479                    }
1480                }
1481                fmt_vec.reverse();
1482                String::from_utf8(fmt_vec).unwrap_or_default()
1483            }
1484
1485            let mut output = String::new();
1486            let mut i = 0;
1487
1488            while i < fmt.len() {
1489                if fmt[i..].starts_with('{') {
1490                    if let Some(end) = fmt[i..].find('}') {
1491                        let token = &fmt[i + 1..i + end];
1492                        let formatted = if token.contains(':') {
1493                            let mut parts = token.split(':');
1494                            let index: usize = if let Some(p) = parts.next() {
1495                                p.parse().unwrap_or(0)
1496                            } else {
1497                                0
1498                            };
1499
1500                            let spec = parts.next();
1501                            match args.get(index) {
1502                                Some(val) => match spec {
1503                                    Some(s) if s.starts_with('N') => {
1504                                        let precision = s[1..].parse::<usize>().unwrap_or(2);
1505                                        if let Ok(f) = val.cast_to_float() {
1506                                            format!("{:.1$}", f, precision)
1507                                        } else {
1508                                            val.cast_to_string().to_string()
1509                                        }
1510                                    }
1511                                    Some(s) => strange_special_case(s, val.cast_to_int()?),
1512                                    None => val.cast_to_string().to_string(),
1513                                },
1514                                None => format!("{{{}}}", token), /* leave as-is if index out of
1515                                                                   * bounds */
1516                            }
1517                        } else if token.contains(',') {
1518                            let mut parts = token.split(',');
1519                            let index: usize = parts.next().unwrap().parse().unwrap_or(0);
1520                            let spec = parts.next();
1521                            match args.get(index) {
1522                                Some(val) => match spec {
1523                                    Some(s) => {
1524                                        let spaces = s.parse::<usize>().unwrap_or(0);
1525                                        let spaces_str = " ".repeat(spaces);
1526                                        format!("{spaces_str}{}", val.cast_to_string())
1527                                    }
1528                                    _ => val.cast_to_string().to_string(),
1529                                },
1530                                None => format!("{{{}}}", token), /* leave as-is if index out of
1531                                                                   * bounds */
1532                            }
1533                        } else {
1534                            let index: usize =
1535                                Val::String(token.to_string().into()).cast_to_int()? as usize;
1536                            match args.get(index) {
1537                                Some(val) => val.cast_to_string().to_string(),
1538                                None => format!("{{{}}}", token), /* leave as-is if index out of
1539                                                                   * bounds */
1540                            }
1541                        };
1542
1543                        output.push_str(&formatted);
1544                        i += end + 1;
1545                    } else {
1546                        output.push('{');
1547                        i += 1;
1548                    }
1549                } else {
1550                    output.push(fmt[i..].chars().next().unwrap());
1551                    i += 1;
1552                }
1553            }
1554
1555            Ok(output)
1556        }
1557
1558        Ok(if let Some(token) = pairs.next() {
1559            let first_fmt = format.cast_to_string();
1560
1561            let second_fmt = self.eval_range_exp(token)?;
1562            let res = self.eval_format_impl(second_fmt, pairs)?;
1563            Val::String(format_with_vec(first_fmt.as_str(), res.cast_to_array())?.into())
1564        } else {
1565            format
1566        })
1567    }
1568
1569    fn eval_format_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1570        check_rule!(token, Rule::format_exp);
1571        let mut pairs = token.into_inner();
1572        let format = self.eval_range_exp(pairs.next().unwrap())?;
1573        self.eval_format_impl(format, pairs)
1574    }
1575
1576    fn eval_mult(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1577        check_rule!(token, Rule::multiplicative_exp);
1578        let mut pairs = token.into_inner();
1579        let mut res = self.eval_format_exp(pairs.next().unwrap())?;
1580        while let Some(op) = pairs.next() {
1581            let Some(fun) = ArithmeticPred::get(op.as_str()) else {
1582                log::error!("No arithmetic function for operator: {}", op.as_str());
1583                return Err(ParserError::NotImplemented(format!(
1584                    "No arithmetic function for operator: {}",
1585                    op.as_str()
1586                )));
1587            };
1588
1589            let postfix = pairs.next().unwrap();
1590            let right_op = self.eval_format_exp(postfix)?;
1591            res = fun(res, right_op)?;
1592        }
1593
1594        Ok(res)
1595    }
1596
1597    fn eval_additive(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1598        check_rule!(token, Rule::additive_exp);
1599
1600        let mut pairs = token.into_inner();
1601        let mut res = self.eval_mult(pairs.next().unwrap())?;
1602        while let Some(op) = pairs.next() {
1603            //check_rule!(op, Rule::additive_op); plus or minus
1604            let Some(fun) = ArithmeticPred::get(op.as_str()) else {
1605                log::error!("No arithmetic function for operator: {}", op.as_str());
1606                return Err(ParserError::NotImplemented(format!(
1607                    "No arithmetic function for operator: {}",
1608                    op.as_str()
1609                )));
1610            };
1611
1612            let mult = pairs.next().unwrap();
1613            let right_op = self.eval_mult(mult)?;
1614            res = fun(res, right_op)?;
1615        }
1616
1617        Ok(res)
1618    }
1619
1620    fn eval_split_special_case(
1621        &mut self,
1622        script_block: ScriptBlock,
1623        input: Val,
1624    ) -> ParserResult<Vec<String>> {
1625        let mut res_vec = vec![];
1626        let mut parts = String::new();
1627        let input_str = input.cast_to_string();
1628        let characters = input_str.chars();
1629
1630        // filtered_elements.join("")
1631        for ch in characters {
1632            let b = match script_block.run(vec![], self, Some(Val::String(ch.to_string().into()))) {
1633                Err(er) => {
1634                    self.errors.push(er);
1635                    false
1636                }
1637                Ok(res) => res.val.cast_to_bool(),
1638            };
1639
1640            if b {
1641                res_vec.push(parts);
1642                parts = String::new();
1643            } else {
1644                parts.push(ch);
1645            }
1646        }
1647        self.variables.reset_ps_item();
1648        Ok(res_vec)
1649    }
1650
1651    fn eval_comparison_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1652        check_rule!(token, Rule::comparison_exp);
1653        let mut pairs = token.into_inner();
1654        let token = pairs.next().unwrap();
1655
1656        // we need to handle strange case. -split and -join can be invoke without
1657        // previous expression, eg. "-join 'some'"
1658        let mut res = if token.as_rule() == Rule::additive_exp {
1659            self.eval_additive(token)?
1660        } else {
1661            Val::Null
1662        };
1663
1664        while let Some(op) = pairs.next() {
1665            let Some(fun) = StringPred::get(op.as_str()) else {
1666                log::error!("No string predicate for operator: {}", op.as_str());
1667                return Err(ParserError::NotImplemented(format!(
1668                    "No string predicate for operator: {}",
1669                    op.as_str()
1670                )));
1671            };
1672
1673            let token = pairs.next().unwrap();
1674            let right_op = match token.as_rule() {
1675                Rule::script_block_expression => {
1676                    let script_block = self.parse_script_block_expression(token)?;
1677
1678                    return Ok(Val::Array(
1679                        self.eval_split_special_case(script_block, res)?
1680                            .into_iter()
1681                            .map(|s| Val::String(s.into()))
1682                            .collect::<Vec<_>>(),
1683                    ));
1684                }
1685                Rule::additive_exp => self.eval_additive(token)?,
1686                //Rule::type_literal => self.eval_type_literal(token)?,
1687                _ => unexpected_token!(token),
1688            };
1689            log::trace!("res: {:?}, right_op: {:?}", &res, &right_op);
1690            res = fun(res, right_op)?;
1691            log::trace!("res: {:?}", &res);
1692        }
1693
1694        Ok(res)
1695    }
1696
1697    fn parse_script_param_block(&mut self, token: Pair<'a>) -> ParserResult<Vec<Param>> {
1698        check_rule!(token, Rule::script_param_block);
1699        let mut pairs = token.into_inner();
1700        let Some(param_block_token) = pairs.next() else {
1701            return Ok(vec![]);
1702        };
1703        self.parse_param_block(param_block_token)
1704    }
1705
1706    fn parse_param_block(&mut self, token: Pair<'a>) -> ParserResult<Vec<Param>> {
1707        check_rule!(token, Rule::param_block);
1708        let mut pairs = token.into_inner();
1709
1710        let Some(token) = pairs.next() else {
1711            return Ok(vec![]);
1712        };
1713
1714        let option_param_token = match token.as_rule() {
1715            Rule::attribute_list => {
1716                //self.parse_attribute_list(token)?;
1717                pairs.next()
1718            }
1719            Rule::parameter_list => Some(token),
1720            _ => unexpected_token!(token),
1721        };
1722
1723        let Some(param_token) = option_param_token else {
1724            return Ok(vec![]);
1725        };
1726        self.parse_parameter_list(param_token)
1727    }
1728
1729    fn parse_parameter_list(&mut self, token: Pair<'a>) -> ParserResult<Vec<Param>> {
1730        check_rule!(token, Rule::parameter_list);
1731        let mut params = vec![];
1732        let param_list_pairs = token.into_inner();
1733        for script_parameter_token in param_list_pairs {
1734            check_rule!(script_parameter_token, Rule::script_parameter);
1735            params.push(self.parse_script_parameter(script_parameter_token)?);
1736        }
1737        Ok(params)
1738    }
1739
1740    fn parse_attribute_list(&mut self, token: Pair<'a>) -> ParserResult<Option<ValType>> {
1741        check_rule!(token, Rule::attribute_list);
1742        let attribute_list_pairs = token.into_inner();
1743        for attribute_token in attribute_list_pairs {
1744            check_rule!(attribute_token, Rule::attribute);
1745            let attribute_type_token = attribute_token.into_inner().next().unwrap();
1746            match attribute_type_token.as_rule() {
1747                Rule::attribute_info => {
1748                    //skip for now
1749                    continue;
1750                }
1751                Rule::type_literal => {
1752                    return Ok(Some(
1753                        self.get_valtype_from_type_literal(attribute_type_token)?,
1754                    ));
1755                }
1756                _ => unexpected_token!(attribute_type_token),
1757            }
1758        }
1759        Ok(None)
1760    }
1761    fn parse_script_parameter(&mut self, token: Pair<'a>) -> ParserResult<Param> {
1762        check_rule!(token, Rule::script_parameter);
1763        let mut pairs = token.into_inner();
1764        let mut token = pairs.next().unwrap();
1765
1766        let type_literal = if token.as_rule() == Rule::attribute_list {
1767            let type_literal = self.parse_attribute_list(token).unwrap_or(None);
1768            token = pairs.next().unwrap();
1769            type_literal
1770        } else {
1771            None
1772        };
1773
1774        check_rule!(token, Rule::variable);
1775        let var_name = Self::parse_variable(token)?;
1776
1777        let default_value = if let Some(default_value_token) = pairs.next() {
1778            check_rule!(default_value_token, Rule::script_parameter_default);
1779            let default_value_expr = default_value_token.into_inner().next().unwrap();
1780            let default_value = self.eval_primary_expression(default_value_expr)?;
1781            Some(default_value)
1782        } else {
1783            None
1784        };
1785        Ok(Param::new(type_literal, var_name.name, default_value))
1786    }
1787
1788    fn eval_bitwise_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1789        check_rule!(token, Rule::bitwise_exp);
1790
1791        let mut pairs = token.into_inner();
1792        let mut res = self.eval_as_exp(pairs.next().unwrap())?;
1793        while let Some(op) = pairs.next() {
1794            check_rule!(op, Rule::bitwise_operator);
1795            let Some(fun) = BitwisePred::get(op.as_str()) else {
1796                log::error!("No bitwise predicate for operator: {}", op.as_str());
1797                return Err(ParserError::NotImplemented(format!(
1798                    "No bitwise predicate for operator: {}",
1799                    op.as_str()
1800                )));
1801            };
1802
1803            let mult = pairs.next().unwrap();
1804            let right_op = self.eval_as_exp(mult)?;
1805            res = fun(res, right_op)?;
1806        }
1807
1808        Ok(res)
1809    }
1810
1811    fn eval_as_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1812        check_rule!(token, Rule::as_expression);
1813
1814        let mut pairs = token.into_inner();
1815        let mut res = self.eval_comparison_exp(pairs.next().unwrap())?;
1816        for token in pairs {
1817            let runtime_object = match token.as_rule() {
1818                Rule::type_literal => self.eval_type_literal(token)?,
1819                Rule::comparison_exp => self.eval_comparison_exp(token)?,
1820                _ => unexpected_token!(token),
1821            };
1822
1823            res = res.cast(&runtime_object).unwrap_or_default();
1824        }
1825
1826        Ok(res)
1827    }
1828
1829    fn parse_cmdlet_command_name(&mut self, token: Pair<'a>) -> ParserResult<Command> {
1830        check_rule!(token, Rule::cmdlet_command);
1831
1832        let mut pairs = token.into_inner();
1833        let token = pairs.next().unwrap();
1834        let command_name = match token.as_rule() {
1835            Rule::command_name => token.as_str(),
1836            Rule::where_command_name => "where-object",
1837            Rule::foreach_command_name => "foreach-object",
1838            Rule::powershell_command_name => "powershell",
1839            _ => unexpected_token!(token),
1840        };
1841
1842        let mut command = Command::cmdlet(command_name);
1843        if Rule::command_name == token.as_rule() {
1844            command.set_session_scope(SessionScope::New);
1845        }
1846        Ok(command)
1847    }
1848
1849    fn parse_command_args(&mut self, pairs: Pairs<'a>) -> ParserResult<Vec<CommandElem>> {
1850        let mut args = vec![];
1851        for command_element_token in pairs {
1852            let token_string = command_element_token.as_str().to_string();
1853            match command_element_token.as_rule() {
1854                Rule::command_argument => {
1855                    let arg_token = command_element_token.into_inner().next().unwrap();
1856                    let arg = match arg_token.as_rule() {
1857                        Rule::array_literal_exp => self.eval_array_literal_exp(arg_token)?,
1858                        Rule::script_block_expression => {
1859                            Val::ScriptBlock(self.parse_script_block_expression(arg_token)?)
1860                        }
1861                        Rule::parenthesized_expression => {
1862                            let token = arg_token.into_inner().next().unwrap();
1863                            self.eval_pipeline(token)?
1864                        }
1865                        _ => Val::ScriptText(arg_token.as_str().to_string()),
1866                    };
1867                    args.push(CommandElem::Argument(arg));
1868                }
1869                Rule::command_parameter => {
1870                    args.push(CommandElem::Parameter(token_string.to_ascii_lowercase()))
1871                }
1872                Rule::argument_list => args.push(CommandElem::ArgList(token_string)),
1873                Rule::splatten_arg => {
1874                    let var_name = Self::parse_scoped_variable(command_element_token)?;
1875                    let var = self.variables.get(&var_name).unwrap_or_default();
1876                    if let Val::HashTable(h) = var {
1877                        for (k, v) in h {
1878                            args.push(CommandElem::Parameter(format!("-{}", k)));
1879                            args.push(CommandElem::Argument(v));
1880                        }
1881                    }
1882                }
1883                Rule::redirection => { //todo: implement redirection
1884                }
1885                Rule::stop_parsing => { //todo: stop parsing
1886                }
1887                _ => unexpected_token!(command_element_token),
1888            }
1889        }
1890        Ok(args)
1891    }
1892
1893    fn eval_command(&mut self, token: Pair<'a>, piped_arg: Option<Val>) -> ParserResult<Val> {
1894        check_rule!(token, Rule::command);
1895        let command_str = token.as_str().to_string();
1896
1897        let mut pairs = token.into_inner();
1898        let command_token = pairs.next().unwrap();
1899        let mut command = match command_token.as_rule() {
1900            Rule::cmdlet_command => self.parse_cmdlet_command_name(command_token)?,
1901            Rule::invocation_command => self.parse_invocation_command(command_token)?,
1902            _ => unexpected_token!(command_token),
1903        };
1904
1905        let mut args = self.parse_command_args(pairs)?;
1906        if let Some(arg) = piped_arg {
1907            args.insert(0, CommandElem::Argument(arg));
1908        }
1909
1910        command.with_args(args);
1911        self.tokens
1912            .push(Token::command(command_str, command.name(), command.args()));
1913
1914        match command.execute(self) {
1915            Ok(CommandOutput {
1916                val,
1917                deobfuscated: _deobfuscated,
1918            }) => Ok(val),
1919            Err(e) => {
1920                self.errors.push(e);
1921                Ok(Val::ScriptText(command.to_string()))
1922            }
1923        }
1924
1925        // if let Some(msg) = deobfuscated {
1926        //     self.add_deobfuscated_statement(msg);
1927        // }
1928    }
1929
1930    fn add_deobfuscated_statement(&mut self, msg: String) {
1931        if let Some(last) = self.results.last_mut() {
1932            last.deobfuscated.push(msg);
1933        }
1934    }
1935
1936    fn add_output_statement(&mut self, msg: StreamMessage) {
1937        if let Some(last) = self.results.last_mut() {
1938            last.output.push(msg);
1939        }
1940    }
1941
1942    fn parse_invocation_command(&mut self, token: Pair<'a>) -> ParserResult<Command> {
1943        check_rule!(token, Rule::invocation_command);
1944
1945        let invocation_command_token = token.into_inner().next().unwrap();
1946
1947        let mut session_scope = match invocation_command_token.as_rule() {
1948            Rule::current_scope_invocation_command => SessionScope::Current,
1949            Rule::new_scope_invocation_command => SessionScope::New,
1950            _ => unexpected_token!(invocation_command_token),
1951        };
1952
1953        let token_inner = invocation_command_token.into_inner().next().unwrap();
1954
1955        let mut command = match token_inner.as_rule() {
1956            Rule::cmdlet_command => {
1957                session_scope = SessionScope::New;
1958                self.parse_cmdlet_command_name(token_inner)?
1959            }
1960            Rule::primary_expression => {
1961                let primary = self.eval_primary_expression(token_inner)?;
1962                if let Val::ScriptBlock(script_block) = primary {
1963                    Command::script_block(script_block)
1964                } else {
1965                    Command::cmdlet(&primary.cast_to_script())
1966                }
1967            }
1968            Rule::path_command_name => Command::path(token_inner.as_str()),
1969            _ => unexpected_token!(token_inner),
1970        };
1971
1972        command.set_session_scope(session_scope);
1973        Ok(command)
1974    }
1975
1976    fn eval_redirected_expression(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1977        check_rule!(token, Rule::redirected_expression);
1978
1979        let expression_token = token.into_inner().next().unwrap();
1980        //todo: handle redirections
1981
1982        self.eval_expression(expression_token)
1983    }
1984
1985    fn eval_expression(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1986        check_rule!(token, Rule::expression);
1987        let token_string = token.as_str().trim().to_string();
1988
1989        let mut pairs = token.into_inner();
1990        let mut res = self.eval_bitwise_exp(pairs.next().unwrap())?;
1991        while let Some(op) = pairs.next() {
1992            check_rule!(op, Rule::logical_operator);
1993            let Some(fun) = LogicalPred::get(op.as_str()) else {
1994                log::error!("No logical predicate for operator: {}", op.as_str());
1995                return Err(ParserError::NotImplemented(format!(
1996                    "No logical predicate for operator: {}",
1997                    op.as_str()
1998                )));
1999            };
2000
2001            let mult = pairs.next().unwrap();
2002            let right_op = self.eval_bitwise_exp(mult)?;
2003            res = Val::Bool(fun(res, right_op));
2004        }
2005        self.tokens
2006            .push(Token::expression(token_string, res.clone().into()));
2007
2008        if let Val::String(value::PsString(s)) = &res {
2009            self.tokens.push(Token::String(s.clone()));
2010        }
2011
2012        Ok(res)
2013    }
2014
2015    fn eval_pipeline_tail(&mut self, token: Pair<'a>, mut piped_arg: Val) -> ParserResult<Val> {
2016        check_rule!(token, Rule::pipeline_tail);
2017        let pairs = token.into_inner();
2018
2019        for token in pairs {
2020            //self.variables.set_ps_item(arg);
2021            piped_arg = self.eval_command(token, Some(piped_arg))?;
2022        }
2023
2024        Ok(piped_arg)
2025    }
2026
2027    fn eval_pipeline_with_tail(&mut self, token: Pair<'a>) -> ParserResult<Val> {
2028        check_rule!(token, Rule::pipeline_with_tail);
2029        let mut pairs = token.into_inner();
2030        let token = pairs.next().unwrap();
2031
2032        let result: Val = match token.as_rule() {
2033            Rule::redirected_expression => self.eval_redirected_expression(token)?,
2034            Rule::command => self.eval_command(token, None)?,
2035            _ => unexpected_token!(token),
2036        };
2037
2038        if let Some(token) = pairs.next() {
2039            match token.as_rule() {
2040                Rule::pipeline_tail => Ok(self.eval_pipeline_tail(token, result)?),
2041                _ => unexpected_token!(token),
2042            }
2043        } else {
2044            Ok(result)
2045        }
2046    }
2047
2048    fn eval_pipeline(&mut self, token: Pair<'a>) -> ParserResult<Val> {
2049        check_rule!(token, Rule::pipeline);
2050        let mut pairs = token.into_inner();
2051        let token = pairs.next().unwrap();
2052
2053        match token.as_rule() {
2054            Rule::assignment_exp => self.eval_assigment_exp(token),
2055            Rule::pipeline_with_tail => self.eval_pipeline_with_tail(token),
2056            _ => unexpected_token!(token),
2057        }
2058    }
2059
2060    fn safe_eval_pipeline(&mut self, token: Pair<'a>) -> ParserResult<Val> {
2061        let res = self.eval_pipeline(token.clone());
2062
2063        let v = match res {
2064            Ok(val) => val,
2065            Err(err) => {
2066                self.errors.push(err);
2067                Val::ScriptText(token.as_str().to_string())
2068            }
2069        };
2070
2071        Ok(v)
2072    }
2073
2074    fn eval_cast_expression(&mut self, token: Pair<'a>) -> ParserResult<Val> {
2075        check_rule!(token, Rule::cast_expression);
2076
2077        let mut pairs = token.into_inner();
2078        let type_token = pairs.next().unwrap();
2079        check_rule!(type_token, Rule::type_literal);
2080        let val_type = self.eval_type_literal(type_token)?;
2081        let token = pairs.next().unwrap();
2082        let res = match token.as_rule() {
2083            Rule::parenthesized_expression => {
2084                let token = token.into_inner().next().unwrap();
2085                self.safe_eval_pipeline(token)?
2086            }
2087            Rule::unary_exp => self.eval_unary_exp(token)?,
2088            _ => unexpected_token!(token),
2089        };
2090        Ok(res.cast(&val_type)?)
2091    }
2092
2093    fn eval_assigment_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
2094        check_rule!(token, Rule::assignment_exp);
2095
2096        let mut specified_type = None;
2097
2098        let mut pairs = token.into_inner();
2099        let mut token = pairs.next().unwrap();
2100        if token.as_rule() == Rule::type_literal {
2101            specified_type = Some(self.eval_type_literal(token)?);
2102            token = pairs.next().unwrap();
2103        }
2104        let (var_name, access) = self.parse_assignable_variable(token)?;
2105        let mut variable = self.variables.get(&var_name).unwrap_or_default();
2106        let mut accessed_elem = &mut variable;
2107
2108        // sometimes we have variable access like $a[0].Property, and we need access
2109        // property by reference
2110        if let Some(access) = access {
2111            for token in access {
2112                accessed_elem = self.variable_access(token, accessed_elem)?;
2113            }
2114        }
2115        let assignement_op = pairs.next().unwrap();
2116
2117        //get operand
2118        let op = assignement_op.into_inner().next().unwrap();
2119        let pred = ArithmeticPred::get(op.as_str());
2120
2121        let right_token = pairs.next().unwrap();
2122        let right_op = self.eval_statement(right_token.clone())?;
2123
2124        let Some(pred) = pred else {
2125            log::error!("No arithmetic function for operator: {}", op.as_str());
2126            return Err(ParserError::NotImplemented(format!(
2127                "No arithmetic function for operator: {}",
2128                op.as_str()
2129            )));
2130        };
2131
2132        *accessed_elem = pred(accessed_elem.clone(), right_op)?;
2133        if let Some(runtime_type) = specified_type {
2134            *accessed_elem = accessed_elem.cast(&runtime_type)?;
2135        }
2136        self.variables.set(&var_name, variable.clone())?;
2137        //we want save each assignment statement
2138        self.add_deobfuscated_statement(format!("{} = {}", var_name, variable.cast_to_script()));
2139
2140        Ok(Val::NonDisplayed(Box::new(variable)))
2141    }
2142
2143    fn push_scope_session(&mut self) {
2144        self.variables.push_scope_session();
2145    }
2146
2147    fn pop_scope_session(&mut self) {
2148        self.variables.pop_scope_session();
2149    }
2150}
2151
2152#[cfg(test)]
2153mod tests {
2154    use pest::Parser;
2155
2156    use super::*;
2157
2158    #[test]
2159    fn comment_and_semicolon() {
2160        let input = r#"
2161# This is a single line comment
2162$a = 1; $b = 2; Write-Output $a
2163
2164Write-Output "Hello"  # Another comment
2165
2166<#
2167    This is a
2168    multi-line block comment
2169#>
2170"#;
2171
2172        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
2173    }
2174
2175    #[test]
2176    fn while_loop() {
2177        let input = r#"
2178while ($true) {
2179    if ($someCondition) {
2180        break
2181    }
2182    # other code
2183}
2184"#;
2185
2186        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
2187    }
2188
2189    #[test]
2190    fn foreach_loop() {
2191        let input = r#"
2192foreach ($n in $numbers) {
2193    Write-Output $n
2194}
2195"#;
2196
2197        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
2198    }
2199
2200    #[test]
2201    fn for_loop() {
2202        let input = r#"
2203# Comma separated assignment expressions enclosed in parentheses.
2204for (($i = 0), ($j = 0); $i -lt 10; $i++)
2205{
2206    "`$i:$i"
2207    "`$j:$j"
2208}
2209"#;
2210
2211        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
2212    }
2213
2214    #[test]
2215    fn switch() {
2216        let input = r#"
2217switch ($var) {
2218    "a" { Write-Output "A" }
2219    1 { Write-Output "One" }
2220    default { Write-Output "Other" }
2221}
2222"#;
2223
2224        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
2225    }
2226
2227    #[test]
2228    fn functions() {
2229        let input = r#"
2230function Get-Square {
2231    param($x)
2232    return $x * $x
2233}
2234
2235function Say-Hello {
2236    Write-Output "Hello"
2237}
2238"#;
2239
2240        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
2241    }
2242
2243    #[test]
2244    fn if_expression() {
2245        let input = r#"
2246$x="hello"
2247        Write-Host $x
2248        $y = 42
2249        Start-Process "notepad.exe"
2250
2251        $x = 42
2252if ($x -eq 1) {
2253    Write-Output "One"
2254} elseif ($x -eq 2) {
2255    Write-Output "Two"
2256} else {
2257    Write-Output "Other"
2258}
2259"#;
2260
2261        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
2262    }
2263
2264    #[test]
2265    fn command() {
2266        let input = r#"
2267Get-Process | Where-Object { $_.CPU -gt 100 }
2268"#;
2269
2270        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
2271    }
2272
2273    #[test]
2274    fn range() {
2275        let input = r#"
2276$numbers = 1..5
2277"#;
2278
2279        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
2280    }
2281
2282    #[test]
2283    fn literals() {
2284        let input = r#"
2285$hex = 0xFF
2286
2287$name = "Alice"
2288$msg = "Hello, $name. Today is $day."
2289$escaped = "She said: `"Hi`""
2290$literal = 'Hello, $name'
2291"#;
2292
2293        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
2294    }
2295
2296    #[test]
2297    fn floats() {
2298        let input = r#"
2299    $pi = 3.1415
2300$half = .5
2301"#;
2302
2303        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
2304    }
2305
2306    #[test]
2307    fn arrays() {
2308        let input = r#"
2309$a = 1, 2, 3
2310$b = @("one", "two", "three")
2311$c = @(1, 2, @(3, 4))
2312"#;
2313
2314        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
2315    }
2316
2317    #[test]
2318    fn static_method_call() {
2319        let input = r#"
2320[Threading.Thread]::Sleep(399)
2321"#;
2322
2323        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
2324    }
2325
2326    #[test]
2327    fn neg_pipeline() {
2328        let input = r#"
2329-not $input | Where-Object { $_ -gt 5 }
2330"#;
2331
2332        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
2333    }
2334
2335    #[test]
2336    fn amsi_fail() {
2337        let input = r#"
2338#Matt Graebers second Reflection method 
2339$VMRviwsbtehQfPtxbt=$null;
2340$ilryNQSTt="System.$([cHAR]([ByTE]0x4d)+[ChAR]([byte]0x61)+[chAr](110)+[cHar]([byTE]0x61)+[cHaR](103)+[cHar](101*64/64)+[chaR]([byTE]0x6d)+[cHAr](101)+[CHAr]([byTE]0x6e)+[Char](116*103/103)).$([Char]([ByTe]0x41)+[Char](117+70-70)+[CHAr]([ByTE]0x74)+[CHar]([bYte]0x6f)+[CHar]([bytE]0x6d)+[ChaR]([ByTe]0x61)+[CHar]([bYte]0x74)+[CHAR]([byte]0x69)+[Char](111*26/26)+[chAr]([BYTe]0x6e)).$(('Âmsí'+'Ùtìl'+'s').NORmalizE([ChAR](44+26)+[chAR](111*9/9)+[cHar](82+32)+[ChaR](109*34/34)+[cHaR](68+24-24)) -replace [ChAr](92)+[CHaR]([BYTe]0x70)+[Char]([BytE]0x7b)+[CHaR]([BYTe]0x4d)+[chAR](110)+[ChAr](15+110))"
2341
2342"#;
2343
2344        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
2345    }
2346}