<commit_before>//! Implements parser to convert from ESIL to RadecoIR.

use num::traits::Num;

use std::collections::HashMap;
use std::cmp;
use regex::Regex;

use super::{MInst, MVal, MOpcode, MValType, Address, MArity, MRegInfo, MAddr};
use super::structs::{LOpInfo, LAliasInfo, LRegInfo, LRegProfile, LFlagInfo};
use super::super::middle::ssa::{SSAStorage, SSA};
use super::super::transform::ssa::SSAConstruction;

// Macro to return a new hash given (key, value) tuples.
// Example: hash![("foo", "bar"), ("bar", "baz")]
macro_rules! hash {
    ( $( ($x:expr, $y:expr) ),* ) => {
        {
            let mut temp_hash = HashMap::new();
            $(
                temp_hash.insert($x, $y);
             )*
                temp_hash
        }
    };
}

// Convert hex string ("0xbadc0de") to decimal representation.
macro_rules! hex_to_i {
    ( $x:expr ) => {
        Num::from_str_radix($x.trim_left_matches("0x"), 16)
    };
}

#[derive(Debug)]
pub enum ParseError {
    InvalidEsil,
    InvalidMOperator,
    InsufficientOperands,
}

#[allow(dead_code)]
pub struct Parser<'a> {
    stack:        Vec<MVal>,
    insts:        Vec<MInst>,
    opset:        HashMap<&'a str, MOpcode>,
    regset:       HashMap<String, LRegProfile>,
    alias_info:   HashMap<String, LAliasInfo>,
    flags:        HashMap<u64, LFlagInfo>,
    default_size: u8,
    tmp_prefix:   String,
    arch:         String,
    addr:         Address,
    opinfo:       Option<LOpInfo>,
    tmp_index:    u64,
    last_assgn:   MVal,
    ssa:          &'a SSAStorage,
    ssac:         Option<SSAConstruction<'a>>,
}

// Struct used to configure the Parser. If `None` is passed to any of the fields, then the default
// values are set.
pub struct ParserConfig<'a> {
    arch:         Option<String>,
    default_size: Option<u8>,
    tmp_prefix:   Option<String>,
    init_opset:   Option<fn() -> HashMap<&'a str, MOpcode>>,
    regset:       Option<HashMap<String, LRegProfile>>,
    alias_info:   Option<HashMap<String, LAliasInfo>>,
    flags:        Option<HashMap<u64, LFlagInfo>>,
}

impl<'a> Default for ParserConfig<'a> {
    fn default() -> Self {
        ParserConfig {
            arch:         Some("x86_64".to_string()),
            default_size: Some(64),
            tmp_prefix:   Some("tmp".to_string()),
            init_opset:   Some(map_esil_to_opset),
            regset:       Some(HashMap::new()),
            alias_info:   Some(HashMap::new()),
            flags:        Some(HashMap::new()),
        }
    }
}

impl<'a> Parser<'a> {
    pub fn new(config: Option<ParserConfig<'a>>, ssa: &'a mut SSAStorage) -> Parser<'a> {
        let config = config.unwrap_or_default();
        let arch = config.arch.unwrap_or("x86_64".to_string());
        let default_size = config.default_size.unwrap_or(64);
        let tmp_prefix = config.tmp_prefix.unwrap_or("tmp".to_string());
        let init_opset = config.init_opset.unwrap_or(map_esil_to_opset);
        let regset = config.regset.unwrap_or(HashMap::new());
        let alias_info = config.alias_info.unwrap_or(HashMap::new());
        let flags = config.flags.unwrap_or(HashMap::new());
        let val = MVal::null();

