ps_parser/
parser.rs

1mod command;
2mod error;
3mod predicates;
4mod script_result;
5mod stream_message;
6mod token;
7mod value;
8mod variables;
9
10use std::collections::HashMap;
11
12pub(crate) use command::CommandError;
13use command::{Command, CommandElem};
14pub(crate) use stream_message::StreamMessage;
15use value::{RuntimeObject, ScriptBlock, ValResult};
16use variables::Scope;
17type ParserResult<T> = core::result::Result<T, ParserError>;
18use error::ParserError;
19type PestError = pest::error::Error<Rule>;
20use pest::Parser;
21use pest_derive::Parser;
22use predicates::{ArithmeticPred, BitwisePred, LogicalPred, StringPred};
23pub use script_result::{PsValue, ScriptResult};
24pub use token::{Token, Tokens};
25pub(crate) use value::{Val, ValType};
26pub use variables::Variables;
27use variables::{VarName, VariableError};
28
29use crate::parser::command::CommandOutput;
30
31type Pair<'i> = ::pest::iterators::Pair<'i, Rule>;
32type Pairs<'i> = ::pest::iterators::Pairs<'i, Rule>;
33
34pub(crate) const NEWLINE: &str = "\n";
35
36macro_rules! check_rule {
37    ($pair:expr, $rule:pat) => {
38        if !matches!($pair.as_rule(), $rule) {
39            panic!("rule: {:?}", $pair.as_rule());
40        }
41    };
42}
43
44#[derive(Parser)]
45#[grammar = "powershell.pest"]
46pub struct PowerShellSession {
47    variables: Variables,
48    tokens: Tokens,
49    errors: Vec<ParserError>,
50    output: Vec<StreamMessage>,
51    deobfuscated_statements: Vec<String>,
52}
53
54impl Default for PowerShellSession {
55    fn default() -> Self {
56        Self::new()
57    }
58}
59
60impl<'a> PowerShellSession {
61    /// Creates a new PowerShell parsing session with default settings.
62    ///
63    /// The session is initialized with built-in variables like `$true`,
64    /// `$false`, `$null`, and special variables like `$?` for error status
65    /// tracking.
66    ///
67    /// # Returns
68    ///
69    /// A new `PowerShellSession` instance ready for script evaluation.
70    ///
71    /// # Examples
72    ///
73    /// ```rust
74    /// use ps_parser::PowerShellSession;
75    ///
76    /// let mut session = PowerShellSession::new();
77    /// let result = session.safe_eval("$true").unwrap();
78    /// assert_eq!(result, "True");
79    /// ```
80    pub fn new() -> Self {
81        Self {
82            variables: Variables::new(),
83            tokens: Tokens::new(),
84            errors: Vec::new(),
85            output: Vec::new(),
86            deobfuscated_statements: Vec::new(),
87        }
88    }
89
90    /// Creates a new PowerShell session with the provided variables.
91    ///
92    /// This constructor allows you to initialize the session with a custom set
93    /// of variables, such as environment variables or variables loaded from
94    /// configuration files.
95    ///
96    /// # Arguments
97    ///
98    /// * `variables` - A `Variables` instance containing the initial variable
99    ///   set.
100    ///
101    /// # Returns
102    ///
103    /// A new `PowerShellSession` instance with the provided variables.
104    ///
105    /// # Examples
106    ///
107    /// ```rust
108    /// use ps_parser::{PowerShellSession, Variables};
109    ///
110    /// let env_vars = Variables::env();
111    /// let mut session = PowerShellSession::new().with_variables(env_vars);
112    /// let username = session.safe_eval("$env:USERNAME").unwrap();
113    /// ```
114    pub fn with_variables(mut self, variables: Variables) -> Self {
115        self.variables = variables;
116        self
117    }
118
119    /// Safely evaluates a PowerShell script and returns the output as a string.
120    ///
121    /// This method parses and evaluates the provided PowerShell script,
122    /// handling errors gracefully and returning the result as a formatted
123    /// string. It's the recommended method for simple script evaluation.
124    ///
125    /// # Arguments
126    ///
127    /// * `script` - A string slice containing the PowerShell script to
128    ///   evaluate.
129    ///
130    /// # Returns
131    ///
132    /// * `Result<String, ParserError>` - The output of the script evaluation,
133    ///   or an error if parsing/evaluation fails.
134    ///
135    /// # Examples
136    ///
137    /// ```rust
138    /// use ps_parser::PowerShellSession;
139    ///
140    /// let mut session = PowerShellSession::new();
141    ///
142    /// // Simple arithmetic
143    /// let result = session.safe_eval("1 + 2 * 3").unwrap();
144    /// assert_eq!(result, "7");
145    ///
146    /// // Variable assignment and retrieval
147    /// let result = session.safe_eval("$name = 'World'; \"Hello $name\"").unwrap();
148    /// assert_eq!(result, "Hello World");
149    /// ```
150    pub fn safe_eval(&mut self, script: &str) -> Result<String, ParserError> {
151        Ok(self.parse_input(script)?.result().to_string())
152    }
153
154    /// Parses and evaluates a PowerShell script, returning detailed results.
155    ///
156    /// This method provides comprehensive information about the parsing and
157    /// evaluation process, including the final result, generated output,
158    /// any errors encountered, and the tokenized representation of the
159    /// script. It's particularly useful for debugging and deobfuscation.
160    ///
161    /// # Arguments
162    ///
163    /// * `input` - A string slice containing the PowerShell script to parse and
164    ///   evaluate.
165    ///
166    /// # Returns
167    ///
168    /// * `Result<ScriptResult, ParserError>` - A detailed result containing the
169    ///   evaluation outcome, output, errors, and tokens, or a parsing error if
170    ///   the script is malformed.
171    ///
172    /// # Examples
173    ///
174    /// ```rust
175    /// use ps_parser::PowerShellSession;
176    ///
177    /// let mut session = PowerShellSession::new();
178    /// let script_result = session.parse_input("$a = 42; Write-Output $a").unwrap();
179    ///
180    /// println!("Final result: {:?}", script_result.result());
181    /// println!("Generated output: {:?}", script_result.output());
182    /// println!("Parsing errors: {:?}", script_result.errors());
183    /// println!("Deobfuscated code: {:?}", script_result.deobfuscated());
184    /// ```
185    pub fn parse_input(&mut self, input: &str) -> Result<ScriptResult, ParserError> {
186        let mut pairs = PowerShellSession::parse(Rule::program, input)?;
187        let program_token = pairs.next().expect("");
188
189        //let mut script_statements = Vec::new();
190        let mut script_last_output = Val::default();
191
192        if let Rule::program = program_token.as_rule() {
193            let pairs = program_token.into_inner();
194
195            //println!("token: {} deobfuscated: {:?}", token.as_str(),
196            // &self.deobfuscated_statements);
197            for token in pairs {
198                let token_str = token.as_str();
199                let result = match token.as_rule() {
200                    Rule::pipeline => {
201                        //first assign to output, later create from it script line
202                        //self.eval_pipeline(token.clone())
203                        let mut pairs = token.into_inner();
204                        let token = pairs.next().unwrap();
205
206                        match token.as_rule() {
207                            Rule::assignment_exp => {
208                                let result = self.eval_assigment_exp(token);
209                                //we don't want print assignent result to deobfuscated script.
210                                // Thats why we always return null
211                                result.map(|_| Val::Null)
212                            }
213                            Rule::pipeline_with_tail => self.eval_pipeline_with_tail(token),
214                            _ => panic!("not possible: {:?}", token.as_rule()),
215                        }
216                    }
217                    Rule::if_statement => self.eval_if_statement(token),
218                    Rule::statement_terminator => continue,
219                    Rule::EOI => break,
220                    _ => {
221                        log::error!("parse_input not implemented: {:?}", token.as_rule());
222                        Err(ParserError::NotImplemented(format!(
223                            "Not implemented: {:?}",
224                            token.as_rule()
225                        )))
226                    }
227                };
228
229                self.variables.set_status(result.is_ok());
230
231                script_last_output = match result {
232                    Ok(val) => {
233                        if val != Val::Null {
234                            self.output.push(val.display().into());
235                        }
236
237                        val
238                    }
239                    Err(e) => {
240                        self.errors.push(e);
241                        self.deobfuscated_statements.push(token_str.into());
242                        Val::Null
243                    }
244                };
245            }
246        }
247
248        Ok(ScriptResult::new(
249            script_last_output,
250            std::mem::take(&mut self.output),
251            std::mem::take(&mut self.deobfuscated_statements),
252            std::mem::take(&mut self.tokens),
253            std::mem::take(&mut self.errors),
254        ))
255    }
256
257    pub(crate) fn eval_if_statement(&mut self, token: Pair<'a>) -> ParserResult<Val> {
258        check_rule!(token, Rule::if_statement);
259        let mut pair = token.into_inner();
260        let condition_token = pair.next().unwrap();
261        let true_token = pair.next().unwrap();
262        let condition_val = self.eval_pipeline(condition_token)?;
263        let res = if condition_val.cast_to_bool() {
264            self.eval_statement_block(true_token)?
265        } else {
266            if let Some(mut token) = pair.next() {
267                if token.as_rule() == Rule::elseif_clauses {
268                    for else_if in token.into_inner() {
269                        let mut pairs = else_if.into_inner();
270                        let condition_token = pairs.next().unwrap();
271                        let statement_token = pairs.next().unwrap();
272                        let condition_val = self.eval_pipeline(condition_token)?;
273                        if condition_val.cast_to_bool() {
274                            return self.eval_statement_block(statement_token);
275                        }
276                    }
277                    let Some(token2) = pair.next() else {
278                        return Ok(Val::Null);
279                    };
280                    token = token2;
281                }
282                if token.as_rule() == Rule::else_condition {
283                    let statement_token = token.into_inner().next().unwrap();
284                    self.eval_statement_block(statement_token)?
285                } else {
286                    Val::Null
287                }
288            } else {
289                Val::Null
290            }
291        };
292
293        Ok(res)
294    }
295
296    pub(crate) fn eval_script_block(
297        &mut self,
298        input: &ScriptBlock,
299        ps_item: &Val,
300    ) -> ParserResult<bool> {
301        self.variables.set_ps_item(ps_item.clone());
302        let mut new_session = PowerShellSession::new().with_variables(self.variables.clone());
303        let res = new_session
304            .parse_input(input.0.as_str())?
305            .result()
306            .is_true();
307        self.variables.reset_ps_item();
308        Ok(res)
309    }
310
311    fn eval_statement(&mut self, token: Pair<'a>) -> ParserResult<Val> {
312        match token.as_rule() {
313            Rule::pipeline => self.eval_pipeline(token),
314            Rule::if_statement => self.eval_if_statement(token),
315            _ => Err(ParserError::NotImplemented(format!(
316                "Not implemented: {:?}",
317                token.as_rule()
318            )))?,
319        }
320    }
321
322    fn safe_eval_sub_expr(&mut self, token: Pair<'a>) -> ParserResult<Val> {
323        match self.eval_statements(token.clone()) {
324            Ok(vals) => Ok(Val::Array(vals)),
325            Err(err) => {
326                self.errors.push(err);
327                Ok(Val::ScriptText(token.as_str().to_string()))
328            }
329        }
330    }
331
332    fn eval_statement_block(&mut self, token: Pair<'a>) -> ParserResult<Val> {
333        Ok(self
334            .safe_eval_statements(token)?
335            .iter()
336            .last()
337            .cloned()
338            .unwrap_or(Val::Null))
339    }
340
341    fn eval_statements(&mut self, token: Pair<'a>) -> ParserResult<Vec<Val>> {
342        //check_rule!(token, Rule::statements);
343        let pairs = token.into_inner();
344        let mut statements = vec![];
345
346        for token in pairs {
347            let s = self.eval_statement(token)?;
348            statements.push(s);
349        }
350        Ok(statements)
351    }
352
353    fn safe_eval_statements(&mut self, token: Pair<'a>) -> ParserResult<Vec<Val>> {
354        //check_rule!(token, Rule::statements);
355        let pairs = token.into_inner();
356        let mut statements = vec![];
357
358        for token in pairs {
359            match self.eval_statement(token.clone()) {
360                Ok(s) => statements.push(s),
361                Err(err) => {
362                    self.errors.push(err);
363                    statements.push(Val::ScriptText(token.as_str().to_string()));
364                }
365            }
366        }
367        Ok(statements)
368    }
369
370    fn parse_dq(&mut self, token: Pair<'a>) -> ParserResult<String> {
371        let mut res_str = String::new();
372        let pairs = token.into_inner();
373        for token in pairs {
374            let token = token.into_inner().next().unwrap();
375            let s = match token.as_rule() {
376                Rule::variable => self.get_variable(token)?.cast_to_string(),
377                Rule::sub_expression => self.safe_eval_sub_expr(token)?.cast_to_string(),
378                Rule::backtick_escape => token
379                    .as_str()
380                    .strip_prefix("`")
381                    .unwrap_or_default()
382                    .to_string(),
383                _ => token.as_str().to_string(),
384            };
385            res_str.push_str(s.as_str());
386        }
387        Ok(res_str)
388    }
389
390    fn eval_string_literal(&mut self, token: Pair<'a>) -> ParserResult<Val> {
391        check_rule!(token, Rule::string_literal);
392        let mut pair = token.into_inner();
393        let token = pair.next().unwrap();
394        let cloned_token = token.clone();
395
396        let mut is_expandable = false;
397        let res = match token.as_rule() {
398            Rule::doublequoted_string_literal | Rule::doublequoted_multiline_string_literal => {
399                is_expandable = true;
400                self.parse_dq(token)?
401            }
402            Rule::singlequoted_string_literal => {
403                if let Some(stripped_prefix) = token.as_str().to_string().strip_prefix("'") {
404                    if let Some(stripped_suffix) = stripped_prefix.to_string().strip_suffix("'") {
405                        stripped_suffix.to_string()
406                    } else {
407                        panic!("no suffix")
408                    }
409                } else {
410                    panic!("no prefix")
411                }
412            }
413            Rule::singlequoted_multiline_string_literal => {
414                let mut res_str = String::new();
415                let pairs = token.into_inner();
416                for token in pairs {
417                    res_str.push_str(token.as_str());
418                }
419                res_str
420            }
421            _ => {
422                panic!("eval_string_literal - token.rule(): {:?}", token.as_rule());
423            }
424        };
425        let ps_token = if is_expandable {
426            Token::StringExpandable(cloned_token.as_str().to_string(), res.clone())
427        } else {
428            Token::String(cloned_token.as_str().to_string())
429        };
430        self.tokens.push(ps_token);
431
432        Ok(Val::String(res.into()))
433    }
434
435    fn get_variable(&mut self, token: Pair<'a>) -> ParserResult<Val> {
436        check_rule!(token, Rule::variable);
437        let var_name = Self::parse_variable(token)?;
438        let Some(var) = self.variables.get(&var_name) else {
439            return Err(ParserError::VariableError(VariableError::NotDefined(
440                var_name.name,
441            )));
442        };
443        Ok(var)
444    }
445
446    fn parse_variable(token: Pair<'a>) -> ParserResult<VarName> {
447        check_rule!(token, Rule::variable);
448        let mut pair = token.into_inner();
449        let token = pair.next().unwrap();
450
451        Ok(match token.as_rule() {
452            Rule::special_variable => VarName::new(Scope::Special, token.as_str().to_string()),
453            Rule::parenthesized_variable => {
454                Self::parse_variable(token.into_inner().next().unwrap())?
455            }
456            Rule::braced_variable => {
457                let token = token.into_inner().next().unwrap();
458                let var = token.as_str().to_ascii_lowercase();
459                let splits: Vec<&str> = var.split(":").collect();
460                if splits.len() == 2 {
461                    VarName::new(Scope::from(splits[0]), splits[1].to_string())
462                } else {
463                    VarName::new(Scope::Global, var)
464                }
465            }
466            Rule::scoped_variable => {
467                let mut pairs = token.into_inner();
468                let mut token = pairs.next().unwrap();
469
470                let scope = if token.as_rule() == Rule::scope_keyword {
471                    let scope = token.as_str().to_ascii_lowercase();
472                    token = pairs.next().unwrap();
473                    check_rule!(token, Rule::var_name);
474                    Scope::from(scope.as_str())
475                } else {
476                    Scope::Global
477                };
478                VarName::new(scope, token.as_str().to_ascii_lowercase())
479            }
480            _ => {
481                panic!("token.rule(): {:?}", token.as_rule());
482            }
483        })
484    }
485
486    fn eval_expression_with_unary_operator(&mut self, token: Pair<'a>) -> ParserResult<Val> {
487        check_rule!(token, Rule::expression_with_unary_operator);
488        let mut pair = token.into_inner();
489        let token = pair.next().unwrap();
490
491        let res = match token.as_rule() {
492            Rule::pre_inc_expression => {
493                let variable_token = token.into_inner().next().unwrap();
494                let var_name = Self::parse_variable(variable_token)?;
495                let mut var = self.variables.get(&var_name).unwrap_or_default();
496                var.inc()?;
497
498                self.variables.set(&var_name, var.clone())?;
499                var
500            }
501            Rule::pre_dec_expression => {
502                let variable_token = token.into_inner().next().unwrap();
503                let var_name = Self::parse_variable(variable_token)?;
504                let mut var = self.variables.get(&var_name).unwrap_or_default();
505                var.dec()?;
506
507                self.variables.set(&var_name, var.clone())?;
508                var
509            }
510            Rule::cast_expression => self.eval_cast_expression(token)?,
511            Rule::negate_op => {
512                let unary_token = pair.next().unwrap();
513                let unary = self.eval_unary_exp(unary_token)?;
514                Val::Bool(!unary.cast_to_bool())
515            }
516            Rule::bitwise_negate_op => {
517                let unary_token = pair.next().unwrap();
518                let unary = self.eval_unary_exp(unary_token)?;
519                Val::Int(!unary.cast_to_int()?)
520            }
521            _ => {
522                panic!("token.rule(): {:?}", token.as_rule());
523            }
524        };
525
526        Ok(res)
527    }
528
529    fn eval_argument_list(&mut self, token: Pair<'a>) -> ParserResult<Vec<Val>> {
530        check_rule!(token, Rule::argument_list);
531        let pairs = token.into_inner();
532
533        let mut args = Vec::new();
534        for token in pairs {
535            args.push(self.eval_expression(token)?);
536        }
537
538        Ok(args)
539    }
540
541    fn eval_member_access(&mut self, token: Pair<'a>) -> ParserResult<String> {
542        //check_rule!(token, Rule::member_access);
543        let member_name_token = token.into_inner().next().unwrap();
544        let member_name = member_name_token.as_str().to_ascii_lowercase();
545
546        Ok(member_name)
547    }
548
549    fn method_is_static(&mut self, token: Pair<'a>) -> bool {
550        check_rule!(token, Rule::method_invocation);
551        let mut pairs = token.into_inner();
552
553        let access = pairs.next().unwrap();
554        match access.as_rule() {
555            Rule::member_access => false,
556            Rule::static_access => true,
557            _ => todo!(),
558        }
559    }
560
561    fn eval_method_invokation(&mut self, token: Pair<'a>) -> ParserResult<(String, Vec<Val>)> {
562        check_rule!(token, Rule::method_invocation);
563        let token_string = token.as_str().to_string();
564
565        let mut pairs = token.into_inner();
566
567        let access = pairs.next().unwrap();
568        //check_rule!(member_access, Rule::member_access);
569        let method_name = self.eval_member_access(access)?;
570
571        let args = if let Some(token) = pairs.next() {
572            check_rule!(token, Rule::argument_list);
573            self.eval_argument_list(token)?
574        } else {
575            Vec::new()
576        };
577
578        self.tokens.push(Token::Function(
579            token_string,
580            method_name.clone(),
581            args.clone().iter().map(|arg| arg.clone().into()).collect(),
582        ));
583        Ok((method_name, args))
584    }
585
586    fn eval_access(&mut self, token: Pair<'a>) -> ParserResult<Val> {
587        fn get_member_name(token: Pair<'_>) -> &'_ str {
588            token.into_inner().next().unwrap().as_str()
589        }
590        check_rule!(token, Rule::access);
591        let mut pairs = token.into_inner();
592        let token = pairs.next().unwrap();
593
594        let mut object = self.eval_value(token)?;
595
596        for token in pairs {
597            match token.as_rule() {
598                Rule::static_access => {
599                    object = object.get_static_member(get_member_name(token))?;
600                }
601                Rule::member_access => {
602                    object = object.get_member(get_member_name(token))?;
603                }
604                Rule::method_invocation => {
605                    let static_method = self.method_is_static(token.clone());
606                    let (function_name, args) = self.eval_method_invokation(token)?;
607                    log::trace!("Method: {:?} {:?}", &function_name, &args);
608                    object = if static_method {
609                        let call = object.get_static_fn(function_name.as_str())?;
610                        call(args)?
611                    } else {
612                        let call = object.get_method(function_name.as_str())?;
613                        call(object, args)?
614                    };
615                }
616                Rule::element_access => {
617                    let mut pairs = token.into_inner();
618                    let index_token = pairs.next().unwrap();
619                    check_rule!(index_token, Rule::expression);
620                    let index = self.eval_expression(index_token)?;
621                    object = object.get_index(index)?;
622                }
623                _ => {
624                    panic!("token.rule(): {:?}", token.as_rule());
625                }
626            }
627        }
628        log::debug!("Success eval_access: {:?}", object);
629        Ok(object)
630    }
631
632    fn parse_access(&mut self, token: Pair<'a>) -> ParserResult<Val> {
633        check_rule!(token, Rule::access);
634        let mut pairs = token.into_inner();
635        let token = pairs.next().unwrap();
636
637        let mut object = token.as_str().to_string();
638
639        for token in pairs {
640            match token.as_rule() {
641                Rule::static_access => {
642                    object.push_str("::");
643                    object.push_str(token.as_str());
644                }
645                Rule::member_access => {
646                    //object.push('.');
647                    object.push_str(token.as_str());
648                }
649                Rule::method_invocation => {
650                    let static_method = self.method_is_static(token.clone());
651                    let (method_name, args) = self.eval_method_invokation(token)?;
652
653                    let separator = if static_method { "::" } else { "." };
654                    object = format!(
655                        "{}{separator}{}({:?})",
656                        object,
657                        method_name.to_ascii_lowercase(),
658                        args
659                    )
660                }
661                Rule::element_access => {
662                    let mut pairs = token.into_inner();
663                    let index_token = pairs.next().unwrap();
664                    check_rule!(index_token, Rule::expression);
665                    let index = self.eval_expression(index_token)?;
666                    object = format!("{}[{}]", object, index);
667                }
668                _ => {
669                    panic!("parse_access token.rule(): {:?}", token.as_rule());
670                }
671            }
672        }
673        Ok(Val::String(object.into()))
674    }
675
676    fn eval_primary_expression(&mut self, token: Pair<'a>) -> ParserResult<Val> {
677        check_rule!(token, Rule::primary_expression);
678        let mut pair = token.into_inner();
679        let token = pair.next().unwrap();
680        let res = match token.as_rule() {
681            Rule::access => match self.eval_access(token.clone()) {
682                Ok(res) => res,
683                Err(err) => {
684                    log::info!("eval_access error: {:?}", err);
685                    self.errors.push(err);
686                    self.parse_access(token)?
687                }
688            },
689            Rule::value => self.eval_value(token)?,
690            Rule::post_inc_expression => {
691                let variable_token = token.into_inner().next().unwrap();
692                let var_name = Self::parse_variable(variable_token)?;
693                let mut var = self.variables.get(&var_name).unwrap_or_default();
694                let var_to_return = var.clone();
695
696                var.inc()?;
697                self.variables.set(&var_name, var.clone())?;
698
699                //if var_to_return.ttype() ==
700                var_to_return
701            }
702            Rule::post_dec_expression => {
703                let variable_token = token.into_inner().next().unwrap();
704                let var_name = Self::parse_variable(variable_token)?;
705                let mut var = self.variables.get(&var_name).unwrap_or_default();
706                let var_to_return = var.clone();
707
708                var.dec()?;
709                self.variables.set(&var_name, var.clone())?;
710
711                var_to_return
712            }
713            _ => {
714                panic!(
715                    "eval_primary_expression: rule: {:?} str: {}",
716                    token.as_rule(),
717                    token.as_str()
718                );
719            }
720        };
721
722        Ok(res)
723    }
724
725    fn eval_type_literal(&mut self, token: Pair<'a>) -> ParserResult<ValType> {
726        check_rule!(token, Rule::type_literal);
727
728        let token = token.into_inner().next().unwrap();
729        check_rule!(token, Rule::type_spec);
730        Ok(ValType::cast(token.as_str())?)
731    }
732
733    fn parse_script_block_expression(&mut self, token: Pair<'a>) -> ParserResult<Val> {
734        check_rule!(token, Rule::script_block_expression);
735
736        let mut pairs = token.into_inner();
737        let token = pairs.next().unwrap();
738
739        Ok(Val::ScriptBlock(ScriptBlock(token.as_str().to_string())))
740    }
741
742    fn eval_hash_key(&mut self, token: Pair<'a>) -> ParserResult<String> {
743        check_rule!(token, Rule::key_expression);
744        let mut pairs = token.into_inner();
745        let key_token = pairs.next().unwrap();
746
747        Ok(match key_token.as_rule() {
748            Rule::simple_name => key_token.as_str().to_ascii_lowercase(),
749            Rule::unary_exp => self
750                .eval_unary_exp(key_token)?
751                .cast_to_string()
752                .to_ascii_lowercase(),
753            _ => {
754                panic!("key_token.rule(): {:?}", key_token.as_rule());
755            }
756        })
757    }
758
759    fn eval_hash_entry(&mut self, token: Pair<'a>) -> ParserResult<(String, Val)> {
760        check_rule!(token, Rule::hash_entry);
761
762        let mut pairs = token.into_inner();
763        let token_key = pairs.next().unwrap();
764        let token_value = pairs.next().unwrap();
765
766        Ok((
767            self.eval_hash_key(token_key)?,
768            self.eval_statement(token_value)?,
769        ))
770    }
771
772    fn eval_hash_literal(&mut self, token: Pair<'a>) -> ParserResult<Val> {
773        check_rule!(token, Rule::hash_literal_expression);
774        let pairs = token.into_inner();
775        let mut hash = HashMap::new();
776        for token in pairs {
777            let (key, value) = self.eval_hash_entry(token)?;
778            hash.insert(key, value);
779        }
780        Ok(Val::HashTable(hash))
781    }
782
783    fn eval_value(&mut self, token: Pair<'a>) -> ParserResult<Val> {
784        check_rule!(token, Rule::value);
785        let mut pair = token.into_inner();
786        let token = pair.next().unwrap();
787
788        let res = match token.as_rule() {
789            Rule::parenthesized_expression => {
790                let token = token.into_inner().next().unwrap();
791                self.safe_eval_pipeline(token)?
792            }
793            Rule::sub_expression | Rule::array_expression => {
794                let statements = self.eval_statements(token)?;
795                if statements.len() == 1 && statements[0].ttype() == ValType::Array {
796                    statements[0].clone()
797                } else {
798                    Val::Array(statements)
799                }
800            }
801            Rule::script_block_expression => self.parse_script_block_expression(token)?,
802            Rule::hash_literal_expression => self.eval_hash_literal(token)?,
803            Rule::string_literal => self.eval_string_literal(token)?,
804            Rule::number_literal => self.eval_number_literal(token)?,
805            Rule::type_literal => Val::init(self.eval_type_literal(token)?)?,
806            Rule::variable => self.get_variable(token)?,
807            _ => {
808                panic!("token.rule(): {:?}", token.as_rule());
809            }
810        };
811        log::debug!("eval_value - res: {:?}", res);
812        Ok(res)
813    }
814
815    fn eval_number_literal(&mut self, token: Pair<'a>) -> ParserResult<Val> {
816        check_rule!(token, Rule::number_literal);
817        let mut negate = false;
818        let mut pairs = token.into_inner();
819        let mut token = pairs.next().unwrap();
820
821        //first handle prefix sign: + or -
822        if token.as_rule() == Rule::minus {
823            negate = true;
824            token = pairs.next().unwrap();
825        } else if token.as_rule() == Rule::plus {
826            token = pairs.next().unwrap();
827        }
828
829        let mut val = self.eval_number(token)?;
830
831        if negate {
832            val.neg()?;
833        }
834
835        if let Some(unit) = pairs.next() {
836            let unit = unit.as_str().to_ascii_lowercase();
837            let unit_int = match unit.as_str() {
838                "k" => 1024,
839                "m" => 1024 * 1024,
840                "g" => 1024 * 1024 * 1024,
841                "t" => 1024 * 1024 * 1024 * 1024,
842                "p" => 1024 * 1024 * 1024 * 1024 * 1024,
843                _ => 1,
844            };
845            val.mul(Val::Int(unit_int))?;
846        }
847        Ok(val)
848    }
849
850    fn eval_number(&mut self, token: Pair<'a>) -> ParserResult<Val> {
851        check_rule!(token, Rule::number);
852        let mut pairs = token.into_inner();
853        let token = pairs.next().unwrap();
854        let v = match token.as_rule() {
855            Rule::decimal_integer => {
856                let int_val = token.into_inner().next().unwrap();
857                Val::Int(int_val.as_str().parse::<i64>().unwrap())
858            }
859            Rule::hex_integer => {
860                let int_val = token.into_inner().next().unwrap();
861                Val::Int(i64::from_str_radix(int_val.as_str(), 16).unwrap())
862            }
863            //todo: parse float in proper way
864            Rule::float => {
865                let float_str = token.as_str().trim();
866
867                match float_str.parse::<f64>() {
868                    Ok(float_val) => Val::Float(float_val),
869                    Err(err) => {
870                        println!("eval_number - invalid float: {}: asd {}", float_str, err);
871                        panic!("eval_number - invalid float: {}: {}", float_str, err);
872                    }
873                }
874            }
875            _ => {
876                panic!("eval_number - token.rule(): {:?}", token.as_rule());
877            }
878        };
879        Ok(v)
880    }
881
882    fn eval_unary_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
883        check_rule!(token, Rule::unary_exp);
884        let token = token.into_inner().next().unwrap();
885        match token.as_rule() {
886            Rule::expression_with_unary_operator => self.eval_expression_with_unary_operator(token),
887            Rule::primary_expression => self.eval_primary_expression(token),
888            _ => {
889                panic!("eval_unary_exp token.rule(): {:?}", token.as_rule());
890            }
891        }
892    }
893
894    fn eval_array_literal_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
895        check_rule!(token, Rule::array_literal_exp);
896        let mut arr = Vec::new();
897        let mut pairs = token.into_inner();
898        arr.push(self.eval_unary_exp(pairs.next().unwrap())?);
899        for token in pairs {
900            arr.push(self.eval_unary_exp(token)?);
901        }
902
903        Ok(if arr.len() == 1 {
904            arr[0].clone()
905        } else {
906            Val::Array(arr)
907        })
908    }
909
910    fn eval_range_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
911        fn range(left: i64, right: i64) -> Vec<Val> {
912            if left < right {
913                (left..=right).collect::<Vec<i64>>()
914            } else {
915                let mut v = (right..=left).collect::<Vec<i64>>();
916                v.reverse();
917                v
918            }
919            .into_iter()
920            .map(Val::Int)
921            .collect::<Vec<Val>>()
922        }
923        check_rule!(token, Rule::range_exp);
924        let mut pairs = token.into_inner();
925        let token = pairs.next().unwrap();
926        let res = match token.as_rule() {
927            Rule::decimal_integer => {
928                let int_val = token.into_inner().next().unwrap();
929                let left = int_val.as_str().parse::<i64>().unwrap();
930                let token = pairs.next().unwrap();
931                let right = self.eval_array_literal_exp(token)?.cast_to_int()?;
932                Val::Array(range(left, right))
933            }
934            Rule::array_literal_exp => {
935                let res = self.eval_array_literal_exp(token)?;
936                if let Some(token) = pairs.next() {
937                    let left = res.cast_to_int()?;
938                    let right = self.eval_array_literal_exp(token)?.cast_to_int()?;
939                    Val::Array(range(left, right))
940                } else {
941                    res
942                }
943            }
944            _ => {
945                panic!("eval_range_exp not implemented: {:?}", token.as_rule());
946            }
947        };
948
949        Ok(res)
950    }
951
952    fn eval_format_impl(&mut self, format: Val, mut pairs: Pairs<'a>) -> ParserResult<Val> {
953        fn format_with_vec(fmt: &str, args: Vec<Val>) -> ParserResult<String> {
954            fn strange_special_case(fmt: &str, n: i64) -> String {
955                fn split_digits(n: i64) -> Vec<u8> {
956                    n.abs() // ignore sign for digit splitting
957                        .to_string()
958                        .chars()
959                        .filter_map(|c| c.to_digit(10).map(|opt| opt as u8))
960                        .collect()
961                }
962
963                //"{0:31sdfg,0100a0b00}" -f 578 evals to 310100a5b78
964                let mut digits = split_digits(n);
965                digits.reverse();
966                let mut fmt_vec = fmt.as_bytes().to_vec();
967                fmt_vec.reverse();
968
969                let mut i = 0;
970                for digit in digits {
971                    while i < fmt_vec.len() {
972                        if fmt_vec[i] != b'0' {
973                            i += 1
974                        } else {
975                            fmt_vec[i] = digit + b'0';
976                            break;
977                        }
978                    }
979                }
980                fmt_vec.reverse();
981                String::from_utf8(fmt_vec).unwrap_or_default()
982            }
983
984            let mut output = String::new();
985            let mut i = 0;
986
987            while i < fmt.len() {
988                if fmt[i..].starts_with('{') {
989                    if let Some(end) = fmt[i..].find('}') {
990                        let token = &fmt[i + 1..i + end];
991                        let formatted = if token.contains(':') {
992                            let mut parts = token.split(':');
993                            let index: usize = if let Some(p) = parts.next() {
994                                p.parse().unwrap_or(0)
995                            } else {
996                                0
997                            };
998
999                            let spec = parts.next();
1000                            match args.get(index) {
1001                                Some(val) => match spec {
1002                                    Some(s) if s.starts_with('N') => {
1003                                        let precision = s[1..].parse::<usize>().unwrap_or(2);
1004                                        if let Ok(f) = val.cast_to_float() {
1005                                            format!("{:.1$}", f, precision)
1006                                        } else {
1007                                            val.cast_to_string().to_string()
1008                                        }
1009                                    }
1010                                    Some(s) => strange_special_case(s, val.cast_to_int()?),
1011                                    None => val.cast_to_string().to_string(),
1012                                },
1013                                None => format!("{{{}}}", token), /* leave as-is if index out of
1014                                                                   * bounds */
1015                            }
1016                        } else if token.contains(',') {
1017                            let mut parts = token.split(',');
1018                            let index: usize = parts.next().unwrap().parse().unwrap_or(0);
1019                            let spec = parts.next();
1020                            match args.get(index) {
1021                                Some(val) => match spec {
1022                                    Some(s) => {
1023                                        let spaces = s.parse::<usize>().unwrap_or(0);
1024                                        let spaces_str = " ".repeat(spaces);
1025                                        format!("{spaces_str}{}", val.cast_to_string())
1026                                    }
1027                                    _ => val.cast_to_string().to_string(),
1028                                },
1029                                None => format!("{{{}}}", token), /* leave as-is if index out of
1030                                                                   * bounds */
1031                            }
1032                        } else {
1033                            let index: usize =
1034                                Val::String(token.to_string().into()).cast_to_int()? as usize;
1035                            match args.get(index) {
1036                                Some(val) => val.cast_to_string().to_string(),
1037                                None => format!("{{{}}}", token), /* leave as-is if index out of
1038                                                                   * bounds */
1039                            }
1040                        };
1041
1042                        output.push_str(&formatted);
1043                        i += end + 1;
1044                    } else {
1045                        output.push('{');
1046                        i += 1;
1047                    }
1048                } else {
1049                    output.push(fmt[i..].chars().next().unwrap());
1050                    i += 1;
1051                }
1052            }
1053
1054            Ok(output)
1055        }
1056
1057        Ok(if let Some(token) = pairs.next() {
1058            let first_fmt = format.cast_to_string();
1059
1060            let second_fmt = self.eval_range_exp(token)?;
1061            let res = self.eval_format_impl(second_fmt, pairs)?;
1062            Val::String(format_with_vec(first_fmt.as_str(), res.cast_to_array())?.into())
1063        } else {
1064            format
1065        })
1066    }
1067
1068    fn eval_format_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1069        check_rule!(token, Rule::format_exp);
1070        let mut pairs = token.into_inner();
1071        let format = self.eval_range_exp(pairs.next().unwrap())?;
1072        self.eval_format_impl(format, pairs)
1073    }
1074
1075    fn eval_mult(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1076        check_rule!(token, Rule::multiplicative_exp);
1077        let mut pairs = token.into_inner();
1078        let mut res = self.eval_format_exp(pairs.next().unwrap())?;
1079        while let Some(op) = pairs.next() {
1080            let Some(fun) = ArithmeticPred::get(op.as_str()) else {
1081                panic!(
1082                    "can't find arithmetic function for operator: {}",
1083                    op.as_str()
1084                )
1085            };
1086
1087            let postfix = pairs.next().unwrap();
1088            let right_op = self.eval_format_exp(postfix)?;
1089            res = fun(res, right_op)?;
1090        }
1091
1092        Ok(res)
1093    }
1094
1095    fn eval_additive(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1096        check_rule!(token, Rule::additive_exp);
1097
1098        let mut pairs = token.into_inner();
1099        let mut res = self.eval_mult(pairs.next().unwrap())?;
1100        while let Some(op) = pairs.next() {
1101            //check_rule!(op, Rule::additive_op); plus or minus
1102            let Some(fun) = ArithmeticPred::get(op.as_str()) else {
1103                panic!()
1104            };
1105
1106            let mult = pairs.next().unwrap();
1107            let right_op = self.eval_mult(mult)?;
1108            res = fun(res, right_op)?;
1109        }
1110
1111        Ok(res)
1112    }
1113
1114    fn eval_split_special_case(
1115        &mut self,
1116        token: Pair<'a>,
1117        input: Val,
1118    ) -> ParserResult<Vec<String>> {
1119        let mut res_vec = vec![];
1120        let mut parts = String::new();
1121        let input_str = input.cast_to_string();
1122        let characters = input_str.chars();
1123
1124        // filtered_elements.join("")
1125        for ch in characters {
1126            self.variables
1127                .set_ps_item(Val::String(ch.to_string().into()));
1128
1129            let b = match self.eval_script_block(
1130                &ScriptBlock(token.as_str().to_string()),
1131                &Val::String(ch.to_string().into()),
1132            ) {
1133                Err(er) => {
1134                    self.errors.push(er);
1135                    false
1136                }
1137                Ok(b) => b,
1138            };
1139
1140            if b {
1141                res_vec.push(parts);
1142                parts = String::new();
1143            } else {
1144                parts.push(ch);
1145            }
1146        }
1147        self.variables.reset_ps_item();
1148        Ok(res_vec)
1149    }
1150    fn eval_comparison_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1151        check_rule!(token, Rule::comparison_exp);
1152        let mut pairs = token.into_inner();
1153        let token = pairs.next().unwrap();
1154
1155        // we need to handle strange case. -split and -join can be invoke without
1156        // previous expression, eg. "-join 'some'"
1157        let mut res = if token.as_rule() == Rule::additive_exp {
1158            self.eval_additive(token)?
1159        } else {
1160            Val::Null
1161        };
1162
1163        while let Some(op) = pairs.next() {
1164            let Some(fun) = StringPred::get(op.as_str()) else {
1165                panic!("no operator: {}", op.as_str())
1166            };
1167
1168            let token = pairs.next().unwrap();
1169            let right_op = match token.as_rule() {
1170                Rule::script_block_expression => {
1171                    let mut pairs = token.into_inner();
1172                    let token = pairs.next().unwrap();
1173                    check_rule!(token, Rule::script_block_inner);
1174
1175                    let mut pairs = token.into_inner();
1176                    let mut token = pairs.next().unwrap();
1177                    if token.as_rule() == Rule::param_block {
1178                        //skip for now
1179                        token = pairs.next().unwrap();
1180                    }
1181                    check_rule!(token, Rule::script_block);
1182                    return Ok(Val::Array(
1183                        self.eval_split_special_case(token, res)?
1184                            .into_iter()
1185                            .map(|s| Val::String(s.into()))
1186                            .collect::<Vec<_>>(),
1187                    ));
1188                }
1189                Rule::additive_exp => self.eval_additive(token)?,
1190                _ => {
1191                    panic!("eval_comparison_exp not implemented: {:?}", token.as_rule());
1192                }
1193            };
1194            log::trace!("res: {:?}, right_op: {:?}", &res, &right_op);
1195            res = fun(res, right_op)?;
1196            log::trace!("res: {:?}", &res);
1197        }
1198
1199        Ok(res)
1200    }
1201
1202    fn eval_bitwise_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1203        check_rule!(token, Rule::bitwise_exp);
1204
1205        let mut pairs = token.into_inner();
1206        let mut res = self.eval_comparison_exp(pairs.next().unwrap())?;
1207        while let Some(op) = pairs.next() {
1208            check_rule!(op, Rule::bitwise_operator);
1209            let Some(fun) = BitwisePred::get(op.as_str()) else {
1210                panic!()
1211            };
1212
1213            let mult = pairs.next().unwrap();
1214            let right_op = self.eval_comparison_exp(mult)?;
1215            res = fun(res, right_op);
1216        }
1217
1218        Ok(res)
1219    }
1220
1221    fn parse_long_command(&mut self, token: Pair<'a>) -> ParserResult<(String, Vec<CommandElem>)> {
1222        check_rule!(token, Rule::long_command);
1223
1224        let mut pairs = token.into_inner();
1225        let command_name_token = pairs.next().unwrap();
1226        let command_name = command_name_token.as_str();
1227
1228        let mut args = vec![];
1229        for command_element_token in pairs {
1230            let token_string = command_element_token.as_str().to_string();
1231            match command_element_token.as_rule() {
1232                Rule::command_argument => {
1233                    let arg_token = command_element_token.into_inner().next().unwrap();
1234                    let arg = match arg_token.as_rule() {
1235                        Rule::array_literal_exp => self.eval_array_literal_exp(arg_token)?,
1236                        Rule::parenthesized_expression => {
1237                            let token = arg_token.into_inner().next().unwrap();
1238                            self.eval_pipeline(token)?
1239                        }
1240                        _ => Val::String(arg_token.as_str().to_string().into()),
1241                    };
1242                    args.push(CommandElem::Argument(arg));
1243                }
1244                Rule::command_parameter => args.push(CommandElem::Parameter(token_string)),
1245                Rule::argument_list => args.push(CommandElem::ArgList(token_string)),
1246                Rule::redirection => { //todo: implement redirection
1247                }
1248                Rule::stop_parsing => { //todo: stop parsing
1249                }
1250                Rule::script_block_expression => args.push(CommandElem::Argument(
1251                    self.parse_script_block_expression(command_element_token)?,
1252                )),
1253                _ => panic!(
1254                    "eval_command not implemented: {:?}",
1255                    command_element_token.as_rule()
1256                ),
1257            }
1258        }
1259        Ok((command_name.to_string(), args))
1260    }
1261
1262    fn parse_script_block_command(
1263        &mut self,
1264        token: Pair<'a>,
1265    ) -> ParserResult<(String, Vec<CommandElem>)> {
1266        check_rule!(token, Rule::script_block_command);
1267
1268        let mut pairs = token.into_inner();
1269        let command_name_token = pairs.next().unwrap();
1270        let command_name = command_name_token.as_str();
1271        let command_element_token = pairs.next().unwrap();
1272
1273        check_rule!(command_element_token, Rule::script_block_expression);
1274        let script_block = self.parse_script_block_expression(command_element_token)?;
1275        Ok((
1276            command_name.to_string(),
1277            vec![CommandElem::Argument(script_block)],
1278        ))
1279    }
1280
1281    fn eval_command(&mut self, token: Pair<'a>, input: Option<Val>) -> ParserResult<Val> {
1282        check_rule!(token, Rule::command);
1283
1284        let mut pairs = token.into_inner();
1285        //unfortunately I can't make long_command silent
1286
1287        let mut args = if let Some(v) = input {
1288            vec![CommandElem::Argument(v)]
1289        } else {
1290            Vec::new()
1291        };
1292
1293        let command = pairs.next().unwrap();
1294        let (command_name, mut command_args) = match command.as_rule() {
1295            Rule::script_block_command => self.parse_script_block_command(command)?,
1296            Rule::foreach_command => Err(ParserError::NotImplemented("foreach_command".into()))?,
1297            Rule::long_command => self.parse_long_command(command)?,
1298            Rule::invocation_command => {
1299                Err(ParserError::NotImplemented("invocation_command".into()))?
1300            }
1301            _ => panic!("eval_command not implemented: {:?}", command.as_rule()),
1302        };
1303        args.append(&mut command_args);
1304
1305        let CommandOutput {
1306            val,
1307            deobfuscated,
1308            stream,
1309        } = Command::execute(self, command_name.as_str(), args)?;
1310
1311        if let Some(msg) = deobfuscated {
1312            self.deobfuscated_statements.push(msg);
1313        }
1314
1315        if let Some(msg) = stream {
1316            self.output.push(msg);
1317        }
1318
1319        Ok(val.unwrap_or_default())
1320    }
1321
1322    fn eval_redirected_expression(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1323        check_rule!(token, Rule::redirected_expression);
1324
1325        let expression_token = token.into_inner().next().unwrap();
1326        //todo: handle redirections
1327
1328        self.eval_expression(expression_token)
1329    }
1330
1331    fn eval_expression(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1332        check_rule!(token, Rule::expression);
1333        let token_string = token.as_str().trim().to_string();
1334
1335        let mut pairs = token.into_inner();
1336        let mut res = self.eval_bitwise_exp(pairs.next().unwrap())?;
1337        while let Some(op) = pairs.next() {
1338            check_rule!(op, Rule::logical_operator);
1339            let Some(fun) = LogicalPred::get(op.as_str()) else {
1340                panic!()
1341            };
1342
1343            let mult = pairs.next().unwrap();
1344            let right_op = self.eval_bitwise_exp(mult)?;
1345            res = Val::Bool(fun(res, right_op));
1346        }
1347        self.tokens
1348            .push(Token::Expression(token_string, res.clone().into()));
1349
1350        Ok(res)
1351    }
1352
1353    fn eval_pipeline_tail(&mut self, token: Pair<'a>, input: Val) -> ParserResult<Val> {
1354        check_rule!(token, Rule::pipeline_tail);
1355        let mut arg = input;
1356        let mut pairs = token.into_inner();
1357
1358        while let Some(token) = pairs.next() {
1359            arg = self.eval_command(token, Some(arg))?;
1360        }
1361
1362        Ok(arg)
1363    }
1364
1365    fn eval_pipeline_with_tail(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1366        check_rule!(token, Rule::pipeline_with_tail);
1367        let mut pairs = token.into_inner();
1368        let token = pairs.next().unwrap();
1369
1370        let result: Val = match token.as_rule() {
1371            Rule::redirected_expression => self.eval_redirected_expression(token)?,
1372            Rule::command => self.eval_command(token, None)?,
1373            _ => {
1374                panic!("eval_pipeline not implemented: {:?}", token.as_rule());
1375            }
1376        };
1377
1378        if let Some(token) = pairs.next() {
1379            match token.as_rule() {
1380                Rule::pipeline_tail => Ok(self.eval_pipeline_tail(token, result)?),
1381                _ => {
1382                    panic!("eval_pipeline not implemented: {:?}", token.as_rule());
1383                }
1384            }
1385        } else {
1386            Ok(result)
1387        }
1388    }
1389
1390    fn eval_pipeline(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1391        check_rule!(token, Rule::pipeline);
1392        let mut pairs = token.into_inner();
1393        let token = pairs.next().unwrap();
1394
1395        match token.as_rule() {
1396            Rule::assignment_exp => return self.eval_assigment_exp(token),
1397            Rule::pipeline_with_tail => return self.eval_pipeline_with_tail(token),
1398            _ => panic!("not possible: {:?}", token.as_rule()),
1399        }
1400    }
1401
1402    fn safe_eval_pipeline(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1403        let res = self.eval_pipeline(token.clone());
1404
1405        let v = match res {
1406            Ok(val) => val,
1407            Err(err) => {
1408                self.errors.push(err);
1409                Val::ScriptText(token.as_str().to_string())
1410            }
1411        };
1412
1413        Ok(v)
1414    }
1415
1416    fn eval_cast_expression(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1417        check_rule!(token, Rule::cast_expression);
1418
1419        let mut pairs = token.into_inner();
1420        let type_token = pairs.next().unwrap();
1421        let val_type = self.eval_type_literal(type_token)?;
1422
1423        let token = pairs.next().unwrap();
1424        let mut res = match token.as_rule() {
1425            Rule::parenthesized_expression => {
1426                let token = token.into_inner().next().unwrap();
1427                self.safe_eval_pipeline(token)?
1428            }
1429            Rule::range_exp => self.eval_range_exp(token)?,
1430            Rule::unary_exp => self.eval_unary_exp(token)?,
1431            _ => {
1432                panic!(
1433                    "eval_cast_expression not implemented: {:?}",
1434                    token.as_rule()
1435                );
1436            }
1437        };
1438
1439        Ok(res.cast(val_type)?)
1440    }
1441
1442    fn eval_assigment_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1443        check_rule!(token, Rule::assignment_exp);
1444
1445        let mut pairs = token.into_inner();
1446        let variable_token = pairs.next().unwrap();
1447        let var_name = Self::parse_variable(variable_token)?;
1448        let var = self.variables.get(&var_name).unwrap_or_default();
1449
1450        let assignement_op = pairs.next().unwrap();
1451
1452        //get operand
1453        let op = assignement_op.into_inner().next().unwrap();
1454        let pred = ArithmeticPred::get(op.as_str());
1455
1456        let right_token = pairs.next().unwrap();
1457        let right_op = self.eval_pipeline(right_token.clone())?;
1458
1459        let Some(pred) = pred else { panic!() };
1460        let op_result = pred(var, right_op)?;
1461        self.variables.set(&var_name, op_result.clone())?;
1462
1463        //we want save each assignment statement
1464        self.deobfuscated_statements
1465            .push(format!("{} = {}", var_name, op_result.cast_to_script()));
1466        Ok(op_result)
1467    }
1468}
1469
1470#[cfg(test)]
1471mod tests {
1472    use pest::Parser;
1473
1474    use super::*;
1475
1476    #[test]
1477    fn comment_and_semicolon() {
1478        let input = r#"
1479# This is a single line comment
1480$a = 1; $b = 2; Write-Output $a
1481
1482Write-Output "Hello"  # Another comment
1483
1484<#
1485    This is a
1486    multi-line block comment
1487#>
1488"#;
1489
1490        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1491    }
1492
1493    #[test]
1494    fn while_loop() {
1495        let input = r#"
1496while ($true) {
1497    if ($someCondition) {
1498        break
1499    }
1500    # other code
1501}
1502"#;
1503
1504        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1505    }
1506
1507    #[test]
1508    fn foreach_loop() {
1509        let input = r#"
1510foreach ($n in $numbers) {
1511    Write-Output $n
1512}
1513"#;
1514
1515        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1516    }
1517
1518    #[test]
1519    fn for_loop() {
1520        let input = r#"
1521# Comma separated assignment expressions enclosed in parentheses.
1522for (($i = 0), ($j = 0); $i -lt 10; $i++)
1523{
1524    "`$i:$i"
1525    "`$j:$j"
1526}
1527"#;
1528
1529        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1530    }
1531
1532    #[test]
1533    fn switch() {
1534        let input = r#"
1535switch ($var) {
1536    "a" { Write-Output "A" }
1537    1 { Write-Output "One" }
1538    default { Write-Output "Other" }
1539}
1540"#;
1541
1542        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1543    }
1544
1545    #[test]
1546    fn functions() {
1547        let input = r#"
1548function Get-Square {
1549    param($x)
1550    return $x * $x
1551}
1552
1553function Say-Hello {
1554    Write-Output "Hello"
1555}
1556"#;
1557
1558        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1559    }
1560
1561    #[test]
1562    fn if_expression() {
1563        let input = r#"
1564$x="hello"
1565        Write-Host $x
1566        $y = 42
1567        Start-Process "notepad.exe"
1568
1569        $x = 42
1570if ($x -eq 1) {
1571    Write-Output "One"
1572} elseif ($x -eq 2) {
1573    Write-Output "Two"
1574} else {
1575    Write-Output "Other"
1576}
1577"#;
1578
1579        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1580    }
1581
1582    #[test]
1583    fn command() {
1584        let input = r#"
1585Get-Process | Where-Object { $_.CPU -gt 100 }
1586"#;
1587
1588        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1589    }
1590
1591    #[test]
1592    fn range() {
1593        let input = r#"
1594$numbers = 1..5
1595"#;
1596
1597        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1598    }
1599
1600    #[test]
1601    fn literals() {
1602        let input = r#"
1603$hex = 0xFF
1604
1605$name = "Alice"
1606$msg = "Hello, $name. Today is $day."
1607$escaped = "She said: `"Hi`""
1608$literal = 'Hello, $name'
1609"#;
1610
1611        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1612    }
1613
1614    #[test]
1615    fn floats() {
1616        let input = r#"
1617    $pi = 3.1415
1618$half = .5
1619"#;
1620
1621        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1622    }
1623
1624    #[test]
1625    fn arrays() {
1626        let input = r#"
1627$a = 1, 2, 3
1628$b = @("one", "two", "three")
1629$c = @(1, 2, @(3, 4))
1630"#;
1631
1632        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1633    }
1634
1635    #[test]
1636    fn static_method_call() {
1637        let input = r#"
1638[Threading.Thread]::Sleep(399)
1639"#;
1640
1641        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1642    }
1643
1644    #[test]
1645    fn neg_pipeline() {
1646        let input = r#"
1647-not $input | Where-Object { $_ -gt 5 }
1648"#;
1649
1650        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1651    }
1652
1653    #[test]
1654    fn amsi_fail() {
1655        let input = r#"
1656#Matt Graebers second Reflection method 
1657$VMRviwsbtehQfPtxbt=$null;
1658$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))"
1659
1660"#;
1661
1662        let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1663    }
1664}