feat(ir, parser): Support if/while/break/logical expr/cmp in parser and ir generator
This commit is contained in:
+36
-16
@@ -17,7 +17,7 @@ pub struct Lexer {
|
||||
|
||||
const WHITESPACE_CHARS: &[char] = &[' ', '\t', '\n', '\r'];
|
||||
const DELIMITER_CHARS: &[char] = &[
|
||||
'+', '-', '*', '/', '%', '=', '!', '<', '>', '(', ')', ',', ';'
|
||||
'+', '-', '*', '/', '%', '=', '!', '<', '>', '(', ')', ',', ';', '{', '|', '&'
|
||||
];
|
||||
struct Cursor {
|
||||
chars: Vec<char>,
|
||||
@@ -185,22 +185,10 @@ fn parse_litint(
|
||||
) -> Result<TokenValue, LexParseError> {
|
||||
let mut c1 = str_iter.peek().ok_or(LexParseError::NotMatched)?;
|
||||
// c1 is the peek value from here
|
||||
let mut sign_base: i64 = 1;
|
||||
let mut base: i64 = 10;
|
||||
if !(c1.is_ascii_digit() || c1 == '-') {
|
||||
if !(c1.is_ascii_digit()) {
|
||||
return Err(LexParseError::NotMatched);
|
||||
}
|
||||
if c1 == '-' {
|
||||
sign_base = -1;
|
||||
str_iter.advance(1);
|
||||
c1 = str_iter.peek().ok_or(LexParseError::NotMatched)?;
|
||||
if !c1.is_ascii_digit() {
|
||||
// only a minus sign, not a number
|
||||
// back one so cursor still points to the minus sign
|
||||
str_iter.back(1);
|
||||
return Err(LexParseError::NotMatched);
|
||||
}
|
||||
}
|
||||
let mut number = 0i64;
|
||||
let mut has_digits = false;
|
||||
if c1 == '0' {
|
||||
@@ -248,7 +236,6 @@ fn parse_litint(
|
||||
// No valid digits found, add a diagnostic
|
||||
return Err(LexParseError::InvalidInMatch(LexingError::InvalidIntLiteral));
|
||||
}
|
||||
number *= sign_base;
|
||||
Ok(TokenValue::IntLit(number))
|
||||
}
|
||||
|
||||
@@ -293,6 +280,7 @@ fn parse_puncuation(
|
||||
if let Some('=') = str_iter.peek() {
|
||||
TokenValue::NotEqual
|
||||
} else {
|
||||
str_iter.back(1);
|
||||
TokenValue::Not
|
||||
}
|
||||
},
|
||||
@@ -301,7 +289,24 @@ fn parse_puncuation(
|
||||
|
||||
',' => TokenValue::Comma,
|
||||
';' => TokenValue::Semicolon,
|
||||
|
||||
'|' => {
|
||||
str_iter.advance(1);
|
||||
if let Some('|') = str_iter.peek() {
|
||||
TokenValue::Or
|
||||
} else {
|
||||
// unrecognized token starting with '|'
|
||||
return Err(LexParseError::InvalidInMatch(LexingError::UnrecognizedToken("|".to_string())));
|
||||
}
|
||||
},
|
||||
'&' => {
|
||||
str_iter.advance(1);
|
||||
if let Some('&') = str_iter.peek() {
|
||||
TokenValue::And
|
||||
} else {
|
||||
// unrecognized token starting with '&'
|
||||
return Err(LexParseError::InvalidInMatch(LexingError::UnrecognizedToken("&".to_string())));
|
||||
}
|
||||
},
|
||||
_ => return Err(LexParseError::NotMatched),
|
||||
};
|
||||
str_iter.advance(1);
|
||||
@@ -330,6 +335,21 @@ fn parse_ident(
|
||||
if name.eq("return") {
|
||||
return Ok(TokenValue::Return);
|
||||
}
|
||||
if name.eq("if") {
|
||||
return Ok(TokenValue::If);
|
||||
}
|
||||
if name.eq("else") {
|
||||
return Ok(TokenValue::Else);
|
||||
}
|
||||
if name.eq("while") {
|
||||
return Ok(TokenValue::While);
|
||||
}
|
||||
if name.eq("break") {
|
||||
return Ok(TokenValue::Break);
|
||||
}
|
||||
if name.eq("continue") {
|
||||
return Ok(TokenValue::Continue);
|
||||
}
|
||||
if let Some(type_ident) = TypeIdent::from_str(&name).ok() {
|
||||
return Ok(TokenValue::TypeIdent(type_ident));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user