use crate::ast::*; use crate::{ lexer::Token, token_stream::{Error, TokenStream}, }; pub trait Parse where Self: std::marker::Sized, { fn parse(stream: TokenStream) -> Result; } impl Parse for Type { fn parse(mut stream: TokenStream) -> Result { let kind = if let Some(Token::BracketOpen) = stream.peek() { stream.expect(Token::BracketOpen)?; let inner = stream.parse::()?; stream.expect(Token::Semi)?; let length = if let Some(Token::DecimalValue(length)) = stream.next() { length } else { return Err(stream.expected_err("array length (number)")?); }; stream.expect(Token::BracketClose)?; TypeKind::Array(Box::new(inner.0), length) } else { if let Some(Token::Identifier(ident)) = stream.next() { match &*ident { "bool" => TypeKind::Bool, "i8" => TypeKind::I8, "i16" => TypeKind::I16, "i32" => TypeKind::I32, "i64" => TypeKind::I64, "i128" => TypeKind::I128, "u8" => TypeKind::U8, "u16" => TypeKind::U16, "u32" => TypeKind::U32, "u64" => TypeKind::U64, "u128" => TypeKind::U128, "string" => TypeKind::String, _ => Err(stream.expected_err("known type identifier")?)?, } } else { return Err(stream.expected_err("type identifier")?)?; } }; Ok(Type(kind, stream.get_range().unwrap())) } } impl Parse for Expression { fn parse(mut stream: TokenStream) -> Result { let lhs = stream.parse::()?.0; parse_binop_rhs(&mut stream, lhs, None) } } #[derive(Debug)] pub struct PrimaryExpression(Expression); impl Parse for PrimaryExpression { fn parse(mut stream: TokenStream) -> Result { use ExpressionKind as Kind; let mut expr = if let Ok(exp) = stream.parse() { Expression( Kind::FunctionCall(Box::new(exp)), stream.get_range().unwrap(), ) } else if let Ok(block) = stream.parse() { Expression( Kind::BlockExpr(Box::new(block)), stream.get_range().unwrap(), ) } else if let Ok(ifexpr) = stream.parse() { Expression(Kind::IfExpr(Box::new(ifexpr)), stream.get_range().unwrap()) } else if let (Some(Token::Identifier(_)), Some(Token::BraceOpen)) = (stream.peek(), stream.peek2()) { Expression( Kind::StructInit(stream.parse()?), stream.get_range().unwrap(), ) } else if let Some(token) = stream.next() { match &token { Token::Identifier(v) => { if let Some(Token::BraceOpen) = stream.peek() { Expression( Kind::StructInit(stream.parse()?), stream.get_range().unwrap(), ) } else { Expression(Kind::VariableName(v.clone()), stream.get_range().unwrap()) } } Token::DecimalValue(v) => Expression( Kind::Literal(Literal::Number(*v)), stream.get_range().unwrap(), ), Token::StringLit(v) => Expression( Kind::Literal(Literal::String(v.clone())), stream.get_range().unwrap(), ), Token::True => Expression( Kind::Literal(Literal::Bool(true)), stream.get_range().unwrap(), ), Token::False => Expression( Kind::Literal(Literal::Bool(false)), stream.get_range().unwrap(), ), Token::ParenOpen => { let exp = stream.parse()?; stream.expect(Token::ParenClose)?; exp } Token::BracketOpen => { let mut expressions = Vec::new(); if let Ok(exp) = stream.parse() { expressions.push(exp); while let Some(Token::Comma) = stream.peek() { stream.next(); // Consume comma expressions.push(stream.parse()?); } } stream.expect(Token::BracketClose)?; Expression(Kind::Array(expressions), stream.get_range().unwrap()) } _ => Err(stream.expected_err("identifier, constant, parentheses or brackets")?)?, } } else { Err(stream.expected_err("expression")?)? }; while let Ok(ValueIndex(idx)) = stream.parse() { expr = Expression( ExpressionKind::Index(Box::new(expr), idx), stream.get_range().unwrap(), ); } Ok(PrimaryExpression(expr)) } } /// This algorithm seems somewhat like magic to me. I understand it if I read /// carefully, but it is difficult to read every single time. /// /// Reference for how the algorithm is formed: /// https://llvm.org/docs/tutorial/MyFirstLanguageFrontend/LangImpl02.html#binary-expression-parsing fn parse_binop_rhs( stream: &mut TokenStream, mut lhs: Expression, mut prev_operator: Option, ) -> Result { // Expression precedence = LHS precedence so far. let expr_precedence = if let Some(op) = prev_operator.take() { op.get_precedence() } else { 0 }; while let Ok(op) = // If next operator precedence is lower than expression precedence, we // need to climb back up the recursion. stream.parse_if::(|b| b.get_precedence() >= expr_precedence) { let curr_token_prec = op.get_precedence(); let mut rhs = stream.parse::()?.0; if let Ok(next_op) = stream.parse_peek::() { let next_prec = next_op.get_precedence(); if curr_token_prec < next_prec { // Operator on the right of rhs has more precedence, turn // rhs into lhs for new binop rhs = parse_binop_rhs(stream, rhs, Some(op))?; } else { let _ = prev_operator.insert(next_op); } } lhs = Expression( ExpressionKind::Binop(op, Box::new(lhs), Box::new(rhs)), stream.get_range().unwrap(), ); } Ok(lhs) } impl Parse for BinaryOperator { fn parse(mut stream: TokenStream) -> Result { Ok(match (stream.next(), stream.peek()) { (Some(Token::Et), Some(Token::Et)) => { stream.next(); BinaryOperator::And } (Some(Token::LessThan), Some(Token::Equals)) => { stream.next(); BinaryOperator::LE } (Some(Token::GreaterThan), Some(Token::Equals)) => { stream.next(); BinaryOperator::GE } (Some(Token::Equals), Some(Token::Equals)) => { stream.next(); BinaryOperator::EQ } (Some(Token::Exclamation), Some(Token::Equals)) => { stream.next(); BinaryOperator::NE } (Some(Token::LessThan), _) => BinaryOperator::LT, (Some(Token::GreaterThan), _) => BinaryOperator::GT, (Some(Token::Plus), _) => BinaryOperator::Add, (Some(Token::Minus), _) => BinaryOperator::Minus, (Some(Token::Times), _) => BinaryOperator::Mult, (_, _) => Err(stream.expected_err("expected operator")?)?, }) } } impl Parse for FunctionCallExpression { fn parse(mut stream: TokenStream) -> Result { if let Some(Token::Identifier(name)) = stream.next() { stream.expect(Token::ParenOpen)?; let mut args = Vec::new(); if let Ok(exp) = stream.parse() { args.push(exp); while stream.expect(Token::Comma).is_ok() { args.push(stream.parse()?); } } stream.expect(Token::ParenClose)?; Ok(FunctionCallExpression( name, args, stream.get_range().unwrap(), )) } else { Err(stream.expected_err("identifier")?) } } } impl Parse for IfExpression { fn parse(mut stream: TokenStream) -> Result { stream.expect(Token::If)?; let cond = stream.parse()?; let then_b = stream.parse()?; let else_b = if let Ok(_) = stream.expect(Token::Else) { Some(stream.parse()?) } else { None }; Ok(IfExpression( cond, then_b, else_b, stream.get_range().unwrap(), )) } } impl Parse for LetStatement { fn parse(mut stream: TokenStream) -> Result { stream.expect(Token::LetKeyword)?; let mutability = stream.expect(Token::MutKeyword).is_ok(); if let Some(Token::Identifier(variable)) = stream.next() { stream.expect(Token::Equals)?; let expression = stream.parse()?; stream.expect(Token::Semi)?; Ok(LetStatement( variable, None, // TODO add possibility to name type mutability, expression, stream.get_range().unwrap(), )) } else { Err(stream.expected_err("identifier")?) } } } impl Parse for ImportStatement { fn parse(mut stream: TokenStream) -> Result { stream.expect(Token::ImportKeyword)?; let mut import_list = Vec::new(); if let Some(Token::Identifier(name)) = stream.next() { import_list.push(name); while stream.expect(Token::Colon).is_ok() && stream.expect(Token::Colon).is_ok() { if let Some(Token::Identifier(name)) = stream.next() { import_list.push(name); } else { Err(stream.expected_err("identifier")?)? } } } else { Err(stream.expected_err("identifier")?)? } stream.expect(Token::Semi)?; Ok(ImportStatement(import_list, stream.get_range().unwrap())) } } impl Parse for FunctionDefinition { fn parse(mut stream: TokenStream) -> Result { let is_pub = if let Some(Token::PubKeyword) = stream.peek() { stream.next(); // Consume pub true } else { false }; stream.expect(Token::FnKeyword)?; Ok(FunctionDefinition( stream.parse()?, is_pub, stream.parse()?, stream.get_range().unwrap(), )) } } impl Parse for FunctionSignature { fn parse(mut stream: TokenStream) -> Result { if let Some(Token::Identifier(name)) = stream.next() { stream.expect(Token::ParenOpen)?; let mut args = Vec::new(); while let Some(Token::Identifier(arg_name)) = stream.peek() { stream.next(); stream.expect(Token::Colon)?; args.push((arg_name, stream.parse()?)); } stream.expect(Token::ParenClose)?; let mut return_type = None; if stream.expect(Token::Arrow).is_ok() { return_type = Some(stream.parse()?); } Ok(FunctionSignature { name, args, return_type, range: stream.get_range().unwrap(), }) } else { Err(stream.expected_err("identifier")?)? } } } impl Parse for Block { fn parse(mut stream: TokenStream) -> Result { let mut statements = Vec::new(); let mut return_stmt = None; stream.expect(Token::BraceOpen)?; while !matches!(stream.peek(), Some(Token::BraceClose)) { if let Some((_, e)) = return_stmt.take() { // Special list of expressions that are simply not warned about, // if semicolon is missing. if !matches!(e, Expression(ExpressionKind::IfExpr(_), _)) { println!("Oh no, does this statement lack ;"); } statements.push(BlockLevelStatement::Expression(e)); } let statement = stream.parse()?; if let BlockLevelStatement::Return(r_type, e) = &statement { match r_type { ReturnType::Hard => { return_stmt = Some((*r_type, e.clone())); break; // Return has to be the last statement // TODO: Make a mechanism that "can" parse even after this } ReturnType::Soft => { return_stmt = Some((*r_type, e.clone())); continue; // In theory possible to have lines after a soft return } }; } statements.push(statement); } stream.expect(Token::BraceClose)?; Ok(Block(statements, return_stmt, stream.get_range().unwrap())) } } impl Parse for VariableReference { fn parse(mut stream: TokenStream) -> Result { if let Some(Token::Identifier(ident)) = stream.next() { let mut var_ref = VariableReference( VariableReferenceKind::Name(ident, stream.get_one_token_range()), stream.get_range().unwrap(), ); while let Ok(ValueIndex(idx)) = stream.parse() { var_ref = VariableReference( VariableReferenceKind::Index(Box::new(var_ref), idx), stream.get_range().unwrap(), ); } Ok(var_ref) } else { Err(stream.expected_err("identifier")?)? } } } impl Parse for StructInit { fn parse(mut stream: TokenStream) -> Result { let Some(Token::Identifier(name)) = stream.next() else { return Err(stream.expected_err("struct identifier")?); }; stream.expect(Token::BraceOpen)?; let named_list = stream.parse::>()?; let fields = named_list.0.into_iter().map(|f| (f.0, f.1)).collect(); stream.expect(Token::BraceClose)?; stream.expect(Token::Semi)?; Ok(StructInit { name, fields }) } } #[derive(Debug)] pub struct NamedFieldList(Vec>); impl Parse for NamedFieldList { fn parse(mut stream: TokenStream) -> Result { let mut fields = Vec::new(); while let Ok(field) = stream.parse() { fields.push(field); match stream.peek() { Some(Token::Comma) => { stream.next(); } // Consume comma Some(Token::BraceClose) => break, Some(_) | None => Err(stream.expected_err("another field or closing brace")?)?, } } Ok(NamedFieldList(fields)) } } #[derive(Debug)] pub struct NamedField(String, T, TokenRange); impl Parse for NamedField { fn parse(mut stream: TokenStream) -> Result { let Some(Token::Identifier(field_name)) = stream.next() else { return Err(stream.expected_err("type name")?); }; stream.expect(Token::Colon)?; let value = stream.parse()?; Ok(NamedField(field_name, value, stream.get_range().unwrap())) } } #[derive(Debug, Clone, Copy)] pub struct ValueIndex(u64); impl Parse for ValueIndex { fn parse(mut stream: TokenStream) -> Result { stream.expect(Token::BracketOpen)?; if let Some(Token::DecimalValue(idx)) = stream.next() { stream.expect(Token::BracketClose)?; Ok(ValueIndex(idx)) } else { return Err(stream.expected_err("array index (number)")?); } } } impl Parse for BlockLevelStatement { fn parse(mut stream: TokenStream) -> Result { use BlockLevelStatement as Stmt; Ok(match stream.peek() { Some(Token::LetKeyword) => Stmt::Let(stream.parse()?), Some(Token::ImportKeyword) => Stmt::Import { _i: stream.parse()?, }, Some(Token::ReturnKeyword) => { stream.next(); let exp = stream.parse()?; stream.expect(Token::Semi)?; Stmt::Return(ReturnType::Hard, exp) } _ => { if let Ok(SetStatement(ident, expr, range)) = stream.parse() { Stmt::Set(ident, expr, range) } else { if let Ok(e) = stream.parse() { if stream.expect(Token::Semi).is_ok() { Stmt::Expression(e) } else { Stmt::Return(ReturnType::Soft, e) } } else { Err(stream.expected_err("expression")?)? } } } }) } } #[derive(Debug)] pub struct SetStatement(VariableReference, Expression, TokenRange); impl Parse for SetStatement { fn parse(mut stream: TokenStream) -> Result { let var_ref = stream.parse()?; stream.expect(Token::Equals)?; let expr = stream.parse()?; stream.expect(Token::Semi)?; Ok(SetStatement(var_ref, expr, stream.get_range().unwrap())) } } #[derive(Debug)] pub struct StructDefinition(String, Vec, TokenRange); impl Parse for StructDefinition { fn parse(mut stream: TokenStream) -> Result { stream.expect(Token::Struct)?; let Some(Token::Identifier(name)) = stream.next() else { return Err(stream.expected_err("identifier")?); }; stream.expect(Token::BraceOpen)?; let named_fields = stream.parse::>()?; let fields = named_fields .0 .into_iter() .map(|f| StructDefinitionField { name: f.0, ty: f.1, range: f.2, }) .collect(); stream.expect(Token::BraceClose)?; Ok(StructDefinition(name, fields, stream.get_range().unwrap())) } } impl Parse for TopLevelStatement { fn parse(mut stream: TokenStream) -> Result { use TopLevelStatement as Stmt; Ok(match stream.peek() { Some(Token::ImportKeyword) => Stmt::Import(stream.parse()?), Some(Token::Extern) => { stream.next(); // Consume Extern stream.expect(Token::FnKeyword)?; let extern_fn = Stmt::ExternFunction(stream.parse()?); stream.expect(Token::Semi)?; extern_fn } Some(Token::FnKeyword) | Some(Token::PubKeyword) => { Stmt::FunctionDefinition(stream.parse()?) } Some(Token::Struct) => { let StructDefinition(name, fields, range) = stream.parse::()?; Stmt::TypeDefinition(TypeDefinition { name, kind: TypeDefinitionKind::Struct(fields), range, }) } _ => Err(stream.expected_err("import or fn")?)?, }) } }