MCLang, now with testing!
This commit is contained in:
@@ -33,8 +33,8 @@ impl Token {
|
||||
}
|
||||
|
||||
|
||||
pub fn tokenise(s: &str) -> anyhow::Result<Vec<Token>> {
|
||||
let mut loc = Loc::default();
|
||||
pub fn tokenise(s: &str, file_p: &str) -> anyhow::Result<Vec<Token>> {
|
||||
let mut loc = Loc::new(file_p, 1, 1);
|
||||
let mut tokens = Vec::new();
|
||||
let chars: Vec<_> = s.chars().collect();
|
||||
let mut chars = chars.iter().peekable();
|
||||
@@ -70,44 +70,52 @@ pub fn tokenise(s: &str) -> anyhow::Result<Vec<Token>> {
|
||||
// tokens.push(Token::new(TokenType::Comment(Comment::Line(buf.clone())), &loc));
|
||||
}
|
||||
'\n' => loc.inc_line(),
|
||||
'"' | '\'' |
|
||||
'c' if *c != 'c' || chars.peek() == Some(&&'"') => {
|
||||
let str_typ = *c;
|
||||
let mut sc = *c;
|
||||
if *c == 'c' {
|
||||
sc = '"';
|
||||
chars.peek();
|
||||
}
|
||||
'"' => {
|
||||
let mut last = '\0';
|
||||
let mut buf = String::new();
|
||||
while let Some(c) = chars.next_if(|v| **v != '\n') {
|
||||
loc.inc_col();
|
||||
if *c == sc && last != '\\' {
|
||||
if *c == '"' && last != '\\' {
|
||||
break;
|
||||
}
|
||||
buf.push(*c);
|
||||
last = *c;
|
||||
}
|
||||
|
||||
match str_typ {
|
||||
'"' => {
|
||||
tokens.push(Token::new(TokenType::string(&buf, false), &loc));
|
||||
tokens.push(Token::new(TokenType::string(&buf, false), &loc));
|
||||
}
|
||||
'\'' => {
|
||||
let mut last = '\0';
|
||||
let mut buf = String::new();
|
||||
while let Some(c) = chars.next_if(|v| **v != '\n') {
|
||||
loc.inc_col();
|
||||
if *c == '\'' && last != '\\' {
|
||||
break;
|
||||
}
|
||||
'c' => {
|
||||
tokens.push(Token::new(TokenType::string(&buf, true), &loc));
|
||||
}
|
||||
'\'' => {
|
||||
let buf = buf
|
||||
.replace("\\n", "\n")
|
||||
.replace("\\r", "\r");
|
||||
if buf.len() > 1 {
|
||||
lerror!(&loc, "Chars can only have 1 byte");
|
||||
bail!("")
|
||||
}
|
||||
tokens.push(Token::new(TokenType::char(buf.chars().nth(0).unwrap()), &loc));
|
||||
}
|
||||
_ => unreachable!()
|
||||
buf.push(*c);
|
||||
last = *c;
|
||||
}
|
||||
let buf = buf
|
||||
.replace("\\n", "\n")
|
||||
.replace("\\r", "\r");
|
||||
if buf.len() > 1 {
|
||||
lerror!(&loc, "Chars can only have 1 byte");
|
||||
bail!("")
|
||||
}
|
||||
tokens.push(Token::new(TokenType::char(buf.chars().nth(0).unwrap()), &loc));
|
||||
}
|
||||
'c' if chars.peek() == Some(&&'"') => {
|
||||
chars.next();
|
||||
let mut last = '\0';
|
||||
let mut buf = String::new();
|
||||
while let Some(c) = chars.next_if(|v| **v != '\n') {
|
||||
loc.inc_col();
|
||||
if *c == '"' && last != '\\' {
|
||||
break;
|
||||
}
|
||||
buf.push(*c);
|
||||
last = *c;
|
||||
}
|
||||
tokens.push(Token::new(TokenType::string(&buf, true), &loc));
|
||||
}
|
||||
'a'..='z' | 'A'..='Z' | '_' => {
|
||||
let mut buf = String::new();
|
||||
@@ -139,12 +147,13 @@ pub fn tokenise(s: &str) -> anyhow::Result<Vec<Token>> {
|
||||
'o' => radix = 8,
|
||||
_ => (),
|
||||
}
|
||||
|
||||
},
|
||||
None => {
|
||||
tokens.push(Token::new(TokenType::number(parse(&buf).unwrap(), radix, signed), &loc));
|
||||
}
|
||||
}
|
||||
while let Some(c) = chars.next_if(|v| matches!(**v, '0'..='9' | '.' | 'a'..='f' | 'A'..='F')) {
|
||||
while let Some(c) = chars.next_if(|v| matches!(**v, '0'..='9' | '.' | 'a'..='f' | 'A'..='F' | 'x' | 'o')) {
|
||||
loc.inc_col();
|
||||
buf.push(*c);
|
||||
}
|
||||
@@ -178,7 +187,7 @@ pub fn tokenise(s: &str) -> anyhow::Result<Vec<Token>> {
|
||||
}
|
||||
tokens.push(Token::new(TokenType::number(parse(&buf).unwrap(), radix, signed), &loc));
|
||||
}
|
||||
16 => {
|
||||
16 => {
|
||||
if buf.strip_prefix("0x").expect("Unreachable")
|
||||
.chars().filter(|v| !matches!(v, '0'..='9' | 'a'..='f' | 'A'..='F')).collect::<Vec<_>>().len() > 0 {
|
||||
lerror!(&loc, "Invalid character in hex number");
|
||||
@@ -268,8 +277,8 @@ lazy_static::lazy_static!(
|
||||
("|", TokenType::Punct(Punctuation::Or)),
|
||||
(">", TokenType::Punct(Punctuation::Gt)),
|
||||
("<", TokenType::Punct(Punctuation::Lt)),
|
||||
(">=", TokenType::Punct(Punctuation::Ge)),
|
||||
("<=", TokenType::Punct(Punctuation::Le)),
|
||||
(">=", TokenType::Punct(Punctuation::Ge)),
|
||||
("<=", TokenType::Punct(Punctuation::Le)),
|
||||
("^", TokenType::Punct(Punctuation::Xor)),
|
||||
("+=", TokenType::Punct(Punctuation::AddEq)),
|
||||
("-=", TokenType::Punct(Punctuation::SubEq)),
|
||||
|
||||
Reference in New Issue
Block a user