Add lexing of escaped characters, add parsing of characters
This commit is contained in:
parent
e220900ac3
commit
9b9398ac26
@ -32,6 +32,7 @@ pub enum TypeKind {
|
||||
F80,
|
||||
F128PPC,
|
||||
Str,
|
||||
Char,
|
||||
Array(Box<TypeKind>, u64),
|
||||
Custom(String),
|
||||
Borrow(Box<TypeKind>, bool),
|
||||
@ -44,7 +45,7 @@ pub enum Literal {
|
||||
Decimal(f64),
|
||||
Bool(bool),
|
||||
String(String),
|
||||
Char(String),
|
||||
Char(char),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -61,6 +61,7 @@ impl Parse for Type {
|
||||
"f128" => TypeKind::F128,
|
||||
"f128ppc" => TypeKind::F128PPC,
|
||||
"str" => TypeKind::Str,
|
||||
"char" => TypeKind::Char,
|
||||
_ => TypeKind::Custom(ident),
|
||||
}
|
||||
} else {
|
||||
@ -177,6 +178,20 @@ impl Parse for PrimaryExpression {
|
||||
stream.get_range().unwrap(),
|
||||
)
|
||||
}
|
||||
Token::CharLit(v) => {
|
||||
stream.next(); // Consume
|
||||
let chars = v.as_bytes();
|
||||
if chars.len() == 0 {
|
||||
stream.expected_err("char to not be empty")?;
|
||||
} else if chars.len() > 0 {
|
||||
stream.expected_err("char to only have one char inside it")?;
|
||||
}
|
||||
|
||||
Expression(
|
||||
Kind::Literal(Literal::Char(v.chars().next().unwrap())),
|
||||
stream.get_range().unwrap(),
|
||||
)
|
||||
}
|
||||
Token::True => {
|
||||
stream.next(); // Consume
|
||||
Expression(
|
||||
|
@ -289,7 +289,7 @@ impl ast::Literal {
|
||||
ast::Literal::Bool(v) => mir::Literal::Bool(*v),
|
||||
ast::Literal::String(val) => mir::Literal::String(val.clone()),
|
||||
ast::Literal::Decimal(v) => mir::Literal::Vague(mir::VagueLiteral::Decimal(*v)),
|
||||
ast::Literal::Char(inner) => mir::Literal::Char(inner.chars().next().unwrap()),
|
||||
ast::Literal::Char(inner) => mir::Literal::Char(*inner),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -326,6 +326,7 @@ impl From<ast::TypeKind> for mir::TypeKind {
|
||||
ast::TypeKind::F80 => mir::TypeKind::F80,
|
||||
ast::TypeKind::F128 => mir::TypeKind::F128,
|
||||
ast::TypeKind::F128PPC => mir::TypeKind::F128PPC,
|
||||
ast::TypeKind::Char => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -250,16 +250,21 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Error
|
||||
}
|
||||
'\"' | '\'' => {
|
||||
let mut value = String::new();
|
||||
let mut ignore_next = false;
|
||||
let mut escape_next = false;
|
||||
while cursor.first().is_some()
|
||||
&& (cursor.first() != Some(*character) || ignore_next)
|
||||
&& (cursor.first() != Some(*character) || escape_next)
|
||||
{
|
||||
if cursor.first() == Some('\\') && !ignore_next {
|
||||
cursor.next(); // Consume backslash anjd always add next character
|
||||
ignore_next = true;
|
||||
if cursor.first() == Some('\\') && !escape_next {
|
||||
cursor.next(); // Consume backslash and always add next character
|
||||
escape_next = true;
|
||||
} else {
|
||||
ignore_next = false;
|
||||
value += &cursor.next().unwrap().to_string();
|
||||
let c = &cursor.next().unwrap();
|
||||
if escape_next {
|
||||
value += &escape_char(&c).to_string();
|
||||
} else {
|
||||
value += &c.to_string();
|
||||
}
|
||||
escape_next = false;
|
||||
}
|
||||
}
|
||||
if cursor.first() == Some(*character) {
|
||||
@ -268,7 +273,7 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Error
|
||||
return Err(Error::MissingQuotation(position));
|
||||
}
|
||||
match character {
|
||||
'\'' => Token::StringLit(value),
|
||||
'\'' => Token::CharLit(value),
|
||||
'\"' => Token::StringLit(value),
|
||||
_ => unsafe { unreachable_unchecked() },
|
||||
}
|
||||
@ -356,6 +361,15 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Error
|
||||
Ok(tokens)
|
||||
}
|
||||
|
||||
fn escape_char(c: &char) -> char {
|
||||
match c {
|
||||
't' => '\t',
|
||||
'n' => '\n',
|
||||
'r' => '\r',
|
||||
_ => *c,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum Error {
|
||||
#[error("Invalid token '{}' ", .0)]
|
||||
|
Loading…
Reference in New Issue
Block a user