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