lib_ruby_parser/lexer/
parse_percent.rs1use 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}