From 9d074ddd195b52413b609fca78745b916661279c Mon Sep 17 00:00:00 2001 From: mars Date: Tue, 1 Mar 2022 10:06:47 -0700 Subject: [PATCH] Tail expressions, integer literal exprs --- src/lexer.rs | 7 +++-- src/parse.rs | 72 ++++++++++++++++++++++++++++++++-------------------- 2 files changed, 50 insertions(+), 29 deletions(-) diff --git a/src/lexer.rs b/src/lexer.rs index 40c0f34..8c07890 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -57,12 +57,15 @@ pub enum Token { #[regex(r"[a-zA-Z_][a-zA-Z0-9_]*")] Identifier, - #[regex(r"0b_*[01][_01]*")] + #[regex(r"0b_*[01][_'01]*")] BinaryInteger, - #[regex(r"0o_*[0-7][_0-7]*")] + #[regex(r"0o_*[0-7][_'0-7]*")] OctalInteger, + #[regex(r"0x_*[0-9a-fA-F][_'0-9a-fA-F]*")] + HexInteger, + #[regex(r"-?[0-9][_'0-9]*")] DecimalInteger, diff --git a/src/parse.rs b/src/parse.rs index 1b791ed..7275110 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -191,37 +191,45 @@ impl<'a> FnBody<'a> { pub fn build(lexer: &mut Lexer<'a>) -> Self { let mut statements = Vec::new(); - let mut tail = Some(Token::Semicolon); + let mut tail_expr = None; loop { - match tail { - Some(Token::Semicolon) => match lexer.next().unwrap() { - Token::Let => { - let (statement, next) = Statement::build_let(lexer); - statements.push(statement); - tail = Some(next); + let tok = lexer.next().unwrap(); + match tok { + Token::Let => { + let (statement, next) = Statement::build_let(lexer); + statements.push(statement); + match next { + Token::Semicolon => {} + Token::BraceClose => break, + _ => lexer.panic_message("Unexpected token"), } - Token::Var => { - let (statement, next) = Statement::build_var(lexer); - statements.push(statement); - tail = Some(next); + } + Token::Var => { + let (statement, next) = Statement::build_var(lexer); + statements.push(statement); + match next { + Token::Semicolon => {} + Token::BraceClose => break, + _ => lexer.panic_message("Unexpected token"), } - Token::Identifier => { - let var = lexer.slice(); - let (expr, next) = Statement::eat_assign(lexer); - statements.push(Statement::Assign { var, expr }); - tail = Some(next); + } + Token::Identifier => match Expr::build_start(tok, lexer) { + (None, Token::Semicolon | Token::BraceClose) => {} + (Some(expr), Token::Semicolon) => statements.push(Statement::Expr(expr)), + (Some(expr), Token::BraceClose) => { + tail_expr = Some(expr); + break; } - Token::BraceClose => break, - _ => lexer.panic_message("Expected var, let, or assign"), + _ => lexer.panic_message("Unexpected token"), }, - Some(Token::BraceClose) => break, - _ => lexer.panic_message("Unexpected token"), + Token::BraceClose => break, + _ => lexer.panic_message("Expected var, let, or assign"), } } Self { statements, - tail_expr: None, + tail_expr, } } } @@ -243,11 +251,14 @@ pub enum Expr<'a> { } impl<'a> Expr<'a> { - pub fn build(lexer: &mut Lexer<'a>) -> (Option, Token) { - let tok = lexer.next().unwrap(); + pub fn build_start(tok: Token, lexer: &mut Lexer<'a>) -> (Option, Token) { let lhs = match tok { Token::Identifier => Self::Local(lexer.slice()), Token::Dot => Self::Member(lexer.eat_expect_id()), + Token::BinaryInteger => Self::Literal(Literal::BinaryInteger(lexer.slice())), + Token::OctalInteger => Self::Literal(Literal::OctalInteger(lexer.slice())), + Token::HexInteger => Self::Literal(Literal::HexInteger(lexer.slice())), + Token::DecimalInteger => Self::Literal(Literal::DecimalInteger(lexer.slice())), Token::Semicolon | Token::BraceClose | Token::ParanClose => return (None, tok), _ => lexer.panic_message("Unexpected token"), }; @@ -260,6 +271,10 @@ impl<'a> Expr<'a> { } } + pub fn build(lexer: &mut Lexer<'a>) -> (Option, Token) { + Self::build_start(lexer.next().unwrap(), lexer) + } + fn eat_op(lexer: &mut Lexer<'a>) -> (Option<(BinaryOp, Self)>, Token) { let tok = lexer.next().unwrap(); if let Some(op) = BinaryOp::from_token(tok) { @@ -311,15 +326,13 @@ impl BinaryOp { pub enum Literal<'a> { BinaryInteger(&'a str), OctalInteger(&'a str), + HexInteger(&'a str), DecimalInteger(&'a str), } #[derive(Debug)] pub enum Statement<'a> { - Assign { - var: &'a str, - expr: Expr<'a>, - }, + Expr(Expr<'a>), Let { var: &'a str, expr: Expr<'a>, @@ -406,6 +419,11 @@ mod tests { assert_eq!(expr.1, Token::Semicolon); } + #[test] + fn int_literals() { + parse_expr("0b1 + 0x2 - 0o3 * 0x4;"); + } + #[test] fn locals() { parse_expr("local1 + local2 - local3;");