ps_parser/
parser.rs

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