|
2 | 2 |
|
3 | 3 | use crate::ast::{self, LitKind, MetaItemLit, StrStyle}; |
4 | 4 | use crate::token::{self, Token}; |
5 | | -use rustc_lexer::unescape::{byte_from_char, unescape_byte, unescape_char, unescape_literal, Mode}; |
| 5 | +use rustc_lexer::unescape::{ |
| 6 | + byte_from_char, unescape_byte, unescape_c_string, unescape_char, unescape_literal, CStrUnit, |
| 7 | + Mode, |
| 8 | +}; |
6 | 9 | use rustc_span::symbol::{kw, sym, Symbol}; |
7 | 10 | use rustc_span::Span; |
8 | 11 | use std::{ascii, fmt, str}; |
@@ -158,6 +161,52 @@ impl LitKind { |
158 | 161 |
|
159 | 162 | LitKind::ByteStr(bytes.into(), StrStyle::Raw(n)) |
160 | 163 | } |
| 164 | + token::CStr => { |
| 165 | + let s = symbol.as_str(); |
| 166 | + let mut buf = Vec::with_capacity(s.len()); |
| 167 | + let mut error = Ok(()); |
| 168 | + unescape_c_string(s, Mode::CStr, &mut |span, c| match c { |
| 169 | + Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) => { |
| 170 | + error = Err(LitError::NulInCStr(span)); |
| 171 | + } |
| 172 | + Ok(CStrUnit::Byte(b)) => buf.push(b), |
| 173 | + Ok(CStrUnit::Char(c)) if c.len_utf8() == 1 => buf.push(c as u8), |
| 174 | + Ok(CStrUnit::Char(c)) => { |
| 175 | + buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes()) |
| 176 | + } |
| 177 | + Err(err) => { |
| 178 | + if err.is_fatal() { |
| 179 | + error = Err(LitError::LexerError); |
| 180 | + } |
| 181 | + } |
| 182 | + }); |
| 183 | + error?; |
| 184 | + buf.push(b'\0'); |
| 185 | + LitKind::CStr(buf.into(), StrStyle::Cooked) |
| 186 | + } |
| 187 | + token::CStrRaw(n) => { |
| 188 | + let s = symbol.as_str(); |
| 189 | + let mut buf = Vec::with_capacity(s.len()); |
| 190 | + let mut error = Ok(()); |
| 191 | + unescape_c_string(s, Mode::RawCStr, &mut |span, c| match c { |
| 192 | + Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) => { |
| 193 | + error = Err(LitError::NulInCStr(span)); |
| 194 | + } |
| 195 | + Ok(CStrUnit::Byte(b)) => buf.push(b), |
| 196 | + Ok(CStrUnit::Char(c)) if c.len_utf8() == 1 => buf.push(c as u8), |
| 197 | + Ok(CStrUnit::Char(c)) => { |
| 198 | + buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes()) |
| 199 | + } |
| 200 | + Err(err) => { |
| 201 | + if err.is_fatal() { |
| 202 | + error = Err(LitError::LexerError); |
| 203 | + } |
| 204 | + } |
| 205 | + }); |
| 206 | + error?; |
| 207 | + buf.push(b'\0'); |
| 208 | + LitKind::CStr(buf.into(), StrStyle::Raw(n)) |
| 209 | + } |
161 | 210 | token::Err => LitKind::Err, |
162 | 211 | }) |
163 | 212 | } |
@@ -191,6 +240,8 @@ impl fmt::Display for LitKind { |
191 | 240 | string = symbol |
192 | 241 | )?; |
193 | 242 | } |
| 243 | + // TODO need to reescape |
| 244 | + LitKind::CStr(..) => todo!(), |
194 | 245 | LitKind::Int(n, ty) => { |
195 | 246 | write!(f, "{n}")?; |
196 | 247 | match ty { |
@@ -237,6 +288,8 @@ impl MetaItemLit { |
237 | 288 | LitKind::Str(_, ast::StrStyle::Raw(n)) => token::StrRaw(n), |
238 | 289 | LitKind::ByteStr(_, ast::StrStyle::Cooked) => token::ByteStr, |
239 | 290 | LitKind::ByteStr(_, ast::StrStyle::Raw(n)) => token::ByteStrRaw(n), |
| 291 | + LitKind::CStr(_, ast::StrStyle::Cooked) => token::CStr, |
| 292 | + LitKind::CStr(_, ast::StrStyle::Raw(n)) => token::CStrRaw(n), |
240 | 293 | LitKind::Byte(_) => token::Byte, |
241 | 294 | LitKind::Char(_) => token::Char, |
242 | 295 | LitKind::Int(..) => token::Integer, |
|
0 commit comments