diff options
Diffstat (limited to 'src/frontend')
-rw-r--r-- | src/frontend/lex.rs | 6 | ||||
-rw-r--r-- | src/frontend/parse.rs | 265 |
2 files changed, 145 insertions, 126 deletions
diff --git a/src/frontend/lex.rs b/src/frontend/lex.rs index 0d9fd22..a51b21d 100644 --- a/src/frontend/lex.rs +++ b/src/frontend/lex.rs @@ -84,7 +84,9 @@ pub enum Punctuation { GenericRightBracket, // ] ArrayLeftBracket, // [ ArrayRightBracket, // ] - StructLeftBrace, // } + ScopeLeftBrace, // { + ScopeRightBrace, // } + StructLeftBrace, // { StructRightBrace, // } Equals, // = Plus, // + @@ -522,6 +524,8 @@ impl std::fmt::Display for Punctuation { GenericRightBracket => write!(f, "]"), ArrayLeftBracket => write!(f, " ["), ArrayRightBracket => write!(f, "]"), + ScopeLeftBrace => write!(f, "{{"), + ScopeRightBrace => write!(f, "}}"), StructLeftBrace => write!(f, "{{"), StructRightBrace => write!(f, "}}"), Equals => write!(f, "="), diff --git a/src/frontend/parse.rs b/src/frontend/parse.rs index 62fe39f..dba94ec 100644 --- a/src/frontend/parse.rs +++ b/src/frontend/parse.rs @@ -29,128 +29,128 @@ impl Input { } } -#[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<Expr> { let mut input = Input(input.into_iter().peekable()); - let body = parse_body(&mut input, State { depth: 0, step: 0 })?; + let body = parse_body(&mut input)?; 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<Vec<Expr>> { +/// Body ::= Expr | ('{' Expr (';' Expr)* '}') +fn parse_body(input: &mut Input) -> Result<Vec<Expr>> { let mut res = Vec::new(); - while input.peek()? == &Indent(state.depth) { - input.next()?; - res.push(parse_expr(input, state)?); + if input.peek()? != &Sep(ScopeLeftBrace) { + res.push(parse_expr(input)?); + return Ok(res); + } + input.then(Sep(ScopeLeftBrace))?; + while input.peek()? != &Sep(ScopeRightBrace) { + res.push(parse_expr(input)?); + if input.peek()? == &Sep(Semicolon) { + input.next()?; + } } + input.then(Sep(ScopeRightBrace))?; 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<Expr> { +fn parse_expr(input: &mut Input) -> Result<Expr> { 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), + Const => parse_const(input, true), + Func => parse_funcdecl(input, true), + Type => parse_typedecl(input, true), + Mod => parse_mod(input, 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), + Let => parse_let(input), + Var => parse_var(input), + Const => parse_const(input, false), + Func => parse_funcdecl(input, false), + Type => parse_typedecl(input, false), + Mod => parse_mod(input, false), + From => parse_import(input, true), // todo: probably rework imports + Import => parse_import(input, false), + Block => parse_block(input), + Static => parse_static(input), + For => parse_for(input), + While => parse_while(input), + Loop => parse_loop(input), + If => parse_if(input), + When => parse_when(input), + Try => parse_try(input), + Match => parse_match(input), _ => 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<Option<Type>> { - 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<Expr> { - let id = parse_pattern(input, state)?; - let kind = parse_annotation(input, state)?; +fn parse_let(input: &mut Input) -> Result<Expr> { + let id = parse_pattern(input)?; + let kind = parse_annotation(input)?; input.then(Sep(Equals))?; - let value = Box::new(parse_expr(input, state)?); + let value = Box::new(parse_expr(input)?); Ok(Expr::Binding(Let { id, kind, value })) } + /// Var ::= 'var' Pattern Annotation? ('=' Expr)? -fn parse_var(input: &mut Input, state: State) -> Result<Expr> { - let id = parse_pattern(input, state)?; - let kind = parse_annotation(input, state)?; +fn parse_var(input: &mut Input) -> Result<Expr> { + let id = parse_pattern(input)?; + let kind = parse_annotation(input)?; let mut value = None; if input.next()? != Sep(Equals) { - value = Some(Box::new(parse_expr(input, state)?)); + value = Some(Box::new(parse_expr(input)?)); } Ok(Expr::Binding(Var { id, kind, value })) } + /// Const ::= 'pub'? 'const' Pattern Annotation? '=' Expr -fn parse_const(input: &mut Input, state: State, public: bool) -> Result<Expr> { - let id = parse_pattern(input, state)?; - let kind = parse_annotation(input, state)?; +fn parse_const(input: &mut Input, public: bool) -> Result<Expr> { + let id = parse_pattern(input)?; + let kind = parse_annotation(input)?; input.then(Sep(Equals))?; - let value = Box::new(parse_expr(input, state)?); + let value = Box::new(parse_expr(input)?); Ok(Expr::Binding(Const { public, id, kind, value })) } + +/// Annotation ::= (':' TypeDesc)? +fn parse_annotation(input: &mut Input) -> Result<Option<Type>> { + let mut kind = None; + if input.peek()? == &Sep(Colon) { + input.next()?; + kind = Some(parse_type(input)?); + } + Ok(kind) +} + /// Func ::= 'pub'? 'func' Ident Generics? Parameters? (':' TypeDesc) '=' Body -fn parse_funcdecl(input: &mut Input, state: State, public: bool) -> Result<Expr> { todo!() } +fn parse_funcdecl(input: &mut Input, public: bool) -> Result<Expr> { todo!() } + /// TypeDecl ::= 'pub'? 'type' Pattern Generics? '=' 'distinct'? 'ref'? TypeDesc -fn parse_typedecl(input: &mut Input, state: State, public: bool) -> Result<Expr> { - let pattern = parse_pattern(input, state)?; +fn parse_typedecl(input: &mut Input, public: bool) -> Result<Expr> { + let pattern = parse_pattern(input)?; todo!() } + /// Mod ::= 'pub'? 'mod' Ident ':' Body -fn parse_mod(input: &mut Input, state: State, public: bool) -> Result<Expr> { +fn parse_mod(input: &mut Input, public: bool) -> Result<Expr> { match input.next()? { Word(id) => { match input.next()? { Sep(Colon) => { - let body = parse_body(input, state.indent())?; + let body = parse_body(input)?; Ok(Expr::Binding(Module { id, body })) }, _ => return Err("unexpected token following mod label".into()), @@ -161,7 +161,7 @@ fn parse_mod(input: &mut Input, state: State, public: bool) -> Result<Expr> { } /// Import ::= ('from' Ident)? 'import' Ident (',' Ident)* ('as' Ident)? -fn parse_import(input: &mut Input, state: State, from_scope: bool) -> Result<Expr> { +fn parse_import(input: &mut Input, from_scope: bool) -> Result<Expr> { let mut from = None; if from_scope { match input.next()? { @@ -172,19 +172,20 @@ fn parse_import(input: &mut Input, state: State, from_scope: bool) -> Result<Exp } todo!() } + /// Block ::= 'block' Ident? ':' Body -fn parse_block(input: &mut Input, state: State) -> Result<Expr> { // todo: body + offset +fn parse_block(input: &mut Input) -> Result<Expr> { // todo: body + offset match input.next()? { Sep(Colon) => { let id = None; - let body = parse_body(input, state.indent())?; + let body = parse_body(input)?; Ok(Expr::Control(Block { id, body })) }, Word(label) => { match input.next()? { Sep(Colon) => { let id = Some(label); - let body = parse_body(input, state.indent())?; + let body = parse_body(input)?; Ok(Expr::Control(Block { id, body })) }, _ => return Err("unexpected token following block label".into()), @@ -193,74 +194,87 @@ fn parse_block(input: &mut Input, state: State) -> Result<Expr> { // todo: body _ => return Err("unexpected thing following block keyword".into()), } } + /// Static ::= 'static' ':' Body -fn parse_static(input: &mut Input, state: State) -> Result<Expr> { +fn parse_static(input: &mut Input) -> Result<Expr> { input.then(Sep(Colon))?; - let body = parse_body(input, state.indent())?; + let body = parse_body(input)?; Ok(Expr::Control(Static { body })) } /// For ::= 'for' Pattern 'in' Expr ':' Body -fn parse_for(input: &mut Input, state: State) -> Result<Expr> { - let binding = parse_pattern(input, state)?; +fn parse_for(input: &mut Input) -> Result<Expr> { + let binding = parse_pattern(input)?; input.then(Key(Keyword::In))?; - let range = Box::new(parse_expr(input, state)?); + let range = Box::new(parse_expr(input)?); input.then(Sep(Colon))?; - let body = parse_body(input, state.indent())?; + let body = parse_body(input)?; Ok(Expr::Control(For { binding, range, body })) } + /// While ::= 'while' Expr ':' Body -fn parse_while(input: &mut Input, state: State) -> Result<Expr> { - let cond = Box::new(parse_expr(input, state)?); +fn parse_while(input: &mut Input) -> Result<Expr> { + let cond = Box::new(parse_expr(input)?); input.then(Sep(Colon))?; - let body = parse_body(input, state.indent())?; + let body = parse_body(input)?; Ok(Expr::Control(While { cond, body })) } + /// Loop ::= 'loop' ':' Body -fn parse_loop(input: &mut Input, state: State) -> Result<Expr> { +fn parse_loop(input: &mut Input) -> Result<Expr> { input.then(Sep(Colon))?; - let body = parse_body(input, state.indent())?; + let body = parse_body(input)?; Ok(Expr::Control(Loop { body })) } -/// If ::= 'if' Expr ':' Body ('elif' Expr ':' Body)* ('else' ':' Body)? -fn parse_if(input: &mut Input, state: State) -> Result<Expr> { +/// If ::= 'if' CondBranch ('elif' CondBranch)* ('else' ':' Body)? +fn parse_if(input: &mut Input) -> Result<Expr> { let mut branches = Vec::new(); - branches.push(parse_cond_branch(input, state)?); + branches.push(parse_cond_branch(input)?); while input.peek()? == &Key(Keyword::Elif) { input.next()?; - branches.push(parse_cond_branch(input, state)?); + branches.push(parse_cond_branch(input)?); } let mut else_body = None; if input.peek()? == &Key(Keyword::Else) { input.next()?; - else_body = Some(parse_body(input, state.indent())?); + else_body = Some(parse_body(input)?); } 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<Expr> { + +// When ::= 'when' CondBranch ('elif' CondBranch)* ('else' ':' Body)? +fn parse_when(input: &mut Input) -> Result<Expr> { let mut branches = Vec::new(); - branches.push(parse_cond_branch(input, state)?); + branches.push(parse_cond_branch(input)?); while input.peek()? == &Key(Keyword::Elif) { input.next()?; - branches.push(parse_cond_branch(input, state)?); + branches.push(parse_cond_branch(input)?); } let mut else_body = None; if input.peek()? == &Key(Keyword::Else) { input.next()?; - else_body = Some(parse_body(input, state.indent())?); + input.then(Sep(Colon))?; + else_body = Some(parse_body(input)?); } 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<CondBranch> { todo!() } + +/// CondBranch ::= Expr ':' Body +fn parse_cond_branch(input: &mut Input) -> Result<CondBranch> { + let cond = parse_expr(input)?; + input.then(Sep(Colon))?; + let body = parse_body(input)?; + Ok(CondBranch { cond, body }) +} + /// Try ::= 'try' ':' Body ('except' Ident (',' Ident)* ':' Body) ('finally' ':' Body)? -fn parse_try(input: &mut Input, state: State) -> Result<Expr> { +fn parse_try(input: &mut Input) -> Result<Expr> { input.then(Sep(Colon))?; - let body = parse_body(input, state.indent())?; - let catches = Vec::new(); + let body = parse_body(input)?; + let mut catches = Vec::new(); while input.peek()? == &Key(Keyword::Catch) { input.next()?; todo!(); @@ -269,13 +283,14 @@ fn parse_try(input: &mut Input, state: State) -> Result<Expr> { if input.peek()? == &Key(Keyword::Finally) { input.next()?; input.then(Sep(Colon))?; - finally = Some(parse_body(input, state.indent())?); + finally = Some(parse_body(input)?); } 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<Expr> { - let item = parse_pattern(input, state)?; +fn parse_match(input: &mut Input) -> Result<Expr> { + let item = parse_pattern(input)?; // fixme let mut branches = Vec::new(); while input.peek()? == &Key(Keyword::Of) { input.next()?; @@ -290,7 +305,7 @@ fn parse_match(input: &mut Input, state: State) -> Result<Expr> { /// 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<Type> { +fn parse_type(input: &mut Input) -> Result<Type> { use Type::*; match input.next()? { Key(word) => { @@ -299,23 +314,23 @@ fn parse_type(input: &mut Input, state: State) -> Result<Type> { _ => 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), + Keyword::Distinct => Ok(Distinct(Box::new(parse_wrapped_type(input)?))), + Keyword::Ref => Ok(Reference(Box::new(parse_wrapped_type(input)?))), + Keyword::Ptr => Ok(Pointer(Box::new(parse_wrapped_type(input)?))), + Keyword::Var => Ok(Mutable(Box::new(parse_wrapped_type(input)?))), + Keyword::Const => Ok(Static(Box::new(parse_wrapped_type(input)?))), + Keyword::Struct => parse_struct_type(input), + Keyword::Tuple => parse_tuple_type(input), + Keyword::Enum => parse_enum_type(input), + Keyword::Union => parse_union_type(input), + Keyword::Interface => parse_interface(input), _ => 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)?; + generics = parse_generics(input)?; } Ok(Alias { id, generics }) }, @@ -324,34 +339,34 @@ fn parse_type(input: &mut Input, state: State) -> Result<Type> { } /// `StructType ::= ('struct' '[' Ident ':' Type (',' Ident ':' Type)* ']'` -fn parse_struct_type(input: &mut Input, state: State) -> Result<Type> { todo!() } +fn parse_struct_type(input: &mut Input) -> Result<Type> { todo!() } /// `TupleType ::= 'tuple' '[' (Ident ':')? Type (',' (Ident ':')? Type)* ']'` -fn parse_tuple_type(input: &mut Input, state: State) -> Result<Type> { todo!() } +fn parse_tuple_type(input: &mut Input) -> Result<Type> { todo!() } /// `EnumType ::= 'enum' '[' Ident ('=' Pattern)? (Ident ('=' Pattern)?)* ']'` -fn parse_enum_type(input: &mut Input, state: State) -> Result<Type> { todo!() } +fn parse_enum_type(input: &mut Input) -> Result<Type> { todo!() } /// `UnionType ::= 'union' '[' Ident (':' Type)? (',' Ident (':' Type)?)* ']'` -fn parse_union_type(input: &mut Input, state: State) -> Result<Type> { todo!() } +fn parse_union_type(input: &mut Input) -> Result<Type> { todo!() } /// `Interface ::= 'interface' '[' Signature (',' Signature)* ']'` -fn parse_interface(input: &mut Input, state: State) -> Result<Type> { todo!() } +fn parse_interface(input: &mut Input) -> Result<Type> { todo!() } /// `Signature ::= Ident ('[' Ident (':' Type)? (',' Ident (':' Type)?)* ']')? ('(' Type (',' Type)* ')')? (':' Type)?` -fn parse_signature(input: &mut Input, state: State) -> Result<Sig> { todo!() } +fn parse_signature(input: &mut Input) -> Result<Sig> { todo!() } /// `WrappedType ::= Type | ('[' Type ']')` -fn parse_wrapped_type(input: &mut Input, state: State) -> Result<Type> { +fn parse_wrapped_type(input: &mut Input) -> Result<Type> { if input.next()? == Sep(GenericLeftBracket) { - let result = parse_type(input, state)?; + let result = parse_type(input)?; input.then(Sep(GenericRightBracket))?; Ok(result) } else { - parse_type(input, state) + parse_type(input) } } /// `GenericType ::= '[' Type (',' Type)* ']'` -fn parse_generics(input: &mut Input, state: State) -> Result<Vec<Type>> { todo!() } +fn parse_generics(input: &mut Input) -> Result<Vec<Type>> { todo!() } /// Pattern ::= Literal | Ident | '(' Pattern (',' Pattern)* ')' | Ident '(' Pattern (',' Pattern)* ')' -/// Literal ::= Char | String | Number | Float -fn parse_pattern(input: &mut Input, state: State) -> Result<Pattern> { todo!() } +fn parse_pattern(input: &mut Input) -> Result<Pattern> { todo!() } -// lex, parse, expand, compile? +/// Literal ::= Char | String | Number | Float +fn parse_literal(input: &mut Input) -> Result<Pattern> { todo!() } |