1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
pub(crate) mod str_types {
    pub(crate) const STR_FUNC_ESCAPE: usize = 0x01;
    pub(crate) const STR_FUNC_EXPAND: usize = 0x02;
    pub(crate) const STR_FUNC_REGEXP: usize = 0x04;
    pub(crate) const STR_FUNC_QWORDS: usize = 0x08;
    pub(crate) const STR_FUNC_SYMBOL: usize = 0x10;
    pub(crate) const STR_FUNC_INDENT: usize = 0x20;
    pub(crate) const STR_FUNC_LABEL: usize = 0x40;
    pub(crate) const STR_FUNC_LIST: usize = 0x4000;
    pub(crate) const STR_FUNC_TERM: usize = 0x8000;

    #[allow(non_upper_case_globals)]
    pub(crate) const str_label: usize = STR_FUNC_LABEL;
    #[allow(non_upper_case_globals)]
    pub(crate) const str_squote: usize = 0;
    #[allow(non_upper_case_globals)]
    pub(crate) const str_dquote: usize = STR_FUNC_EXPAND;
    #[allow(non_upper_case_globals)]
    pub(crate) const str_xquote: usize = STR_FUNC_EXPAND;
    #[allow(non_upper_case_globals)]
    pub(crate) const str_regexp: usize = STR_FUNC_REGEXP | STR_FUNC_ESCAPE | STR_FUNC_EXPAND;
    #[allow(non_upper_case_globals)]
    pub(crate) const str_sword: usize = STR_FUNC_QWORDS | STR_FUNC_LIST;
    #[allow(non_upper_case_globals)]
    pub(crate) const str_dword: usize = STR_FUNC_QWORDS | STR_FUNC_EXPAND | STR_FUNC_LIST;
    #[allow(non_upper_case_globals)]
    pub(crate) const str_ssym: usize = STR_FUNC_SYMBOL;
    #[allow(non_upper_case_globals)]
    pub(crate) const str_dsym: usize = STR_FUNC_SYMBOL | STR_FUNC_EXPAND;
}

#[derive(Debug, Clone, Default)]
pub(crate) struct HeredocEnd {
    pub(crate) start: usize,
    pub(crate) end: usize,
    pub(crate) value: Vec<u8>,
}

#[derive(Debug, Clone, Default)]
pub(crate) struct StringLiteral {
    // struct rb_strterm_literal_struct
    pub(crate) nest: usize,
    pub(crate) func: usize,
    pub(crate) paren: Option<u8>,
    pub(crate) term: u8,
    pub(crate) heredoc_end: Option<HeredocEnd>,
}

impl StringLiteral {
    pub(crate) fn new(
        nest: usize,
        func: usize,
        paren: Option<u8>,
        term: u8,
        heredoc_end: Option<HeredocEnd>,
    ) -> Self {
        Self {
            nest,
            func,
            paren,
            term,
            heredoc_end,
        }
    }
}

#[derive(Debug, Clone, Default)]
pub(crate) struct HeredocLiteral {
    pub(crate) lastline: usize, /* the string of line that contains `<<"END"` */
    pub(crate) offset: usize,   /* the column of END in `<<"END"` */
    pub(crate) sourceline: usize, /* lineno of the line that contains `<<"END"` */
    pub(crate) length: usize,   /* the length of END in `<<"END"` */

    pub(crate) quote: usize,
    pub(crate) func: usize,
}

impl HeredocLiteral {
    pub(crate) fn new(
        lastline: usize,
        offset: usize,
        sourceline: usize,
        length: usize,
        quote: usize,
        func: usize,
    ) -> Self {
        Self {
            lastline,
            offset,
            sourceline,
            length,
            quote,
            func,
        }
    }
}

#[derive(Debug, Clone)]
pub(crate) enum StrTerm {
    // struct rb_strterm_struct
    StringLiteral(StringLiteral),
    HeredocLiteral(HeredocLiteral),
}

impl StrTerm {
    pub(crate) fn new_literal(literal: StringLiteral) -> Self {
        Self::StringLiteral(literal)
    }

    pub(crate) fn new_heredoc(heredoc: HeredocLiteral) -> Self {
        Self::HeredocLiteral(heredoc)
    }
}