Skip to content

Commit 2c71ff9

Browse files
More syntax (#30)
* adding enum and others * todo is up-to-date * updated syntax
1 parent d4c5ae5 commit 2c71ff9

File tree

6 files changed

+175
-19
lines changed

6 files changed

+175
-19
lines changed

ast/src/lib.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
use lexer::Lexeme;
22

3+
#[derive(Debug, Clone, PartialEq)]
4+
pub struct While {
5+
pub expr: Box<Expr>,
6+
pub var_loop: Box<Expr>,
7+
}
8+
9+
impl While {
10+
pub fn new(expr: Box<Expr>, var_loop: Box<Expr>) -> Self {
11+
While { expr, var_loop }
12+
}
13+
}
14+
315
#[derive(Debug, Clone, PartialEq)]
416
pub struct For {
517
pub expr: Box<Expr>,
@@ -283,6 +295,36 @@ impl TagDecl {
283295
}
284296
}
285297

298+
#[derive(Debug, Clone, PartialEq)]
299+
pub struct EnumDecl {
300+
pub visibility: Option<Lexeme>,
301+
pub mutability: Lexeme,
302+
pub identifier: Box<Expr>,
303+
pub declarators: Vec<Box<Expr>>,
304+
pub sig: Option<Box<Expr>>,
305+
pub variant: Option<Box<Expr>>,
306+
}
307+
308+
impl EnumDecl {
309+
pub fn new(
310+
visibility: Option<Lexeme>,
311+
mutability: Lexeme,
312+
identifier: Box<Expr>,
313+
declarators: Vec<Box<Expr>>,
314+
sig: Option<Box<Expr>>,
315+
variant: Option<Box<Expr>>,
316+
) -> Self {
317+
EnumDecl {
318+
visibility,
319+
mutability,
320+
identifier,
321+
declarators,
322+
sig,
323+
variant,
324+
}
325+
}
326+
}
327+
286328
#[derive(Debug, Clone, PartialEq)]
287329
pub struct ErrorDecl {
288330
pub visibility: Option<Lexeme>,
@@ -364,6 +406,23 @@ impl TraitDecl {
364406
}
365407
}
366408

409+
#[derive(Debug, Clone, PartialEq)]
410+
pub struct CatchDecl {
411+
pub args: Option<Vec<Box<Expr>>>,
412+
pub ret_typ: Box<Expr>,
413+
pub block: Box<Expr>,
414+
}
415+
416+
impl CatchDecl {
417+
pub fn new(args: Option<Vec<Box<Expr>>>, ret_typ: Box<Expr>, block: Box<Expr>) -> Self {
418+
CatchDecl {
419+
args,
420+
ret_typ,
421+
block,
422+
}
423+
}
424+
}
425+
367426
#[derive(Debug, Clone, PartialEq)]
368427
pub struct AnonFuncDecl {
369428
pub args: Option<Vec<Box<Expr>>>,
@@ -617,6 +676,7 @@ pub enum Expr {
617676
ArrayDecl(ArrayDecl),
618677
Rest(Rest),
619678
For(For),
679+
While(While),
620680
Match(Match),
621681
Arm(Arm),
622682
FileAll(FileAll),
@@ -634,12 +694,14 @@ pub enum Expr {
634694
Symbol(Symbol),
635695
SymbolDecl(Symbol),
636696
AnonFuncDecl(AnonFuncDecl),
697+
CatchDecl(CatchDecl),
637698
FuncDecl(FuncDecl),
638699
SelfDecl(SelfKeyword),
639700
TraitDecl(TraitDecl),
640701
StructDecl(StructDecl),
641702
ErrorDecl(ErrorDecl),
642703
TagDecl(TagDecl),
704+
EnumDecl(EnumDecl),
643705
InnerDecl(InnerDecl),
644706
TopDecl(TopDecl),
645707
Reassignment(Reassignment),

bootstrap/token/lib.ty

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ pub type TokenError = error
22
| InvalidToken
33
| UnexpectedEnd
44

5-
pub type Token = tag
5+
pub type Token = enum(u8) {
66
| Error
77
| Defer
88
| ErrDefer
@@ -77,6 +77,9 @@ pub type Token = tag
7777
| TypeOf
7878
| InstanceOf
7979
| RangeOf
80+
| Enum
81+
| Try
82+
| Catch
8083
// end keywords
8184
| Split
8285
| Yield
@@ -215,6 +218,9 @@ const keywords: [[char]] = [
215218
"typeof",
216219
"instanceof",
217220
"rangeof",
221+
"enum",
222+
"try",
223+
"catch",
218224
]
219225

220226
pub const get_next = fn(buf: &[char], len: *u32) TokenError!Token {

ebnf.txt

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,30 @@
11
// use this to test, and this must pass at all times
22
// https://bnfplayground.pauliankline.com/
3-
<all> ::= (<top_decls>)*
4-
<top_decl> ::= "pub "? ("const " | "let " | "type " | "impl ") <ident> (":" <signature>)? "= " (<trait> | <fn> | <struct> | <tag> | <import> | <error> | <reassign> | <expr>)
3+
<all> ::= (<top_decl>)*
4+
<top_decl> ::= "pub "? ("const " | "let " | "type " | "impl ") <ident> (":" <signature>)? " = " (<trait> | <fn> | <struct> | <tag> | <import> | <error> | <reassign> | <expr> | <enum>)
55
<import> ::= "import " <chars>
6-
<trait> ::= "trait"
7-
<signature> ::= <val_type> | ("const" | "let")? ("&" | "*")? ("[" <signature> "]" | <ident> ("." <ident>)* | <fn_type>)
6+
<trait> ::= "trait " "{ " (<top_decl)* " }"
7+
<signature> ::= <val_type> | ("&" | "*")? ("[" <signature> "]" | <ident> ("." <ident>)* | <fn_type>)
88
<fn_type> ::= "fn" "(" <type_args> ")" ("void" | <signature>)
99
<type_args> ::= (<type_arg> ("," <type_arg>)*)?
1010
<type_arg> ::= ("self " (":" <signature>)?) | <signature>
1111
<fn> ::= "fn " "(" <args>? ") " <block>
1212
<struct> ::= "struct " "{ " <declarators>? "}"
13-
<error> ::= "error " "{" "}"
14-
<if> ::= "if " "(" <expr> ")" (<fn> | <block>) ("else " <expr>)?
13+
<error> ::= "error " ("| " <ident>)+
14+
<if> ::= "if " "(" <expr> ")" (<fn> | <block>) ("else if "(" <expr> ")" (<fn> | <block>))* ("else " ( <fn> | <block>))?
1515
<for> ::= "for " "(" <expr> ")" (<fn> | <block>)
16+
<while> ::= "while " "(" <expr> ")" (<fn> | <block>)
1617
<match> ::= "match " "(" <expr> ")" "{ " <arm>+ "}"
1718
<arm> ::= <expr> "=> " (<fn> | <block>)
18-
<tag> ::= "tag " ("| " <ident> (":" <signature>)? ("=" <expr>)?)+
19+
<tag> ::= "tag " ("| " <ident> (":" <signature>)?)+
20+
<enum> ::= "enum" "(" <val_type> ")" ("| " <ident> ("=" <expr>)?)+
1921
<declarators> ::= (<declarator>)*
2022
<declarator> ::= "pub "? <ident> (":" <signature>)?
2123
<args> ::= (<arg> ("," <arg>)*)?
2224
<arg> ::= ("self " (": " <signature>)?) | <ident> (":" <signature>)?
2325
<inner_decl> ::= ( "const " | "let ") <ident> (":" <signature>)? "= " <expr>
2426
<reassign> ::= <access> ("= " <expr>)?
25-
<block> ::= "{ " (<inner_decl> | <for> | <if> | <reassign>)* (<return> | <break>)? "}"
27+
<block> ::= "{ " (<inner_decl> | <for> | <while> | <if> | <reassign>)* (<return> | <break>)? "}"
2628
<return> ::= "return " <expr>?
2729
<break> ::= "break " <expr>?
2830
<expr> ::= <block> | <match> | <or>
@@ -31,10 +33,11 @@
3133
<equality> ::= <cmp> (("!= " | "== ") <cmp>)*
3234
<cmp> ::= <low_bin> ((">" | ">=" | "<" | "<=") <low_bin>)*
3335
<low_bin> ::= <high_bin> (("+" | "-") <high_bin>)*
34-
<high_bin> ::= <unary> (("*" | "/" | ".." | "%") <unary>)*
35-
<unary> ::= (("!" | "-" | "&" | "*") <unary>) | <access>
36+
<high_bin> ::= <unary> (("*" | "/" | ".." | "%" | "as") <unary>)*
37+
<unary> ::= (("try" | "copy" | "clone" | "!" | "-" | "&" | "*") <unary>) | <access>
3638
<array_decl> ::= "[" (<or> ("," <or>)*)? "]"
37-
<access> ::= <terminal> ("?" | "!" | <struct_body> | <invoke> | <array_access> | <call> )*
39+
<access> ::= <terminal> ("?" | <struct_body> | <invoke> | <array_access> | <call>)* <catch>?
40+
<catch> ::= "catch" "(" <arg>? ")" <block>
3841
<array_access> ::= "[" <expr> "]"
3942
<invoke> ::= "." <ident>
4043
<call> ::= "(" (<or> ("," <or>)*)? ")"
@@ -46,4 +49,4 @@
4649
<chars> ::= "\"" [a-z]* "\""
4750
<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"
4851
// illegal ebnf but actual implementation
49-
<chars> ::= #[regex(r#""([^"\\]|\\t|\\u|\\n|\\")*""#)n
52+
<chars> ::= #[regex(r#""([^"\\]|\\t|\\u|\\n|\\")*""#)]

parser/src/lib.rs

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ impl<'s> Parser<'s> {
4949
.xresult_or(|expr| result_expr!(Import, mutability, identifier, expr))
5050
}
5151

52-
pub fn tag(
52+
pub fn _tag(
5353
&mut self,
5454
visibility: Option<Lexeme>,
5555
mutability: Lexeme,
@@ -82,6 +82,29 @@ impl<'s> Parser<'s> {
8282
result_expr!(ErrorDecl, visibility, mutability, identifier, sig)
8383
}
8484

85+
pub fn _enum(
86+
&mut self,
87+
visibility: Option<Lexeme>,
88+
mutability: Lexeme,
89+
identifier: Box<Expr>,
90+
sig: Option<Box<Expr>>,
91+
) -> ResultExpr {
92+
let mut variants: Vec<Box<Expr>> = vec![];
93+
let oparen = self.lexer.collect_if(Token::OParen);
94+
let enum_type = self.val_type();
95+
if oparen.is_some() {
96+
let _ = self
97+
.lexer
98+
.collect_if(Token::CParen)
99+
.xexpect_token(&self, "expected ')'".to_string())?;
100+
}
101+
while let Some(_) = self.lexer.collect_if(Token::Bar) {
102+
let x = self.ident().xconvert_to_sym_decl()?;
103+
variants.push(x);
104+
}
105+
result_expr!(EnumDecl, visibility, mutability, identifier, variants, sig, enum_type)
106+
}
107+
85108
pub fn _struct(
86109
&mut self,
87110
visibility: Option<Lexeme>,
@@ -123,14 +146,16 @@ impl<'s> Parser<'s> {
123146
Token::Import,
124147
Token::Tag,
125148
Token::Error,
149+
Token::Enum,
126150
]) {
127151
match val.token {
128152
Token::Struct => return self._struct(has_pub, mutability, identifier, sig),
129153
Token::Func => return self._fn(has_pub, mutability, identifier, sig),
130154
Token::Import => return self._import(mutability, identifier),
131-
Token::Tag => return self.tag(has_pub, mutability, identifier, sig),
155+
Token::Tag => return self._tag(has_pub, mutability, identifier, sig),
132156
Token::Trait => return self._trait(has_pub, mutability, identifier, sig),
133157
Token::Error => return self._error(has_pub, mutability, identifier, sig),
158+
Token::Enum => return self._enum(has_pub, mutability, identifier, sig),
134159
_ => panic!("type-lang error unreachable code hit"),
135160
}
136161
}
@@ -427,6 +452,26 @@ impl<'s> Parser<'s> {
427452
let blk = self.block()?;
428453
return bubble_expr!(For, x, blk);
429454
}
455+
pub fn _while(&mut self) -> ResultOptExpr {
456+
let f = self.lexer.collect_if(Token::While);
457+
if f.is_none() {
458+
return Ok(None);
459+
}
460+
let _ = self
461+
.lexer
462+
.collect_if(Token::OParen)
463+
.xexpect_token(&self, "expected '('".to_string())?;
464+
let x = self.or()?;
465+
let _ = self
466+
.lexer
467+
.collect_if(Token::CParen)
468+
.xexpect_token(&self, "expected ')'".to_string())?;
469+
if let Some(_fn) = self.anon_fn()? {
470+
return bubble_expr!(While, x, _fn);
471+
}
472+
let blk = self.block()?;
473+
return bubble_expr!(While, x, blk);
474+
}
430475
pub fn _for(&mut self) -> ResultOptExpr {
431476
let f = self.lexer.collect_if(Token::For);
432477
if f.is_none() {
@@ -461,7 +506,10 @@ impl<'s> Parser<'s> {
461506
Some(x) => exprs.push(x),
462507
None => match self._if()? {
463508
Some(x) => exprs.push(x),
464-
None => break,
509+
None => match self._while()? {
510+
Some(x) => exprs.push(x),
511+
None => break,
512+
},
465513
},
466514
},
467515
},
@@ -641,9 +689,10 @@ impl<'s> Parser<'s> {
641689
let lexeme = self.lexer.collect_of_if(&[
642690
Token::Ampersand,
643691
Token::Asterisk,
644-
Token::Exclam,
645692
Token::Dash,
646693
Token::Copy,
694+
Token::Clone,
695+
Token::Try,
647696
]);
648697
if let Some(x) = lexeme {
649698
let expr = self.unary();
@@ -658,21 +707,25 @@ impl<'s> Parser<'s> {
658707
if let Some(x) = self.lexer.collect_of_if(&[
659708
Token::Question,
660709
Token::Period,
661-
Token::Tilde,
710+
Token::Try,
662711
Token::OBracket,
663712
Token::OParen,
664713
Token::OBrace,
714+
Token::Catch,
665715
]) {
666716
match x.token {
667717
Token::Question => self.resolve_access(expr!(UndefBubble, prev)),
668-
Token::Tilde => self.resolve_access(expr!(ErrBubble, prev)),
718+
Token::Try => self.resolve_access(expr!(ErrBubble, prev)),
669719
Token::Period => {
670720
let ident = self
671721
.ident()
672722
.xconvert_to_result(&self, "expected identifier".to_string())?;
673723

674724
self.resolve_access(expr!(PropAccess, prev, ident))
675725
}
726+
Token::Catch => {
727+
return self.catch().xconvert_to_result_opt();
728+
}
676729
Token::OBracket => {
677730
let expr = self.array_access()?;
678731
self.resolve_access(expr!(ArrayAccess, expr, prev))
@@ -732,6 +785,26 @@ impl<'s> Parser<'s> {
732785
Ok(Some(prev))
733786
}
734787
}
788+
pub fn catch(&mut self) -> ResultExpr {
789+
let _ = self
790+
.lexer
791+
.collect_if(Token::OParen)
792+
.xexpect_token(&self, "expected one of '('".to_string())?;
793+
let args = self.arg()?;
794+
let ret_type = self
795+
.sig_union()
796+
.xexpect_expr(&self, "expected catch return type".to_string())?;
797+
let _ = self
798+
.lexer
799+
.collect_if(Token::CParen)
800+
.xexpect_token(&self, "expected one of ')'".to_string())?;
801+
802+
let bl = self.block()?;
803+
if args.is_some() {
804+
return result_expr!(CatchDecl, Some(vec![args.unwrap()]), ret_type, bl);
805+
}
806+
return result_expr!(CatchDecl, None, ret_type, bl);
807+
}
735808
pub fn access(&mut self) -> ResultOptExpr {
736809
let term = self.terminal()?;
737810
if let Some(t) = term {

todos.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11
- data layout
22
- scopes
3+
- Bar '|' ebnf doesn't match parser, update parser for every '|' syntax
4+
- "all function declarations must have types in arguments." this can be changed to support deducing types at some point
5+
- impl
6+
- destructuring
7+
- rework import
8+
- make types typey instead of values "function declarations" tags, enums, etc.

token/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,12 @@ pub enum Token {
150150
InstanceOf,
151151
#[token("rangeof")]
152152
RangeOf,
153+
#[token("enum")]
154+
Enum,
155+
#[token("try")]
156+
Try,
157+
#[token("catch")]
158+
Catch,
153159

154160
#[token("|>")]
155161
Split,

0 commit comments

Comments
 (0)