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:
parent
56fffd6911
commit
48f47671cd
29
src/main.rs
29
src/main.rs
|
@ -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));";
|
||||
|
|
Loading…
Reference in a new issue