aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/parse.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/parse.rs')
-rw-r--r--src/frontend/parse.rs134
1 files changed, 99 insertions, 35 deletions
diff --git a/src/frontend/parse.rs b/src/frontend/parse.rs
index c525982..43de16e 100644
--- a/src/frontend/parse.rs
+++ b/src/frontend/parse.rs
@@ -1,5 +1,3 @@
-use std::fmt;
-
use crate::frontend::lex::*;
use crate::frontend::ast::*;
use crate::frontend::ast::Binding::*;
@@ -43,9 +41,8 @@ fn parse_body(input: &mut Input, state: State) -> Result<Vec<Expr>> {
Ok(res)
}
-/// Expr ::= Let | Var | Const | Func | Type |
-/// Mod | Import | Block | Static |
-/// For | While | Loop | If | When | Try | Match
+/// 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> {
use Keyword::*;
match input.next() {
@@ -69,7 +66,7 @@ fn parse_expr(input: &mut Input, state: State) -> Result<Expr> {
Func => parse_funcdecl(input, state, false),
Type => parse_typedecl(input, state, false),
Mod => parse_mod(input, state, false),
- From => parse_import(input, state, true),
+ 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),
@@ -86,14 +83,19 @@ fn parse_expr(input: &mut Input, state: State) -> Result<Expr> {
}
}
-/// Let ::= 'let' Pattern Annotation? '=' Expr
-fn parse_let(input: &mut Input, state: State) -> Result<Expr> {
- let id = parse_pattern(input, state)?;
+/// Annotation ::= (':' TypeDesc)?
+fn parse_annotation(input: &mut Input, state: State) -> Result<Option<Type>> {
let mut kind = None;
if let Some(Sep(Colon)) = input.peek() {
input.next();
- kind = Some(parse_typedesc(input, state)?);
+ 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)?;
if input.next() != Some(Sep(Equals)) {
return Err("= not following binding".into())
}
@@ -103,39 +105,31 @@ fn parse_let(input: &mut Input, state: State) -> Result<Expr> {
/// Var ::= 'var' Pattern Annotation? ('=' Expr)?
fn parse_var(input: &mut Input, state: State) -> Result<Expr> {
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 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
+/// 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 mut kind = None;
- if let Some(Sep(Colon)) = input.peek() {
- input.next();
- kind = Some(parse_typedesc(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' | 'proc') Ident Generics? Parameters? (':' TypeDesc) '=' Body
+/// Func ::= 'pub'? 'func' Ident Generics? Parameters? (':' TypeDesc) '=' Body
fn parse_funcdecl(input: &mut Input, state: State, public: bool) -> Result<Expr> { todo!() }
-// TypeDecl ::= 'pub'? 'type' Pattern Generics? '=' 'distinct'? 'ref'? TypeDesc
+/// 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)?;
todo!()
}
-// Mod ::= 'pub'? 'mod' Ident ':' Body
+/// Mod ::= 'pub'? 'mod' Ident ':' Body
fn parse_mod(input: &mut Input, state: State, public: bool) -> Result<Expr> {
match input.next() {
Some(Word(id)) => {
@@ -151,7 +145,7 @@ fn parse_mod(input: &mut Input, state: State, public: bool) -> Result<Expr> {
}
}
-// Import ::= ('from' Ident)? 'import' Ident (',' Ident)* ('as' Ident)?
+/// Import ::= ('from' Ident)? 'import' Ident (',' Ident)* ('as' Ident)?
fn parse_import(input: &mut Input, state: State, from_scope: bool) -> Result<Expr> {
let mut from = None;
if from_scope {
@@ -165,7 +159,7 @@ fn parse_import(input: &mut Input, state: State, from_scope: bool) -> Result<Exp
}
todo!()
}
-// Block ::= 'block' Ident? ':' Body
+/// Block ::= 'block' Ident? ':' Body
fn parse_block(input: &mut Input, state: State) -> Result<Expr> { // todo: body + offset
match input.next() {
Some(Sep(Colon)) => {
@@ -186,7 +180,7 @@ fn parse_block(input: &mut Input, state: State) -> Result<Expr> { // todo: body
_ => return Err("unexpected thing following block keyword".into()),
}
}
-// Static ::= 'static' ':' Body
+/// Static ::= 'static' ':' Body
fn parse_static(input: &mut Input, state: State) -> Result<Expr> {
if input.next() != Some(Sep(Colon)) {
return Err("colon must follow static invocation".into());
@@ -195,7 +189,7 @@ fn parse_static(input: &mut Input, state: State) -> Result<Expr> {
Ok(Expr::Control(Static { body }))
}
-// For ::= 'for' Pattern 'in' Expr ':' Body
+/// For ::= 'for' Pattern 'in' Expr ':' Body
fn parse_for(input: &mut Input, state: State) -> Result<Expr> {
let binding = parse_pattern(input, state)?;
if input.next() != Some(Key(Keyword::In)) {
@@ -208,7 +202,7 @@ fn parse_for(input: &mut Input, state: State) -> Result<Expr> {
let body = parse_body(input, state.indent())?;
Ok(Expr::Control(For { binding, range, body }))
}
-// While ::= 'while' Expr ':' Body
+/// While ::= 'while' Expr ':' Body
fn parse_while(input: &mut Input, state: State) -> Result<Expr> {
let cond = Box::new(parse_expr(input, state)?);
if input.next() != Some(Sep(Colon)) {
@@ -217,7 +211,7 @@ fn parse_while(input: &mut Input, state: State) -> Result<Expr> {
let body = parse_body(input, state.indent())?;
Ok(Expr::Control(While { cond, body }))
}
-// Loop ::= 'loop' ':' Body
+/// Loop ::= 'loop' ':' Body
fn parse_loop(input: &mut Input, state: State) -> Result<Expr> {
if input.next() != Some(Sep(Colon)) {
return Err("expected colon after loop keyword".into());
@@ -226,7 +220,7 @@ fn parse_loop(input: &mut Input, state: State) -> Result<Expr> {
Ok(Expr::Control(Loop { body }))
}
-// If ::= 'if' Expr ':' Body ('elif' Expr ':' Body)* ('else' ':' Body)?
+/// If ::= 'if' Expr ':' Body ('elif' Expr ':' Body)* ('else' ':' Body)?
fn parse_if(input: &mut Input, state: State) -> Result<Expr> {
let mut branches = Vec::new();
branches.push(parse_cond_branch(input, state)?);
@@ -258,7 +252,8 @@ fn parse_when(input: &mut Input, state: State) -> Result<Expr> {
body.push(Expr::Control(If { branches, else_body }));
Ok(Expr::Control(Static { body }))
}
-// Try ::= 'try' ':' Body ('except' Ident (',' Ident)* ':' Body) ('finally' ':' Body)?
+fn parse_cond_branch(input: &mut Input, state: State) -> Result<CondBranch> { todo!() }
+/// Try ::= 'try' ':' Body ('except' Ident (',' Ident)* ':' Body) ('finally' ':' Body)?
fn parse_try(input: &mut Input, state: State) -> Result<Expr> {
if input.next() != Some(Sep(Colon)) {
return Err("expected colon after try keyword".into());
@@ -279,7 +274,7 @@ fn parse_try(input: &mut Input, state: State) -> Result<Expr> {
}
Ok(Expr::Control(Try { body, catches, finally }))
}
-// Match ::= 'match' Expr ('of' Pattern (',' Pattern)* ('where' Expr)? ':' Body)+
+/// 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)?;
let mut branches = Vec::new();
@@ -290,8 +285,77 @@ fn parse_match(input: &mut Input, state: State) -> Result<Expr> {
Ok(Expr::Control(Match { item, branches }))
}
-fn parse_typedesc(input: &mut Input, state: State) -> Result<Type> { todo!() }
+/// 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<Type> {
+ 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<Type> { todo!() }
+/// `TupleType ::= 'tuple' '[' (Ident ':')? Type (',' (Ident ':')? Type)* ']'`
+fn parse_tuple_type(input: &mut Input, state: State) -> Result<Type> { todo!() }
+/// `EnumType ::= 'enum' '[' Ident ('=' Pattern)? (Ident ('=' Pattern)?)* ']'`
+fn parse_enum_type(input: &mut Input, state: State) -> Result<Type> { todo!() }
+/// `UnionType ::= 'union' '[' Ident (':' Type)? (',' Ident (':' Type)?)* ']'`
+fn parse_union_type(input: &mut Input, state: State) -> Result<Type> { todo!() }
+/// `Interface ::= 'interface' '[' Signature (',' Signature)* ']'`
+fn parse_interface(input: &mut Input, state: State) -> Result<Type> { todo!() }
+/// `Signature ::= Ident ('[' Ident (':' Type)? (',' Ident (':' Type)?)* ']')? ('(' Type (',' Type)* ')')? (':' Type)?`
+fn parse_signature(input: &mut Input, state: State) -> Result<Sig> { todo!() }
+
+/// `WrappedType ::= Type | ('[' Type ']')`
+fn parse_wrapped_type(input: &mut Input, state: State) -> Result<Type> {
+ 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<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_cond_branch(input: &mut Input, state: State) -> Result<CondBranch> { todo!() }
// lex, parse, expand, compile?