        Parser { 
            stack:        Vec::new(),
            insts:        Vec::new(),
            opset:        init_opset(),
            regset:       regset,
            default_size: default_size,
            arch:         arch,
            tmp_prefix:   tmp_prefix,
            addr:         0,
            opinfo:       None,
            alias_info:   alias_info,
            flags:        flags,
            tmp_index:    0,
            last_assgn:   val,
            ssa:          ssa,
            ssac:         None,
        }
    }

    pub fn set_register_profile(&mut self, reg_info: &LRegInfo) {
        self.ssac = Some(SSAConstruction::new(self.ssa, reg_info));
        self.regset = HashMap::new();
        let mut tmp: HashMap<String, LAliasInfo> = HashMap::new();<commit_msg>unbreak previous commit<commit_after>//! Implements parser to convert from ESIL to RadecoIR.

use num::traits::Num;

use std::collections::HashMap;
use std::cmp;
use regex::Regex;

use super::{MInst, MVal, MOpcode, MValType, Address, MArity, MRegInfo, MAddr};
use super::structs::{LOpInfo, LAliasInfo, LRegInfo, LRegProfile, LFlagInfo};
use super::super::middle::ssa::{SSAStorage, SSA};
use super::super::transform::ssa::SSAConstruction;

// Macro to return a new hash given (key, value) tuples.
// Example: hash![("foo", "bar"), ("bar", "baz")]
macro_rules! hash {
    ( $( ($x:expr, $y:expr) ),* ) => {
        {
            let mut temp_hash = HashMap::new();
            $(
                temp_hash.insert($x, $y);
             )*
                temp_hash
        }
    };
}

// Convert hex string ("0xbadc0de") to decimal representation.
macro_rules! hex_to_i {
    ( $x:expr ) => {
        Num::from_str_radix($x.trim_left_matches("0x"), 16)
    };
}

#[derive(Debug)]
pub enum ParseError {
    InvalidEsil,
    InvalidMOperator,
    InsufficientOperands,
}

#[allow(dead_code)]
pub struct Parser<'a> {
    stack:        Vec<MVal>,
    insts:        Vec<MInst>,
    opset:        HashMap<&'a str, MOpcode>,
    regset:       HashMap<String, LRegProfile>,
    alias_info:   HashMap<String, LAliasInfo>,
    flags:        HashMap<u64, LFlagInfo>,
    default_size: u8,
    tmp_prefix:   String,
    arch:         String,
    addr:         Address,
    opinfo:       Option<LOpInfo>,
    tmp_index:    u64,
    last_assgn:   MVal,
    ssac:         Option<SSAConstruction<'a>>,
}

// Struct used to configure the Parser. If `None` is passed to any of the fields, then the default
// values are set.
pub struct ParserConfig<'a> {
    arch:         Option<String>,
    default_size: Option<u8>,
    tmp_prefix:   Option<String>,
    init_opset:   Option<fn() -> HashMap<&'a str, MOpcode>>,
    regset:       Option<HashMap<String, LRegProfile>>,
    alias_info:   Option<HashMap<String, LAliasInfo>>,
    flags:        Option<HashMap<u64, LFlagInfo>>,
}

impl<'a> Default for ParserConfig<'a> {
    fn default() -> Self {
        ParserConfig {
            arch:         Some("x86_64".to_string()),
            default_size: Some(64),
            tmp_prefix:   Some("tmp".to_string()),
            init_opset:   Some(map_esil_to_opset),
            regset:       Some(HashMap::new()),
            alias_info:   Some(HashMap::new()),
            flags:        Some(HashMap::new()),
        }
    }
}

impl<'a> Parser<'a> {
    pub fn new(config: Option<ParserConfig<'a>>) -> Parser<'a> {
        let config = config.unwrap_or_default();
        let arch = config.arch.unwrap_or("x86_64".to_string());
        let default_size = config.default_size.unwrap_or(64);
        let tmp_prefix = config.tmp_prefix.unwrap_or("tmp".to_string());
        let init_opset = config.init_opset.unwrap_or(map_esil_to_opset);
        let regset = config.regset.unwrap_or(HashMap::new());
        let alias_info = config.alias_info.unwrap_or(HashMap::new());
        let flags = config.flags.unwrap_or(HashMap::new());
        let val = MVal::null();

        Parser { 
            stack:        Vec::new(),
            insts:        Vec::new(),
            opset:        init_opset(),
            regset:       regset,
            default_size: default_size,
            arch:         arch,
            tmp_prefix:   tmp_prefix,
            addr:         0,
            opinfo:       None,
            alias_info:   alias_info,
            flags:        flags,
            tmp_index:    0,
            last_assgn:   val,
            ssac:         None,
        }
    }

    pub fn set_register_profile(&mut self, reg_info: &LRegInfo, ssa: &'a mut SSAStorage) {
        self.ssac = Some(SSAConstruction::new(ssa, reg_info));

        self.regset = HashMap::new();
        let mut tmp: HashMap<String, LAliasInfo> = HashMap::new();
{'fraction_non_alphanumeric': 0.13756815012045137, 'fraction_numerical': 0.006846709775580068, 'mean_word_length': 2.259504132231405, 'pattern_counts': {'":': 0, '<': 63, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4083633', 'n_tokens_mistral': 2587, 'n_tokens_neox': 2621, 'n_words': 544}