lt-core/src/parser.rs

252 lines
8.1 KiB
Rust
Raw Normal View History

2024-05-09 20:13:10 +02:00
use {
std::iter::Peekable,
crate::{
lexer::{LTIRLexer, LTIRToken, LexError},
2024-05-11 00:00:20 +02:00
expr::{LTExpr, Statement}
2024-05-09 20:13:10 +02:00
}
};
#[derive(Clone, Debug)]
pub enum ParseError {
LexError(LexError),
UnexpectedClose,
UnexpectedEnd,
UnexpectedToken
}
2024-05-11 00:00:20 +02:00
pub fn parse_expect<It>(
tokens: &mut Peekable<LTIRLexer<It>>,
expected_token: LTIRToken
) -> Result< (), ParseError >
where It: Iterator<Item = char>
{
match tokens.next() {
Some(Ok(t)) => {
if t == expected_token {
Ok(())
} else {
Err(ParseError::UnexpectedToken)
}
},
Some(Err(err)) => Err(ParseError::LexError(err)),
None => Err(ParseError::UnexpectedEnd)
}
}
pub fn parse_symbol<It>(
tokens: &mut Peekable<LTIRLexer<It>>
) -> Result< String, ParseError >
where It: Iterator<Item = char>
{
match tokens.next() {
Some(Ok(LTIRToken::Symbol(name))) => Ok(name),
Some(Ok(_)) => Err(ParseError::UnexpectedToken),
Some(Err(err)) => Err(ParseError::LexError(err)),
None => Err(ParseError::UnexpectedEnd),
}
}
2024-05-09 20:13:10 +02:00
pub fn parse_statement<It>(
tokens: &mut Peekable<LTIRLexer<It>>
) -> Result< crate::expr::Statement, ParseError >
where It: Iterator<Item = char>
{
2024-05-11 00:00:20 +02:00
if let Some(peektok) = tokens.peek() {
match peektok {
Ok(LTIRToken::Symbol(sym)) => {
match sym.as_str() {
"!" => {
tokens.next();
let name = parse_symbol(tokens)?;
let val_expr = parse_expr(tokens)?;
let _ = parse_expect(tokens, LTIRToken::StatementSep)?;
Ok(Statement::Assignment {
var_id: name,
val_expr
})
}
"let" => {
tokens.next();
let name = parse_symbol(tokens)?;
let _ = parse_expect(tokens, LTIRToken::AssignValue);
let val_expr = parse_expr(tokens)?;
let _ = parse_expect(tokens, LTIRToken::StatementSep)?;
Ok(Statement::LetAssign {
var_id: name,
val_expr
})
}
2024-05-11 00:00:20 +02:00
"while" => {
tokens.next();
let _ = parse_expect(tokens, LTIRToken::ExprOpen)?;
let cond = parse_expr(tokens)?;
let _ = parse_expect(tokens, LTIRToken::ExprClose)?;
Ok(Statement::WhileLoop {
condition: cond,
body: parse_block(tokens)?
})
}
"return" => {
tokens.next();
let expr = parse_expr(tokens)?;
let _ = parse_expect(tokens, LTIRToken::StatementSep)?;
Ok(Statement::Return(parse_expr(tokens)?))
}
_ => {
let expr = parse_expr(tokens)?;
let _ = parse_expect(tokens, LTIRToken::StatementSep)?;
Ok(Statement::Expr(expr))
}
}
}
Ok(_) => {
let expr = parse_expr(tokens)?;
let _ = parse_expect(tokens, LTIRToken::StatementSep)?;
Ok(Statement::Expr(expr))
},
Err(err) => Err(ParseError::LexError(err.clone()))
}
} else {
Err(ParseError::UnexpectedEnd)
}
2024-05-09 20:13:10 +02:00
}
pub fn parse_block<It>(
tokens: &mut Peekable<LTIRLexer<It>>
2024-05-11 00:00:20 +02:00
) -> Result< Vec<Statement>, ParseError >
2024-05-09 20:13:10 +02:00
where It: Iterator<Item = char>
{
2024-05-11 00:00:20 +02:00
let _ = parse_expect(tokens, LTIRToken::BlockOpen)?;
let mut statements = Vec::new();
while let Some(peektok) = tokens.peek() {
match peektok {
Ok(LTIRToken::BlockClose) => {
tokens.next();
return Ok(statements)
}
Ok(_) => { statements.push( parse_statement(tokens)? ); }
Err(err) => { return Err(ParseError::LexError(err.clone())); }
}
}
2024-05-09 20:13:10 +02:00
Err(ParseError::UnexpectedEnd)
}
2024-05-11 00:00:20 +02:00
pub fn parse_atom<It>(
tokens: &mut Peekable<LTIRLexer<It>>
) -> Result< crate::expr::LTExpr, ParseError >
where It: Iterator<Item = char>
{
match tokens.next() {
Some(Ok(LTIRToken::Symbol(sym))) => {
Ok(LTExpr::symbol(sym.as_str()))
}
Some(Ok(LTIRToken::Char(c))) => {
Ok(LTExpr::lit_uint(c as u64))
}
Some(Ok(LTIRToken::Num(n))) => {
Ok(LTExpr::lit_uint(n as u64))
}
Some(Ok(_)) => {
Err(ParseError::UnexpectedToken)
}
Some(Err(err)) => {
Err(ParseError::LexError(err))
}
None => {
Err(ParseError::UnexpectedEnd)
}
}
}
2024-05-09 20:13:10 +02:00
pub fn parse_expr<It>(
tokens: &mut Peekable<LTIRLexer<It>>
) -> Result< crate::expr::LTExpr, ParseError >
where It: Iterator<Item = char>
{
let mut children = Vec::new();
2024-05-11 00:00:20 +02:00
while let Some(tok) = tokens.peek() {
match tok {
Ok(LTIRToken::Lambda) => {
if children.len() == 0 {
tokens.next();
let name = parse_symbol(tokens)?;
let body = parse_expr(tokens)?;
return Ok(LTExpr::Abstraction{
arg_id: name,
arg_type: None,
val_expr: Box::new(body)
});
} else {
return Err(ParseError::UnexpectedToken);
}
2024-05-09 20:13:10 +02:00
}
2024-05-11 00:00:20 +02:00
Ok(LTIRToken::ExprOpen) => {
tokens.next();
while let Some(peektok) = tokens.peek() {
match peektok {
Ok(LTIRToken::ExprClose) => {
tokens.next();
break;
}
_ => {}
}
children.push(parse_expr(tokens)?);
}
},
Ok(LTIRToken::ExprClose) => { break; }
Ok(LTIRToken::BlockOpen) => { children.push( LTExpr::block(parse_block(tokens)?)); }
Ok(LTIRToken::BlockClose) => { break; }
Ok(LTIRToken::StatementSep) => { break; }
Ok(LTIRToken::Symbol(name)) => {
match name.as_str() {
"if" => {
tokens.next();
let _ = parse_expect(tokens, LTIRToken::ExprOpen)?;
let cond = parse_expr(tokens)?;
let _ = parse_expect(tokens, LTIRToken::ExprClose)?;
let if_expr = LTExpr::block(parse_block(tokens)?);
let mut else_expr = LTExpr::block(vec![]);
if let Some(peektok) = tokens.peek() {
if let Ok(LTIRToken::Symbol(name)) = peektok {
if name == "else" {
tokens.next();
else_expr = parse_expr(tokens)?;
}
}
}
children.push(LTExpr::Branch{
condition: Box::new(cond),
if_expr: Box::new(if_expr),
else_expr: Box::new(else_expr)
});
}
name => {
children.push(parse_atom(tokens)?);
}
}
}
Ok(atom) => { children.push(parse_atom(tokens)?); }
Err(err) => { return Err(ParseError::LexError(err.clone())); }
2024-05-09 20:13:10 +02:00
}
}
if children.len() > 0 {
let head = children.remove(0);
Ok(LTExpr::Application {
head: Box::new(head),
body: children
})
} else {
Err(ParseError::UnexpectedEnd)
}
}