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::*; struct Input(std::iter::Peekable>); impl Input { /// Map input.next() to return Results for use with the propagation operator fn next(&mut self) -> Result { self.0.next().ok_or("end of input".into()) } /// Map input.peek() to return Results for use with the propagation operator fn peek(&mut self) -> Result<&Token> { self.0.peek().ok_or("end of input".into()) } /// Asserts the next character to be a known token fn then(&mut self, expected: Token) -> Result<()> { match self.next()? { token if expected == token => Ok(()), token => Err(format!("expected token {} but found {}", expected, token).into()) } } } #[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(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()? == &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()? { Key(word) => match word { Pub => { match input.next()? { 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()), } _ => return Err("unrecognized thing following pub".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 input.peek()? == &Sep(Colon) { 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)?; input.then(Sep(Equals))?; 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()? != 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)?; input.then(Sep(Equals))?; 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()? { Word(id) => { match input.next()? { 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()? { Word(id) => from = Some(id), _ => return Err("identifier not following from keyword".into()) } input.then(Key(Keyword::Import))?; } todo!() } /// Block ::= 'block' Ident? ':' Body fn parse_block(input: &mut Input, state: State) -> Result { // todo: body + offset match input.next()? { Sep(Colon) => { let id = None; let body = parse_body(input, state.indent())?; Ok(Expr::Control(Block { id, body })) }, Word(label) => { match input.next()? { 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 { input.then(Sep(Colon))?; 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)?; input.then(Key(Keyword::In))?; let range = Box::new(parse_expr(input, state)?); input.then(Sep(Colon))?; 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)?); input.then(Sep(Colon))?; 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 { input.then(Sep(Colon))?; 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()? == &Key(Keyword::Elif) { input.next()?; branches.push(parse_cond_branch(input, state)?); } let mut else_body = None; if input.peek()? == &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()? == &Key(Keyword::Elif) { input.next()?; branches.push(parse_cond_branch(input, state)?); } let mut else_body = None; if input.peek()? == &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 { input.then(Sep(Colon))?; let body = parse_body(input, state.indent())?; let catches = Vec::new(); while input.peek()? == &Key(Keyword::Catch) { input.next()?; todo!(); } let mut finally = None; if input.peek()? == &Key(Keyword::Finally) { input.next()?; input.then(Sep(Colon))?; 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()? == &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()? { Key(word) => { match input.peek()? { // todo: check if the type is a special typeclass 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()) } }, Word(id) => { let mut generics = Vec::new(); if input.peek()? == &Sep(GenericLeftBracket) { 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 input.next()? == Sep(GenericLeftBracket) { let result = parse_type(input, state)?; input.then(Sep(GenericRightBracket))?; Ok(result) } 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?