lib_ruby_parser/lexer/
parse_qmark.rs

1use crate::lex_states::*;
2use crate::lexer::*;
3use crate::maybe_byte::*;
4use crate::source::buffer::*;
5use crate::DiagnosticMessage;
6
7impl Lexer {
8    fn parse_qmark_ternary(&mut self, c: MaybeByte) -> Result<i32, ()> {
9        self.buffer.pushback(c);
10        self.lex_state.set(EXPR_VALUE);
11        Ok(Self::tEH)
12    }
13
14    pub(crate) fn parse_qmark(&mut self, space_seen: bool) -> Result<i32, ()> {
15        if self.lex_state.is_end() {
16            self.lex_state.set(EXPR_VALUE);
17            return Ok(Self::tEH);
18        }
19        let mut c = self.nextc();
20        if c.is_eof() {
21            self.compile_error(
22                DiagnosticMessage::IncompleteCharacterSyntax {},
23                self.current_loc(),
24            );
25            return Ok(Self::END_OF_INPUT);
26        }
27        if c.is_space() {
28            if !self.lex_state.is_arg() {
29                if let Some(c2) = c.escaped_control_code() {
30                    self.warn_space_char(c2, "?");
31                }
32            }
33            return self.parse_qmark_ternary(c);
34        }
35        self.newtok();
36
37        if !self.is_ascii() {
38            if self.tokadd_mbchar(c).is_err() {
39                return Ok(Self::END_OF_INPUT);
40            }
41        } else if (c.is_alnum() || c == b'_')
42            && self.buffer.pcur < self.buffer.pend
43            && self.buffer.is_identchar(self.buffer.pcur, self.buffer.pend)
44        {
45            if space_seen {
46                let start = self.buffer.pcur - 1;
47                let mut ptr = start;
48                loop {
49                    let n = self.multibyte_char_len(ptr);
50                    match n {
51                        Some(n) => ptr += n,
52                        None => return Ok(Self::END_OF_INPUT),
53                    }
54
55                    if !(ptr < self.buffer.pend && self.buffer.is_identchar(ptr, self.buffer.pend))
56                    {
57                        break;
58                    }
59                }
60                self.warn(
61                    DiagnosticMessage::AmbiguousTernaryOperator {
62                        condition: String::from_utf8_lossy(
63                            self.buffer.substr_at(start, ptr).unwrap(),
64                        )
65                        .into_owned(),
66                    },
67                    self.loc(start - 1, start),
68                )
69            }
70            return self.parse_qmark_ternary(c);
71        } else if c == b'\\' {
72            if self.buffer.peek(b'u') {
73                self.nextc();
74                self.tokadd_utf8(None, 0, 0);
75            } else if !self.buffer.is_eol() && !self.char_at(self.buffer.pcur).is_ascii() {
76                c = self.char_at(self.buffer.pcur);
77                self.nextc();
78                if self.tokadd_mbchar(c).is_err() {
79                    return Ok(Self::END_OF_INPUT);
80                }
81            } else {
82                let byte = self.read_escape(0);
83                self.tokadd(byte);
84            }
85        } else {
86            self.tokadd(c);
87        }
88        self.tokfix();
89        let yylval = self.tokenbuf.take();
90        self.set_yylval_str(&yylval);
91        self.lex_state.set(EXPR_END);
92        Ok(Self::tCHAR)
93    }
94}