aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/frontend/lex.rs6
-rw-r--r--src/frontend/parse.rs265
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!() }