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();
|
2024-05-11 18:07:58 +02:00
|
|
|
// todo accept address-expression instead of symbol
|
2024-05-11 00:00:20 +02:00
|
|
|
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
|
|
|
|
})
|
|
|
|
}
|
2024-05-11 01:19:44 +02:00
|
|
|
"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();
|
2024-05-12 04:22:32 +02:00
|
|
|
|
|
|
|
let mut args = Vec::new();
|
|
|
|
while let Some(Ok(LTIRToken::Symbol(_))) = tokens.peek() {
|
|
|
|
args.push((parse_symbol(tokens)?, None));
|
|
|
|
}
|
2024-05-11 00:00:20 +02:00
|
|
|
let body = parse_expr(tokens)?;
|
|
|
|
|
|
|
|
return Ok(LTExpr::Abstraction{
|
2024-05-12 04:22:32 +02:00
|
|
|
args,
|
|
|
|
body: Box::new(body)
|
2024-05-11 00:00:20 +02:00
|
|
|
});
|
|
|
|
} 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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|