use std::fmt; use crate::lex::*; use crate::ast::*; use crate::ast::Binding::*; use crate::ast::Control::*; use crate::ast::Pattern::*; use Token::*; use Literal::*; use Punctuation::*; type Input = std::iter::Peekable>; #[derive(Clone, Copy)] struct State { depth: usize, step: usize } impl State { fn indent(&self) -> State { State { depth: self.depth + self.step, step: self.step } } fn dedent(&self) -> State { State { depth: self.depth - self.step, step: self.step } } } /// Convert a basic TokenStream into an AbstractSyntaxTree pub fn astify(input: TokenStream, name: &str) -> Result { let mut input = input.into_iter().peekable(); let body = parse_body(&mut input, State { depth: 0, step: 0 })?; Ok(Expr::Binding(Module{ id: name.to_string(), body })) } /// Parse a series of Exprs, for ex. the body of a function. fn parse_body(input: &mut Input, state: State) -> Result> { let mut res = Vec::new(); while input.peek() == Some(&Indent(state.depth)) { input.next(); res.push(parse_expr(input, state)?); } Ok(res) } /// Expr ::= Let | Var | Const | Func | Type | /// Mod | Import | Block | Static | /// For | While | Loop | If | When | Try | Match fn parse_expr(input: &mut Input, state: State) -> Result { use Keyword::*; match input.next() { Some(Key(word)) => match word { Pub => { match input.next() { Some(Key(word)) => match word { Const => parse_const(input, state, true), Func => parse_funcdecl(input, state, true), Type => parse_typedecl(input, state, true), Mod => parse_mod(input, state, true), _ => return Err("unrecognized keyword following pub".into()), } Some(_) => return Err("unrecognized thing following pub".into()), None => return Err("end of input".into()), } }, Let => parse_let(input, state), Var => parse_var(input, state), Const => parse_const(input, state, false), Func => parse_funcdecl(input, state, false), Type => parse_typedecl(input, state, false), Mod => parse_mod(input, state, false), From => parse_import(input, state, true), Import => parse_import(input, state, false), Block => parse_block(input, state), Static => parse_static(input, state), For => parse_for(input, state), While => parse_while(input, state), Loop => parse_loop(input, state), If => parse_if(input, state), When => parse_when(input, state), Try => parse_try(input, state), Match => parse_match(input, state), _ => return Err("invalid keyword starting expression".into()), }, _ => todo!(), // what can i do with this?? match line here } } /// Let ::= 'let' Pattern Annotation? '=' Expr fn parse_let(input: &mut Input, state: State) -> Result { let id = parse_pattern(input, state)?; let mut kind = None; if let Some(Sep(Colon)) = input.peek() { input.next(); kind = Some(parse_typedesc(input, state)?); } if input.next() != Some(Sep(Equals)) { return Err("= not following binding".into()) } let value = Box::new(parse_expr(input, state)?); Ok(Expr::Binding(Let { id, kind, value })) } /// Var ::= 'var' Pattern Annotation? ('=' Expr)? fn parse_var(input: &mut Input, state: State) -> Result { let id = parse_pattern(input, state)?; let mut kind = None; if let Some(Sep(Colon)) = input.peek() { input.next(); kind = Some(parse_typedesc(input, state)?); } let mut value = None; if input.next() != Some(Sep(Equals)) { value = Some(Box::new(parse_expr(input, state)?)); } Ok(Expr::Binding(Var { id, kind, value })) } // Const ::= 'pub'? 'const' Pattern Annotation? '=' Expr fn parse_const(input: &mut Input, state: State, public: bool) -> Result { let id = parse_pattern(input, state)?; let mut kind = None; if let Some(Sep(Colon)) = input.peek() { input.next(); kind = Some(parse_typedesc(input, state)?); } if input.next() != Some(Sep(Equals)) { return Err("= not following binding".into()) } let value = Box::new(parse_expr(input, state)?); Ok(Expr::Binding(Const { public, id, kind, value })) } // Func ::= 'pub'? ('func' | 'proc') Ident Generics? Parameters? (':' TypeDesc) '=' Body fn parse_funcdecl(input: &mut Input, state: State, public: bool) -> Result { todo!() } // TypeDecl ::= 'pub'? 'type' Pattern Generics? '=' 'distinct'? 'ref'? TypeDesc fn parse_typedecl(input: &mut Input, state: State, public: bool) -> Result { let pattern = parse_pattern(input, state)?; todo!() } // Mod ::= 'pub'? 'mod' Ident ':' Body fn parse_mod(input: &mut Input, state: State, public: bool) -> Result { match input.next() { Some(Word(id)) => { match input.next() { Some(Sep(Colon)) => { let body = parse_body(input, state.indent())?; Ok(Expr::Binding(Module { id, body })) }, _ => return Err("unexpected token following mod label".into()), } }, _ => return Err("unexpected thing following mod keyword".into()), } } // Import ::= ('from' Ident)? 'import' Ident (',' Ident)* ('as' Ident)? fn parse_import(input: &mut Input, state: State, from_scope: bool) -> Result { let mut from = None; if from_scope { match input.next() { Some(Word(id)) => from = Some(id), _ => return Err("identifier not following from keyword".into()) } if input.next() != Some(Key(Keyword::Import)) { return Err("expected import to follow from".into()) } } todo!() } // Block ::= 'block' Ident? ':' Body fn parse_block(input: &mut Input, state: State) -> Result { // todo: body + offset match input.next() { Some(Sep(Colon)) => { let id = None; let body = parse_body(input, state.indent())?; Ok(Expr::Control(Block { id, body })) }, Some(Word(label)) => { match input.next() { Some(Sep(Colon)) => { let id = Some(label); let body = parse_body(input, state.indent())?; Ok(Expr::Control(Block { id, body })) }, _ => return Err("unexpected token following block label".into()), } }, _ => return Err("unexpected thing following block keyword".into()), } } // Static ::= 'static' ':' Body fn parse_static(input: &mut Input, state: State) -> Result { if input.next() != Some(Sep(Colon)) { return Err("colon must follow static invocation".into()); } let body = parse_body(input, state.indent())?; Ok(Expr::Control(Static { body })) } // For ::= 'for' Pattern 'in' Expr ':' Body fn parse_for(input: &mut Input, state: State) -> Result { let binding = parse_pattern(input, state)?; if input.next() != Some(Key(Keyword::In)) { return Err("expected in keyword after for pattern".into()); } let range = Box::new(parse_expr(input, state)?); if input.next() != Some(Sep(Colon)) { return Err("expected colon after in expression".into()); } let body = parse_body(input, state.indent())?; Ok(Expr::Control(For { binding, range, body })) } // While ::= 'while' Expr ':' Body fn parse_while(input: &mut Input, state: State) -> Result { let cond = Box::new(parse_expr(input, state)?); if input.next() != Some(Sep(Colon)) { return Err("expected colon after while keyword".into()); } let body = parse_body(input, state.indent())?; Ok(Expr::Control(While { cond, body })) } // Loop ::= 'loop' ':' Body fn parse_loop(input: &mut Input, state: State) -> Result { if input.next() != Some(Sep(Colon)) { return Err("expected colon after loop keyword".into()); } let body = parse_body(input, state.indent())?; Ok(Expr::Control(Loop { body })) } // If ::= 'if' Expr ':' Body ('elif' Expr ':' Body)* ('else' ':' Body)? fn parse_if(input: &mut Input, state: State) -> Result { let mut branches = Vec::new(); branches.push(parse_cond_branch(input, state)?); while input.peek() == Some(&Key(Keyword::Elif)) { input.next(); branches.push(parse_cond_branch(input, state)?); } let mut else_body = None; if input.peek() == Some(&Key(Keyword::Else)) { input.next(); else_body = Some(parse_body(input, state.indent())?); } Ok(Expr::Control(If { branches, else_body })) } // When ::= 'when' Expr ':' Body ('elif' Expr ':' Body)* ('else' ':' Body)? fn parse_when(input: &mut Input, state: State) -> Result { let mut branches = Vec::new(); branches.push(parse_cond_branch(input, state)?); while input.peek() == Some(&Key(Keyword::Elif)) { input.next(); branches.push(parse_cond_branch(input, state)?); } let mut else_body = None; if input.peek() == Some(&Key(Keyword::Else)) { input.next(); else_body = Some(parse_body(input, state.indent())?); } let mut body = Vec::new(); body.push(Expr::Control(If { branches, else_body })); Ok(Expr::Control(Static { body })) } // Try ::= 'try' ':' Body ('except' Ident (',' Ident)* ':' Body) ('finally' ':' Body)? fn parse_try(input: &mut Input, state: State) -> Result { if input.next() != Some(Sep(Colon)) { return Err("expected colon after try keyword".into()); } let body = parse_body(input, state.indent())?; let catches = Vec::new(); while input.peek() == Some(&Key(Keyword::Catch)) { input.next(); todo!(); } let mut finally = None; if input.peek() == Some(&Key(Keyword::Finally)) { input.next(); if input.next() != Some(Sep(Colon)) { return Err("expected colon after try keyword".into()); } finally = Some(parse_body(input, state.indent())?); } Ok(Expr::Control(Try { body, catches, finally })) } // Match ::= 'match' Expr ('of' Pattern (',' Pattern)* ('where' Expr)? ':' Body)+ fn parse_match(input: &mut Input, state: State) -> Result { let item = parse_pattern(input, state)?; let mut branches = Vec::new(); while input.peek() == Some(&Key(Keyword::Of)) { input.next(); todo!(); } Ok(Expr::Control(Match { item, branches })) } fn parse_typedesc(input: &mut Input, state: State) -> Result { todo!() } fn parse_pattern(input: &mut Input, state: State) -> Result { todo!() } fn parse_cond_branch(input: &mut Input, state: State) -> Result { todo!() } // lex, parse, expand, compile?