#![allow(unused_variables)]
use crate::parser::ast::{Stmt, DestructurePattern, Expr};
use crate::parser::lexer::{Token, TokenKind};
use super::utils::Parser;
use super::precedence::parse_expression;
fn pos(parser: &Parser) -> (usize, usize) {
parser.current().map(|t| (t.line, t.col)).unwrap_or((0, 0))
}
fn parse_expr_or_tuple(parser: &mut Parser) -> Result<Expr, super::driver::ParseError> {
let (line, col) = pos(parser);
let mut exprs = Vec::new();
exprs.push(parse_expression(parser)?);
while let Some(Token { kind: TokenKind::Comma, .. }) = parser.current() {
parser.advance();
exprs.push(parse_expression(parser)?);
}
if exprs.len() == 1 {
Ok(exprs.remove(0))
} else {
Ok(Expr::BracketedArray {
items: exprs,
line,
col,
})
}
}
pub fn parse_statement(parser: &mut Parser) -> Result<Stmt, super::driver::ParseError> {
let (line, col) = pos(parser);
if let Some(Token { kind: TokenKind::Colon, .. }) = parser.current() {
let mut keys = Vec::new();
let (colon_line, colon_col) = pos(parser);
while let Some(Token { kind: TokenKind::Colon, .. }) = parser.current() {
parser.advance();
if let Some(Token { kind: TokenKind::Identifier(name), .. }) = parser.current() {
keys.push(name.clone());
parser.advance();
if let Some(Token { kind: TokenKind::Comma, .. }) = parser.current() {
parser.advance();
} else {
break;
}
} else {
return Err(super::driver::ParseError {
msg: "Expected identifier after ':' in destructure pattern".into(),
line: pos(parser).0,
col: pos(parser).1,
});
}
}
parser.expect(&TokenKind::Equals)?;
let right = parse_expression(parser)?;
if let Some(Token { kind: TokenKind::Semi, .. }) = parser.current() {
parser.advance();
}
return Ok(Stmt::AssignmentDestructure {
pattern: DestructurePattern::Keyed(keys),
right,
line: colon_line,
col: colon_col,
});
}
let save_pos = parser.pos;
let mut tuple_vars = Vec::new();
let mut at_least_one = false;
let (tuple_line, tuple_col) = pos(parser);
while let Some(Token { kind: TokenKind::Identifier(id), .. }) = parser.current() {
tuple_vars.push(id.clone());
parser.advance();
at_least_one = true;
if let Some(Token { kind: TokenKind::Comma, .. }) = parser.current() {
parser.advance();
} else {
break;
}
}
if at_least_one
&& matches!(parser.current(), Some(Token { kind: TokenKind::Equals, .. }))
&& tuple_vars.len() >= 2
{
parser.advance();
let right = parse_expr_or_tuple(parser)?;
if let Some(Token { kind: TokenKind::Semi, .. }) = parser.current() {
parser.advance();
}
return Ok(Stmt::AssignmentDestructure {
pattern: DestructurePattern::Tuple(tuple_vars),
right,
line: tuple_line,
col: tuple_col,
});
} else {
parser.pos = save_pos;
}
if let Some(Token { kind: TokenKind::Identifier(id), line, col }) = parser.current() {
if id == "extend" {
parser.advance();
parser.expect(&TokenKind::LParen)?;
if let Some(Token { kind: TokenKind::StringLiteral(p), line: sl, col: sc }) = parser.current() {
let path = p.clone();
parser.advance();
parser.expect(&TokenKind::RParen)?;
return Ok(Stmt::ImportSo {
path,
line: *line,
col: *col,
});
} else {
return Err(super::driver::ParseError {
msg: "extend => expected string literal".into(),
line: pos(parser).0,
col: pos(parser).1,
});
}
}
}
if let Some(Token { kind: TokenKind::Identifier(id), line: id_line, col: id_col }) = parser.current() {
let name = id.clone();
parser.advance();
if let Some(Token { kind: TokenKind::CaretEquals, .. }) = parser.current() {
parser.advance();
let right = parse_expression(parser)?;
if let Some(Token { kind: TokenKind::Semi, .. }) = parser.current() {
parser.advance();
}
return Ok(Stmt::AssignmentScoped {
left: Expr::Ident {
name,
line: *id_line,
col: *id_col,
},
right,
line: *id_line,
col: *id_col,
});
} else {
parser.pos -= 1;
}
}
let save_pos = parser.pos;
let expr_linecol = pos(parser);
if let Ok(left) = parse_expression(parser) {
if let Some(Token { kind: TokenKind::Equals, .. }) = parser.current() {
parser.advance(); let right = parse_expression(parser)?;
if let Some(Token { kind: TokenKind::Semi, .. }) = parser.current() {
parser.advance();
}
return Ok(Stmt::Assignment {
left,
right,
line: expr_linecol.0,
col: expr_linecol.1,
});
}
parser.pos = save_pos; }
let (expr_stmt_line, expr_stmt_col) = pos(parser);
let left = parse_expression(parser)?;
if let Some(Token { kind: TokenKind::Semi, .. }) = parser.current() {
parser.advance();
}
Ok(Stmt::ExprStmt {
expr: left,
line: expr_stmt_line,
col: expr_stmt_col,
})
}