Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions ast/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
use lexer::Lexeme;

#[derive(Debug, Clone, PartialEq)]
pub struct While {
pub expr: Box<Expr>,
pub var_loop: Box<Expr>,
}

impl While {
pub fn new(expr: Box<Expr>, var_loop: Box<Expr>) -> Self {
While { expr, var_loop }
}
}

#[derive(Debug, Clone, PartialEq)]
pub struct For {
pub expr: Box<Expr>,
Expand Down Expand Up @@ -283,6 +295,36 @@ impl TagDecl {
}
}

#[derive(Debug, Clone, PartialEq)]
pub struct EnumDecl {
pub visibility: Option<Lexeme>,
pub mutability: Lexeme,
pub identifier: Box<Expr>,
pub declarators: Vec<Box<Expr>>,
pub sig: Option<Box<Expr>>,
pub variant: Option<Box<Expr>>,
}

impl EnumDecl {
pub fn new(
visibility: Option<Lexeme>,
mutability: Lexeme,
identifier: Box<Expr>,
declarators: Vec<Box<Expr>>,
sig: Option<Box<Expr>>,
variant: Option<Box<Expr>>,
) -> Self {
EnumDecl {
visibility,
mutability,
identifier,
declarators,
sig,
variant,
}
}
}

#[derive(Debug, Clone, PartialEq)]
pub struct ErrorDecl {
pub visibility: Option<Lexeme>,
Expand Down Expand Up @@ -364,6 +406,23 @@ impl TraitDecl {
}
}

#[derive(Debug, Clone, PartialEq)]
pub struct CatchDecl {
pub args: Option<Vec<Box<Expr>>>,
pub ret_typ: Box<Expr>,
pub block: Box<Expr>,
}

impl CatchDecl {
pub fn new(args: Option<Vec<Box<Expr>>>, ret_typ: Box<Expr>, block: Box<Expr>) -> Self {
CatchDecl {
args,
ret_typ,
block,
}
}
}

