Tail expressions, integer literal exprs
This commit is contained in:
parent
1b36737203
commit
9d074ddd19
|
@ -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,
|
||||
|
||||
|
|
72
src/parse.rs
72
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<Self>, Token) {
|
||||
let tok = lexer.next().unwrap();
|
||||
pub fn build_start(tok: Token, lexer: &mut Lexer<'a>) -> (Option<Self>, 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<Self>, 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;");
|
||||
|
|
Loading…
Reference in New Issue