Lower values of char and byte literals

This commit is contained in:
Laurențiu Nicola 2022-05-05 08:10:07 +03:00
parent 0218aeba7a
commit 9856144b0b
8 changed files with 178 additions and 11 deletions

View File

@ -983,9 +983,11 @@ fn from(ast_lit_kind: ast::LiteralKind) -> Self {
let text = s.value().map(Box::from).unwrap_or_else(Default::default); let text = s.value().map(Box::from).unwrap_or_else(Default::default);
Literal::String(text) Literal::String(text)
} }
LiteralKind::Byte => Literal::Uint(Default::default(), Some(BuiltinUint::U8)), LiteralKind::Byte(b) => {
Literal::Uint(b.value().unwrap_or_default() as u128, Some(BuiltinUint::U8))
}
LiteralKind::Char(c) => Literal::Char(c.value().unwrap_or_default()),
LiteralKind::Bool(val) => Literal::Bool(val), LiteralKind::Bool(val) => Literal::Bool(val),
LiteralKind::Char => Literal::Char(Default::default()),
} }
} }
} }

View File

@ -3507,6 +3507,94 @@ fn hover_const_eval() {
--- ---
This is a doc
"#]],
);
// show char literal
check(
r#"
/// This is a doc
const FOO$0: char = 'a';
"#,
expect![[r#"
*FOO*
```rust
test
```
```rust
const FOO: char = 'a'
```
---
This is a doc
"#]],
);
// show escaped char literal
check(
r#"
/// This is a doc
const FOO$0: char = '\x61';
"#,
expect![[r#"
*FOO*
```rust
test
```
```rust
const FOO: char = 'a'
```
---
This is a doc
"#]],
);
// show byte literal
check(
r#"
/// This is a doc
const FOO$0: u8 = b'a';
"#,
expect![[r#"
*FOO*
```rust
test
```
```rust
const FOO: u8 = 97 (0x61)
```
---
This is a doc
"#]],
);
// show escaped byte literal
check(
r#"
/// This is a doc
const FOO$0: u8 = b'\x61';
"#,
expect![[r#"
*FOO*
```rust
test
```
```rust
const FOO: u8 = 97 (0x61)
```
---
This is a doc This is a doc
"#]], "#]],
); );

View File

@ -8,7 +8,6 @@
//! //!
//! The `cli` submodule implements some batch-processing analysis, primarily as //! The `cli` submodule implements some batch-processing analysis, primarily as
//! a debugging aid. //! a debugging aid.
#![recursion_limit = "512"]
pub mod cli; pub mod cli;

View File

@ -283,8 +283,8 @@ pub enum LiteralKind {
ByteString(ast::ByteString), ByteString(ast::ByteString),
IntNumber(ast::IntNumber), IntNumber(ast::IntNumber),
FloatNumber(ast::FloatNumber), FloatNumber(ast::FloatNumber),
Char, Char(ast::Char),
Byte, Byte(ast::Byte),
Bool(bool), Bool(bool),
} }
@ -312,12 +312,16 @@ pub fn kind(&self) -> LiteralKind {
if let Some(t) = ast::ByteString::cast(token.clone()) { if let Some(t) = ast::ByteString::cast(token.clone()) {
return LiteralKind::ByteString(t); return LiteralKind::ByteString(t);
} }
if let Some(t) = ast::Char::cast(token.clone()) {
return LiteralKind::Char(t);
}
if let Some(t) = ast::Byte::cast(token.clone()) {
return LiteralKind::Byte(t);
}
match token.kind() { match token.kind() {
T![true] => LiteralKind::Bool(true), T![true] => LiteralKind::Bool(true),
T![false] => LiteralKind::Bool(false), T![false] => LiteralKind::Bool(false),
CHAR => LiteralKind::Char,
BYTE => LiteralKind::Byte,
_ => unreachable!(), _ => unreachable!(),
} }
} }

View File

@ -132,6 +132,48 @@ fn cast(syntax: SyntaxToken) -> Option<Self> {
fn syntax(&self) -> &SyntaxToken { &self.syntax } fn syntax(&self) -> &SyntaxToken { &self.syntax }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Char {
pub(crate) syntax: SyntaxToken,
}
impl std::fmt::Display for Char {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&self.syntax, f)
}
}
impl AstToken for Char {
fn can_cast(kind: SyntaxKind) -> bool { kind == CHAR }
fn cast(syntax: SyntaxToken) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxToken { &self.syntax }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Byte {
pub(crate) syntax: SyntaxToken,
}
impl std::fmt::Display for Byte {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&self.syntax, f)
}
}
impl AstToken for Byte {
fn can_cast(kind: SyntaxKind) -> bool { kind == BYTE }
fn cast(syntax: SyntaxToken) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxToken { &self.syntax }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Ident { pub struct Ident {
pub(crate) syntax: SyntaxToken, pub(crate) syntax: SyntaxToken,

View File

@ -2,7 +2,7 @@
use std::borrow::Cow; use std::borrow::Cow;
use rustc_lexer::unescape::{unescape_literal, Mode}; use rustc_lexer::unescape::{unescape_byte, unescape_char, unescape_literal, Mode};
use crate::{ use crate::{
ast::{self, AstToken}, ast::{self, AstToken},
@ -406,3 +406,35 @@ fn test_string_escape() {
check_string_value(r"C:\\Windows\\System32\\", "C:\\Windows\\System32\\"); check_string_value(r"C:\\Windows\\System32\\", "C:\\Windows\\System32\\");
} }
} }
impl ast::Char {
pub fn value(&self) -> Option<char> {
let mut text = self.text();
if text.starts_with('\'') {
text = &text[1..];
} else {
return None;
}
if text.ends_with('\'') {
text = &text[0..text.len() - 1];
}
unescape_char(text).ok()
}
}
impl ast::Byte {
pub fn value(&self) -> Option<u8> {
let mut text = self.text();
if text.starts_with("b\'") {
text = &text[2..];
} else {
return None;
}
if text.ends_with('\'') {
text = &text[0..text.len() - 1];
}
unescape_byte(text).ok()
}
}

View File

@ -585,7 +585,7 @@ fn ty(&self) -> proc_macro2::Ident {
fn lower(grammar: &Grammar) -> AstSrc { fn lower(grammar: &Grammar) -> AstSrc {
let mut res = AstSrc { let mut res = AstSrc {
tokens: "Whitespace Comment String ByteString IntNumber FloatNumber Ident" tokens: "Whitespace Comment String ByteString IntNumber FloatNumber Char Byte Ident"
.split_ascii_whitespace() .split_ascii_whitespace()
.map(|it| it.to_string()) .map(|it| it.to_string())
.collect::<Vec<_>>(), .collect::<Vec<_>>(),

View File

@ -151,12 +151,12 @@ fn unquote(text: &str, prefix_len: usize, end_delimiter: char) -> Option<&str> {
} }
} }
} }
ast::LiteralKind::Char => { ast::LiteralKind::Char(_) => {
if let Some(Err(e)) = unquote(text, 1, '\'').map(unescape_char) { if let Some(Err(e)) = unquote(text, 1, '\'').map(unescape_char) {
push_err(1, e); push_err(1, e);
} }
} }
ast::LiteralKind::Byte => { ast::LiteralKind::Byte(_) => {
if let Some(Err(e)) = unquote(text, 2, '\'').map(unescape_byte) { if let Some(Err(e)) = unquote(text, 2, '\'').map(unescape_byte) {
push_err(2, e); push_err(2, e);
} }