#[derive(Debug, Clone, PartialEq)]
pub struct AnonFuncDecl {
pub args: Option<Vec<Box<Expr>>>,
Expand Down Expand Up @@ -617,6 +676,7 @@ pub enum Expr {
ArrayDecl(ArrayDecl),
Rest(Rest),
For(For),
While(While),
Match(Match),
Arm(Arm),
FileAll(FileAll),
Expand All @@ -634,12 +694,14 @@ pub enum Expr {
Symbol(Symbol),
SymbolDecl(Symbol),
AnonFuncDecl(AnonFuncDecl),
CatchDecl(CatchDecl),
FuncDecl(FuncDecl),
SelfDecl(SelfKeyword),
TraitDecl(TraitDecl),
StructDecl(StructDecl),
ErrorDecl(ErrorDecl),
TagDecl(TagDecl),
EnumDecl(EnumDecl),
InnerDecl(InnerDecl),
TopDecl(TopDecl),
Reassignment(Reassignment),
Expand Down
8 changes: 7 additions & 1 deletion bootstrap/token/lib.ty
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pub type TokenError = error
| InvalidToken
| UnexpectedEnd

pub type Token = tag
pub type Token = enum(u8) {
| Error
| Defer
| ErrDefer
Expand Down Expand Up @@ -77,6 +77,9 @@ pub type Token = tag
| TypeOf
| InstanceOf
| RangeOf
| Enum
| Try
| Catch
// end keywords
| Split
| Yield
Expand Down Expand Up @@ -215,6 +218,9 @@ const keywords: [[char]] = [
"typeof",
"instanceof",
"rangeof",
"enum",
"try",
"catch",
]

pub const get_next = fn(buf: &[char], len: *u32) TokenError!Token {
Expand Down
27 changes: 15 additions & 12 deletions ebnf.txt
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
// use this to test, and this must pass at all times
// https://bnfplayground.pauliankline.com/
<all> ::= (<top_decls>)*
<top_decl> ::= "pub "? ("const " | "let " | "type " | "impl ") <ident> (":" <signature>)? "= " (<trait> | <fn> | <struct> | <tag> | <import> | <error> | <reassign> | <expr>)
<all> ::= (<top_decl>)*
<top_decl> ::= "pub "? ("const " | "let " | "type " | "impl ") <ident> (":" <signature>)? " = " (<trait> | <fn> | <struct> | <tag> | <import> | <error> | <reassign> | <expr> | <enum>)
<import> ::= "import " <chars>
<trait> ::= "trait"
<signature> ::= <val_type> | ("const" | "let")? ("&" | "*")? ("[" <signature> "]" | <ident> ("." <ident>)* | <fn_type>)
<trait> ::= "trait " "{ " (<top_decl)* " }"
<signature> ::= <val_type> | ("&" | "*")? ("[" <signature> "]" | <ident> ("." <ident>)* | <fn_type>)
<fn_type> ::= "fn" "(" <type_args> ")" ("void" | <signature>)
<type_args> ::= (<type_arg> ("," <type_arg>)*)?
<type_arg> ::= ("self " (":" <signature>)?) | <signature>
<fn> ::= "fn " "(" <args>? ") " <block>
<struct> ::= "struct " "{ " <declarators>? "}"
<error> ::= "error " "{" "}"
<if> ::= "if " "(" <expr> ")" (<fn> | <block>) ("else " <expr>)?
<error> ::= "error " ("| " <ident>)+
<if> ::= "if " "(" <expr> ")" (<fn> | <block>) ("else if "(" <expr> ")" (<fn> | <block>))* ("else " ( <fn> | <block>))?
<for> ::= "for " "(" <expr> ")" (<fn> | <block>)
<while> ::= "while " "(" <expr> ")" (<fn> | <block>)
<match> ::= "match " "(" <expr> ")" "{ " <arm>+ "}"
<arm> ::= <expr> "=> " (<fn> | <block>)
<tag> ::= "tag " ("| " <ident> (":" <signature>)? ("=" <expr>)?)+
<tag> ::= "tag " ("| " <ident> (":" <signature>)?)+
<enum> ::= "enum" "(" <val_type> ")" ("| " <ident> ("=" <expr>)?)+
<declarators> ::= (<declarator>)*
<declarator> ::= "pub "? <ident> (":" <signature>)?
<args> ::= (<arg> ("," <arg>)*)?
<arg> ::= ("self " (": " <signature>)?) | <ident> (":" <signature>)?
<inner_decl> ::= ( "const " | "let ") <ident> (":" <signature>)? "= " <expr>
<reassign> ::= <access> ("= " <expr>)?
<block> ::= "{ " (<inner_decl> | <for> | <if> | <reassign>)* (<return> | <break>)? "}"
<block> ::= "{ " (<inner_decl> | <for> | <while> | <if> | <reassign>)* (<return> | <break>)? "}"
<return> ::= "return " <expr>?
<break> ::= "break " <expr>?
<expr> ::= <block> | <match> | <or>
Expand All @@ -31,10 +33,11 @@
<equality> ::= <cmp> (("!= " | "== ") <cmp>)*
<cmp> ::= <low_bin> ((">" | ">=" | "<" | "<=") <low_bin>)*
<low_bin> ::= <high_bin> (("+" | "-") <high_bin>)*
<high_bin> ::= <unary> (("*" | "/" | ".." | "%") <unary>)*
<unary> ::= (("!" | "-" | "&" | "*") <unary>) | <access>
<high_bin> ::= <unary> (("*" | "/" | ".." | "%" | "as") <unary>)*
<unary> ::= (("try" | "copy" | "clone" | "!" | "-" | "&" | "*") <unary>) | <access>
<array_decl> ::= "[" (<or> ("," <or>)*)? "]"
<access> ::= <terminal> ("?" | "!" | <struct_body> | <invoke> | <array_access> | <call> )*
<access> ::= <terminal> ("?" | <struct_body> | <invoke> | <array_access> | <call>)* <catch>?
<catch> ::= "catch" "(" <arg>? ")" <block>
<array_access> ::= "[" <expr> "]"
<invoke> ::= "." <ident>
<call> ::= "(" (<or> ("," <or>)*)? ")"
Expand All @@ -46,4 +49,4 @@
<chars> ::= "\"" [a-z]* "\""
<val_type> ::= "i32" | "u32" | "i64" | "u64" | "i16" | "u16" | "u8" | "i8" | "bit" | "f64" | "d64" | "f32" | "d32" | "d128" | "f128" | "isize" | "usize" | "char" | "bool" | "any" | "scalar" | "utf8" | "utf16" | "utf32" | "utf64" | "sized"
// illegal ebnf but actual implementation
<chars> ::= #[regex(r#""([^"\\]|\\t|\\u|\\n|\\")*""#)n
<chars> ::= #[regex(r#""([^"\\]|\\t|\\u|\\n|\\")*""#)]
85 changes: 79 additions & 6 deletions parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl<'s> Parser<'s> {
.xresult_or(|expr| result_expr!(Import, mutability, identifier, expr))
}

pub fn tag(
pub fn _tag(
&mut self,
visibility: Option<Lexeme>,
mutability: Lexeme,
Expand Down Expand Up @@ -82,6 +82,29 @@ impl<'s> Parser<'s> {
result_expr!(ErrorDecl, visibility, mutability, identifier, sig)
}

pub fn _enum(
&mut self,
visibility: Option<Lexeme>,
mutability: Lexeme,
identifier: Box<Expr>,
sig: Option<Box<Expr>>,
) -> ResultExpr {
let mut variants: Vec<Box<Expr>> = vec![];
let oparen = self.lexer.collect_if(Token::OParen);
let enum_type = self.val_type();
if oparen.is_some() {
let _ = self
.lexer
.collect_if(Token::CParen)
.xexpect_token(&self, "expected ')'".to_string())?;
}
while let Some(_) = self.lexer.collect_if(Token::Bar) {
let x = self.ident().xconvert_to_sym_decl()?;
variants.push(x);
}
result_expr!(EnumDecl, visibility, mutability, identifier, variants, sig, enum_type)
}

pub fn _struct(
&mut self,
visibility: Option<Lexeme>,
Expand Down Expand Up @@ -123,14 +146,16 @@ impl<'s> Parser<'s> {
Token::Import,
Token::Tag,
Token::Error,
Token::Enum,
]) {
match val.token {
Token::Struct => return self._struct(has_pub, mutability, identifier, sig),
Token::Func => return self._fn(has_pub, mutability, identifier, sig),
Token::Import => return self._import(mutability, identifier),
Token::Tag => return self.tag(has_pub, mutability, identifier, sig),
Token::Tag => return self._tag(has_pub, mutability, identifier, sig),
Token::Trait => return self._trait(has_pub, mutability, identifier, sig),
Token::Error => return self._error(has_pub, mutability, identifier, sig),
Token::Enum => return self._enum(has_pub, mutability, identifier, sig),
_ => panic!("type-lang error unreachable code hit"),
}
}
Expand Down Expand Up @@ -427,6 +452,26 @@ impl<'s> Parser<'s> {
let blk = self.block()?;
return bubble_expr!(For, x, blk);
}
pub fn _while(&mut self) -> ResultOptExpr {
let f = self.lexer.collect_if(Token::While);
if f.is_none() {
return Ok(None);
}
let _ = self
.lexer
.collect_if(Token::OParen)
.xexpect_token(&self, "expected '('".to_string())?;
let x = self.or()?;
let _ = self
.lexer
.collect_if(Token::CParen)
.xexpect_token(&self, "expected ')'".to_string())?;
if let Some(_fn) = self.anon_fn()? {
return bubble_expr!(While, x, _fn);
}
let blk = self.block()?;
return bubble_expr!(While, x, blk);
}
pub fn _for(&mut self) -> ResultOptExpr {
let f = self.lexer.collect_if(Token::For);
if f.is_none() {
Expand Down Expand Up @@ -461,7 +506,10 @@ impl<'s> Parser<'s> {
Some(x) => exprs.push(x),
None => match self._if()? {
Some(x) => exprs.push(x),
None => break,
None => match self._while()? {
Some(x) => exprs.push(x),
None => break,
},
},
},
},
Expand Down Expand Up @@ -641,9 +689,10 @@ impl<'s> Parser<'s> {
let lexeme = self.lexer.collect_of_if(&[
Token::Ampersand,
Token::Asterisk,
Token::Exclam,
Token::Dash,
Token::Copy,
Token::Clone,
Token::Try,
]);
if let Some(x) = lexeme {
let expr = self.unary();
Expand All @@ -658,21 +707,25 @@ impl<'s> Parser<'s> {
if let Some(x) = self.lexer.collect_of_if(&[
Token::Question,
Token::Period,
Token::Tilde,
Token::Try,
Token::OBracket,
Token::OParen,
Token::OBrace,
Token::Catch,
]) {
match x.token {
Token::Question => self.resolve_access(expr!(UndefBubble, prev)),
Token::Tilde => self.resolve_access(expr!(ErrBubble, prev)),
Token::Try => self.resolve_access(expr!(ErrBubble, prev)),
Token::Period => {
let ident = self
.ident()
.xconvert_to_result(&self, "expected identifier".to_string())?;

self.resolve_access(expr!(PropAccess, prev, ident))
}
Token::Catch => {
return self.catch().xconvert_to_result_opt();
}
Token::OBracket => {
let expr = self.array_access()?;
self.resolve_access(expr!(ArrayAccess, expr, prev))
Expand Down Expand Up @@ -732,6 +785,26 @@ impl<'s> Parser<'s> {
Ok(Some(prev))
}
}
pub fn catch(&mut self) -> ResultExpr {
let _ = self
.lexer
.collect_if(Token::OParen)
.xexpect_token(&self, "expected one of '('".to_string())?;
let args = self.arg()?;
let ret_type = self
.sig_union()
.xexpect_expr(&self, "expected catch return type".to_string())?;
let _ = self
.lexer
.collect_if(Token::CParen)
.xexpect_token(&self, "expected one of ')'".to_string())?;

let bl = self.block()?;
if args.is_some() {
return result_expr!(CatchDecl, Some(vec![args.unwrap()]), ret_type, bl);
}
return result_expr!(CatchDecl, None, ret_type, bl);
}
pub fn access(&mut self) -> ResultOptExpr {
let term = self.terminal()?;
if let Some(t) = term {
Expand Down
6 changes: 6 additions & 0 deletions todos.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
- data layout
- scopes
- Bar '|' ebnf doesn't match parser, update parser for every '|' syntax
- "all function declarations must have types in arguments." this can be changed to support deducing types at some point
- impl
- destructuring
- rework import
- make types typey instead of values "function declarations" tags, enums, etc.
6 changes: 6 additions & 0 deletions token/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ pub enum Token {
InstanceOf,
#[token("rangeof")]
RangeOf,
#[token("enum")]
Enum,
#[token("try")]
Try,
#[token("catch")]
Catch,

#[token("|>")]
Split,
Expand Down
Loading