use crate::frontend::lex::*; use crate::frontend::ast::*; use crate::frontend::ast::Binding::*; use crate::frontend::ast::Control::*; use crate::frontend::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), // todo: probably rework imports 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 } } /// Annotation ::= (':' TypeDesc)? fn parse_annotation(input: &mut Input, state: State) -> Result> { let mut kind = None; if let Some(Sep(Colon)) = input.peek() { input.next(); kind = Some(parse_type(input, state)?); } Ok(kind) } /// Let ::= 'let' Pattern Annotation? '=' Expr fn parse_let(input: &mut Input, state: State) -> Result { let id = parse_pattern(input, state)?; let kind = parse_annotation(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 kind = parse_annotation(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 kind = parse_annotation(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' 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 })) } fn parse_cond_branch(input: &mut Input, state: State) -> Result { todo!() } /// 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 })) } /// Type ::= /// ('ref' | 'ptr' | 'mut' | 'static' | 'struct' | 'tuple' | 'enum' | 'union' | 'interface' | 'concept') | /// ('ref' WrappedType) | ('ptr' WrappedType) | ('mut' WrappedType) | ('static' WrappedType) | ('distinct' WrappedType) | /// StructType | TupleType | EnumType | UnionType | InterfaceType /// The input stream must be normalized before attempting to parse types, because otherwise it's just a little bit hellish. /// In particular: ref, ptr, mut, static, distinct must wrap their parameters in '[' ']' and all type declarations must be on one line. fn parse_type(input: &mut Input, state: State) -> Result { use Type::*; match input.next() { Some(Key(word)) => { match input.peek() { // todo: check if the type is a special typeclass Some(Sep(GenericLeftBracket)) => (), _ => todo!() // ref, ptr, mut, static, struct, tuple, enum, union, interface, concept } match word { Keyword::Distinct => Ok(Distinct(Box::new(parse_wrapped_type(input, state)?))), Keyword::Ref => Ok(Reference(Box::new(parse_wrapped_type(input, state)?))), Keyword::Ptr => Ok(Pointer(Box::new(parse_wrapped_type(input, state)?))), Keyword::Var => Ok(Mutable(Box::new(parse_wrapped_type(input, state)?))), Keyword::Const => Ok(Static(Box::new(parse_wrapped_type(input, state)?))), Keyword::Struct => parse_struct_type(input, state), Keyword::Tuple => parse_tuple_type(input, state), Keyword::Enum => parse_enum_type(input, state), Keyword::Union => parse_union_type(input, state), Keyword::Interface => parse_interface(input, state), _ => return Err("invalid keyword present in type!".into()) } }, Some(Word(id)) => { let mut generics = Vec::new(); if let Some(Sep(GenericLeftBracket)) = input.peek() { generics = parse_generics(input, state)?; } Ok(Alias { id, generics }) }, _ => return Err("error".into()) } } /// `StructType ::= ('struct' '[' Ident ':' Type (',' Ident ':' Type)* ']'` fn parse_struct_type(input: &mut Input, state: State) -> Result { todo!() } /// `TupleType ::= 'tuple' '[' (Ident ':')? Type (',' (Ident ':')? Type)* ']'` fn parse_tuple_type(input: &mut Input, state: State) -> Result { todo!() } /// `EnumType ::= 'enum' '[' Ident ('=' Pattern)? (Ident ('=' Pattern)?)* ']'` fn parse_enum_type(input: &mut Input, state: State) -> Result { todo!() } /// `UnionType ::= 'union' '[' Ident (':' Type)? (',' Ident (':' Type)?)* ']'` fn parse_union_type(input: &mut Input, state: State) -> Result { todo!() } /// `Interface ::= 'interface' '[' Signature (',' Signature)* ']'` fn parse_interface(input: &mut Input, state: State) -> Result { todo!() } /// `Signature ::= Ident ('[' Ident (':' Type)? (',' Ident (':' Type)?)* ']')? ('(' Type (',' Type)* ')')? (':' Type)?` fn parse_signature(input: &mut Input, state: State) -> Result { todo!() } /// `WrappedType ::= Type | ('[' Type ']')` fn parse_wrapped_type(input: &mut Input, state: State) -> Result { if let Some(Sep(GenericLeftBracket)) = input.next() { let result = parse_type(input, state)?; if let Some(Sep(GenericRightBracket)) = input.next() { Ok(result) } else { Err("could not find closing generic bracket!".into()) } } else { parse_type(input, state) } } /// `GenericType ::= '[' Type (',' Type)* ']'` fn parse_generics(input: &mut Input, state: State) -> Result> { todo!() } /// Pattern ::= Literal | Ident | '(' Pattern (',' Pattern)* ')' | Ident '(' Pattern (',' Pattern)* ')' /// Literal ::= Char | String | Number | Float fn parse_pattern(input: &mut Input, state: State) -> Result { todo!() } // lex, parse, expand, compile?