lib_ruby_parser/lexer/
parse_percent.rs

1use crate::lexer::*;
2use crate::maybe_byte::*;
3use crate::source::buffer::*;
4use crate::str_term::str_types::*;
5use crate::DiagnosticMessage;
6use crate::{lex_states::*, LexState};
7
8impl Lexer {
9    fn percent_unknown(&mut self, term: MaybeByte) -> i32 {
10        self.buffer.pushback(term);
11        let len = self.multibyte_char_len(self.buffer.pcur);
12        match len {
13            Some(len) => self.buffer.pcur += len,
14            None => return Self::END_OF_INPUT,
15        }
16        self.yyerror1(
17            DiagnosticMessage::UnknownTypeOfPercentString {},
18            self.current_loc().adjust_end(-1),
19        );
20        Self::END_OF_INPUT
21    }
22
23    fn percent_quotation(&mut self, c: &mut MaybeByte, ptok: usize) -> i32 {
24        let term: MaybeByte;
25
26        if c.is_eof() {
27            return self.percent_unterminated();
28        }
29
30        if !c.is_alnum() {
31            term = *c;
32            if !c.is_ascii() {
33                return self.percent_unknown(term);
34            }
35            *c = MaybeByte::new(b'Q');
36        } else {
37            term = self.nextc();
38            if term.is_alnum() {
39                return self.percent_unknown(term);
40            }
41        }
42
43        let mut term = match term {
44            MaybeByte::EndOfInput => {
45                return self.percent_unterminated();
46            }
47            MaybeByte::Some(term) => term,
48        };
49
50        let mut paren = Some(term);
51        if term == b'(' {
52            term = b')';
53        } else if term == b'[' {
54            term = b']';
55        } else if term == b'{' {
56            term = b'}';
57        } else if term == b'<' {
58            term = b'>';
59        } else {
60            paren = None
61        }
62
63        self.buffer.ptok = ptok - 1;
64        match c.as_option() {
65            Some(b'Q') => {
66                self.strterm = self.new_strterm(str_dquote, term, paren, None);
67                Self::tSTRING_BEG
68            }
69            Some(b'q') => {
70                self.strterm = self.new_strterm(str_squote, term, paren, None);
71                Self::tSTRING_BEG
72            }
73            Some(b'W') => {
74                self.strterm = self.new_strterm(str_dword, term, paren, None);
75                Self::tWORDS_BEG
76            }
77            Some(b'w') => {
78                self.strterm = self.new_strterm(str_sword, term, paren, None);
79                Self::tQWORDS_BEG
80            }
81            Some(b'I') => {
82                self.strterm = self.new_strterm(str_dword, term, paren, None);
83                Self::tSYMBOLS_BEG
84            }
85            Some(b'i') => {
86                self.strterm = self.new_strterm(str_sword, term, paren, None);
87                Self::tQSYMBOLS_BEG
88            }
89            Some(b'x') => {
90                self.strterm = self.new_strterm(str_xquote, term, paren, None);
91                Self::tXSTRING_BEG
92            }
93            Some(b'r') => {
94                self.strterm = self.new_strterm(str_regexp, term, paren, None);
95                Self::tREGEXP_BEG
96            }
97            Some(b's') => {
98                self.strterm = self.new_strterm(str_ssym, term, paren, None);
99                self.lex_state.set(EXPR_FNAME | EXPR_FITEM);
100                Self::tSYMBEG
101            }
102            _ => {
103                self.yyerror1(
104                    DiagnosticMessage::UnknownTypeOfPercentString {},
105                    self.current_loc().adjust_end(-1),
106                );
107                Self::END_OF_INPUT
108            }
109        }
110    }
111
112    fn percent_unterminated(&mut self) -> i32 {
113        self.compile_error(
114            DiagnosticMessage::UnterminatedQuotedString {},
115            self.current_loc(),
116        );
117        Self::END_OF_INPUT
118    }
119
120    pub(crate) fn parse_percent(&mut self, space_seen: bool, last_state: LexState) -> i32 {
121        let mut c: MaybeByte;
122        let ptok = self.buffer.pcur;
123
124        if self.lex_state.is_beg() {
125            c = self.nextc();
126            return self.percent_quotation(&mut c, ptok);
127        }
128
129        c = self.nextc();
130        if c == b'=' {
131            self.set_yylval_id("%=");
132            self.lex_state.set(EXPR_BEG);
133            return Self::tOP_ASGN;
134        }
135        if self.lex_state.is_spacearg(c, space_seen)
136            || (self.lex_state.is_some(EXPR_FITEM) && c == b's')
137        {
138            return self.percent_quotation(&mut c, ptok);
139        }
140        self.lex_state.set(if self.lex_state.is_after_operator() {
141            EXPR_ARG
142        } else {
143            EXPR_BEG
144        });
145        self.buffer.pushback(c);
146        self.warn_balanced(
147            Self::tPERCENT,
148            "%%",
149            "string literal",
150            c,
151            space_seen,
152            last_state,
153        )
154    }
155}