Add minus operator

Adds "minus" operator, both as a unary negation and a binary
subtraction. Refactors Parser::bump to actually return the next
token, which is slightly more useful for us. Also changes how
Token::len is implemented, and now we return 1 for all tokens
that are not listed explicitly.
This commit is contained in:
Aodhnait Étaín 2021-05-27 17:40:36 +00:00
parent 56fffd6911
commit 48f47671cd
Signed by: aodhneine
GPG key ID: ECE91C73AD45F245

View file

@ -7,6 +7,7 @@ enum Token<'a> {
IntegerLiteral(&'a str),
Plus,
Star,
Minus,
Semicolon,
LeftParen,
RightParen,
@ -18,13 +19,14 @@ impl Token<'_> {
pub fn len(&self) -> usize {
return match self {
Token::IntegerLiteral(s) => s.len(),
Token::Plus | Token::Semicolon | Token::LeftParen | Token::RightParen | Token::Star => 1,
// Token::Plus, Token::Minus, Token::Semicolon, Token::LeftParen, Token::RightParen, Token::Star
_ => 1,
};
}
pub fn precedence(&self) -> usize {
return match self {
Token::Plus => 1,
Token::Plus | Token::Minus => 1,
Token::Star => 2,
_ => LOWEST_PRECEDENCE,
}
@ -64,6 +66,7 @@ impl<'a> Source<'a> {
let token = match chars.next()? {
'+' => Token::Plus,
'-' => Token::Minus,
'*' => Token::Star,
';' => Token::Semicolon,
'(' => Token::LeftParen,
@ -151,14 +154,12 @@ impl<'a> Parser<'a> {
return self.source.peek();
}
// Just a wrapper around self.next which disables unused_must_use lint, so it
// can be more useful in some cases (such as when we already know what's the
// following token, for example from the previous call to self.peek, but we
// want to advance the parser now, and don't care about the result).
#[allow(unused_must_use)]
// A wrapper around next function, which WILL panic if there is no token left
// in the source. The intent is to ONLY use it when it is KNOWN that we can
// safely take a token without causing a panic, such as when we peek a token.
#[inline(always)]
fn bump(&mut self) {
self.next();
fn bump(&mut self) -> Token<'a> {
return self.next().unwrap();
}
fn parse_primary_expr(&mut self) -> Option<Expr<'a>> {
@ -180,8 +181,8 @@ impl<'a> Parser<'a> {
fn parse_unary_expr(&mut self) -> Option<Expr<'a>> {
return match self.peek()? {
token @ Token::Plus => {
self.bump();
Token::Plus | Token::Minus => {
let token = self.bump();
let expr = self.parse_unary_expr()?;
Some(Expr::Unary(token, box expr))
},
@ -189,6 +190,9 @@ impl<'a> Parser<'a> {
};
}
// expr = unary_expr [ op expr ]
// unary_expr = '+' unary_expr | primary_expr
// primary_expr = literal | '(' expr ')'
pub fn parse_expr(&mut self, min_precedence: usize) -> Option<Expr<'a>> {
let mut lhs = self.parse_unary_expr()?;
@ -211,7 +215,8 @@ impl<'a> Parser<'a> {
}
fn main() {
let inline_source = "3 + +5 * +7;";
let inline_source = "3 + 2 - -5;";
// let inline_source = "3 + +5 * +7;";
// let inline_source = "3 + 5 * 7;";
// let inline_source = "(3 + 5) + 7;";
// let inline_source = "3 + (5 + (7 + 11));";