Tail expressions, integer literal exprs

This commit is contained in:
mars 2022-03-01 10:06:47 -07:00
parent 1b36737203
commit 9d074ddd19
2 changed files with 50 additions and 29 deletions

View File

@ -57,12 +57,15 @@ pub enum Token {
#[regex(r"[a-zA-Z_][a-zA-Z0-9_]*")] #[regex(r"[a-zA-Z_][a-zA-Z0-9_]*")]
Identifier, Identifier,
#[regex(r"0b_*[01][_01]*")] #[regex(r"0b_*[01][_'01]*")]
BinaryInteger, BinaryInteger,
#[regex(r"0o_*[0-7][_0-7]*")] #[regex(r"0o_*[0-7][_'0-7]*")]
OctalInteger, OctalInteger,
#[regex(r"0x_*[0-9a-fA-F][_'0-9a-fA-F]*")]
HexInteger,
#[regex(r"-?[0-9][_'0-9]*")] #[regex(r"-?[0-9][_'0-9]*")]
DecimalInteger, DecimalInteger,

View File

@ -191,37 +191,45 @@ impl<'a> FnBody<'a> {
pub fn build(lexer: &mut Lexer<'a>) -> Self { pub fn build(lexer: &mut Lexer<'a>) -> Self {
let mut statements = Vec::new(); let mut statements = Vec::new();
let mut tail = Some(Token::Semicolon); let mut tail_expr = None;
loop { loop {
match tail { let tok = lexer.next().unwrap();
Some(Token::Semicolon) => match lexer.next().unwrap() { match tok {
Token::Let => { Token::Let => {
let (statement, next) = Statement::build_let(lexer); let (statement, next) = Statement::build_let(lexer);
statements.push(statement); statements.push(statement);
tail = Some(next); match next {
Token::Semicolon => {}
Token::BraceClose => break,
_ => lexer.panic_message("Unexpected token"),
}
} }
Token::Var => { Token::Var => {
let (statement, next) = Statement::build_var(lexer); let (statement, next) = Statement::build_var(lexer);
statements.push(statement); statements.push(statement);
tail = Some(next); 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;
}
_ => lexer.panic_message("Unexpected token"),
},
Token::BraceClose => break, Token::BraceClose => break,
_ => lexer.panic_message("Expected var, let, or assign"), _ => lexer.panic_message("Expected var, let, or assign"),
},
Some(Token::BraceClose) => break,
_ => lexer.panic_message("Unexpected token"),
} }
} }
Self { Self {
statements, statements,
tail_expr: None, tail_expr,
} }
} }
} }
@ -243,11 +251,14 @@ pub enum Expr<'a> {
} }
impl<'a> Expr<'a> { impl<'a> Expr<'a> {
pub fn build(lexer: &mut Lexer<'a>) -> (Option<Self>, Token) { pub fn build_start(tok: Token, lexer: &mut Lexer<'a>) -> (Option<Self>, Token) {
let tok = lexer.next().unwrap();
let lhs = match tok { let lhs = match tok {
Token::Identifier => Self::Local(lexer.slice()), Token::Identifier => Self::Local(lexer.slice()),
Token::Dot => Self::Member(lexer.eat_expect_id()), 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), Token::Semicolon | Token::BraceClose | Token::ParanClose => return (None, tok),
_ => lexer.panic_message("Unexpected token"), _ => lexer.panic_message("Unexpected token"),
}; };
@ -260,6 +271,10 @@ impl<'a> Expr<'a> {
} }
} }
pub fn build(lexer: &mut Lexer<'a>) -> (Option<Self>, Token) {
Self::build_start(lexer.next().unwrap(), lexer)
}
fn eat_op(lexer: &mut Lexer<'a>) -> (Option<(BinaryOp, Self)>, Token) { fn eat_op(lexer: &mut Lexer<'a>) -> (Option<(BinaryOp, Self)>, Token) {
let tok = lexer.next().unwrap(); let tok = lexer.next().unwrap();
if let Some(op) = BinaryOp::from_token(tok) { if let Some(op) = BinaryOp::from_token(tok) {
@ -311,15 +326,13 @@ impl BinaryOp {
pub enum Literal<'a> { pub enum Literal<'a> {
BinaryInteger(&'a str), BinaryInteger(&'a str),
OctalInteger(&'a str), OctalInteger(&'a str),
HexInteger(&'a str),
DecimalInteger(&'a str), DecimalInteger(&'a str),
} }
#[derive(Debug)] #[derive(Debug)]
pub enum Statement<'a> { pub enum Statement<'a> {
Assign { Expr(Expr<'a>),
var: &'a str,
expr: Expr<'a>,
},
Let { Let {
var: &'a str, var: &'a str,
expr: Expr<'a>, expr: Expr<'a>,
@ -406,6 +419,11 @@ mod tests {
assert_eq!(expr.1, Token::Semicolon); assert_eq!(expr.1, Token::Semicolon);
} }
#[test]
fn int_literals() {
parse_expr("0b1 + 0x2 - 0o3 * 0x4;");
}
#[test] #[test]
fn locals() { fn locals() {
parse_expr("local1 + local2 - local3;"); parse_expr("local1 + local2 - local3;");