Skip to main content

ps_parser/
parser.rs

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