leo_input/values/
char_types.rs1use crate::{
18 ast::{span_into_string, Rule},
19 errors::InputParserError,
20};
21
22use pest::Span;
23use pest_ast::FromPest;
24
25#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
26#[pest_ast(rule(Rule::basic_char))]
27pub struct BasicChar<'ast> {
28 #[pest_ast(outer(with(span_into_string)))]
29 pub value: String,
30 #[pest_ast(outer())]
31 pub span: Span<'ast>,
32}
33
34#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
35#[pest_ast(rule(Rule::escaped_char))]
36pub struct EscapedChar<'ast> {
37 #[pest_ast(outer(with(span_into_string)))]
38 pub value: String,
39 #[pest_ast(outer())]
40 pub span: Span<'ast>,
41}
42
43#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
44#[pest_ast(rule(Rule::hex_char))]
45pub struct HexChar<'ast> {
46 #[pest_ast(outer(with(span_into_string)))]
47 pub value: String,
48 #[pest_ast(outer())]
49 pub span: Span<'ast>,
50}
51
52#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
53#[pest_ast(rule(Rule::unicode_char))]
54pub struct UnicodeChar<'ast> {
55 #[pest_ast(outer(with(span_into_string)))]
56 pub value: String,
57 #[pest_ast(outer())]
58 pub span: Span<'ast>,
59}
60
61#[derive(Clone, Debug, FromPest, PartialEq, Eq)]
62#[pest_ast(rule(Rule::char_types))]
63pub enum CharTypes<'ast> {
64 Basic(BasicChar<'ast>),
65 Escaped(EscapedChar<'ast>),
66 Hex(HexChar<'ast>),
67 Unicode(UnicodeChar<'ast>),
68}
69
70impl<'ast> CharTypes<'ast> {
71 pub fn span(&self) -> &Span<'ast> {
72 match self {
73 CharTypes::Basic(value) => &value.span,
74 CharTypes::Escaped(value) => &value.span,
75 CharTypes::Hex(value) => &value.span,
76 CharTypes::Unicode(value) => &value.span,
77 }
78 }
79}
80
81#[derive(Clone, Debug, PartialEq, Eq)]
82pub enum Char {
83 Scalar(char),
84 NonScalar(u32),
85}
86
87impl<'ast> CharTypes<'ast> {
88 pub fn inner(self) -> Result<Char, InputParserError> {
89 match self {
90 Self::Basic(character) => {
91 if let Some(character) = character.value.chars().next() {
92 return Ok(Char::Scalar(character));
93 }
94
95 Err(InputParserError::invalid_char(character.value, &character.span))
96 }
97 Self::Escaped(character) => {
98 if let Some(inner) = character.value.chars().nth(1) {
99 return match inner {
100 '0' => Ok(Char::Scalar(0 as char)),
101 't' => Ok(Char::Scalar(9 as char)),
102 'n' => Ok(Char::Scalar(10 as char)),
103 'r' => Ok(Char::Scalar(13 as char)),
104 '\"' => Ok(Char::Scalar(34 as char)),
105 '\'' => Ok(Char::Scalar(39 as char)),
106 '\\' => Ok(Char::Scalar(92 as char)),
107 _ => Err(InputParserError::invalid_char(character.value, &character.span)),
108 };
109 }
110
111 Err(InputParserError::invalid_char(character.value, &character.span))
112 }
113 Self::Hex(character) => {
114 let hex_string_number = character.value[2..character.value.len()].to_string();
115 if let Ok(number) = u8::from_str_radix(&hex_string_number, 16) {
116 if number <= 127 {
117 return Ok(Char::Scalar(number as char));
118 }
119 }
120
121 Err(InputParserError::invalid_char(character.value, &character.span))
122 }
123 Self::Unicode(character) => {
124 let unicode_string_number = character.value[3..=character.value.len() - 2].to_string();
125 if let Ok(hex) = u32::from_str_radix(&unicode_string_number, 16) {
126 if let Some(unicode) = std::char::from_u32(hex) {
127 return Ok(Char::Scalar(unicode));
128 } else if hex <= 0x10FFFF {
129 return Ok(Char::NonScalar(hex));
130 }
131 }
132
133 Err(InputParserError::invalid_char(character.value, &character.span))
134 }
135 }
136 }
137}