-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
35 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,62 +1,49 @@ | ||
# Saft | ||
|
||
Saft is my custom programming language. | ||
Saft is my custom programming language. The syntax has a high resemblence to | ||
rust and some concepts have carried over, such as block expressions and control | ||
flow expressions, and tail expressions being returned automatically. | ||
|
||
## Syntax | ||
## State of the language | ||
|
||
The syntax in Saft is very inspired by rust, but instead using the `:=` operator for declarations instead of the `let` keyword. | ||
Since Saft is not yet typed all types are omitted from declarations, parameters and return values. | ||
Currently saft has a lexer, parser, ir (with lowerer) and a bytecode back-end, | ||
which both compiles and interprets bytecode. I have added type annotations, but | ||
type inference and checking has not been implemented yet, so types do nothing | ||
at the moment. | ||
|
||
### EBNF | ||
## Examples | ||
|
||
``` | ||
program = { statement } | ||
statement = item | ||
| stmt , ';' | ||
item = fn | ||
fn = 'fn' , '(', [ Ident , {',' , Ident } ] ')' block | ||
stmt = 'return' , expr | ||
| declaration | ||
| expr | ||
Below is an example of the fibonacci function, implemented recursively. | ||
|
||
``` | ||
fn fib(i: int) -> int { | ||
if i < 2 { | ||
i | ||
} else { | ||
fib(i-1) + fib(i-2) | ||
} | ||
} | ||
``` | ||
|
||
declaration = Ident , ':=' , expr | ||
block = '{' , { statement } , [ expr ] '}' | ||
Here is the fibonacci function implemented with a loop. | ||
|
||
expr = p_none | ||
``` | ||
fn fib(n: int) -> int { | ||
if n == 0 { return 0; }; | ||
p_none = p_assign | ||
p_assign = p_or | p_assign , '=' , p_or | ||
p_or = p_and | p_or , 'or' , p_and | ||
p_and = p_eq | p_and , 'and' , p_eq | ||
p_eq = p_cmp | p_eq , ( '==' | '!=' ) , p_cmp | ||
p_cmp = p_term | p_cmp , ( '<' | '<=' | '>' | '>=' ) , p_term | ||
p_term = p_fac | p_term , ('+' | '-' ) , p_fac | ||
p_fac = p_unary | p_fac ( '*' | '-' ) , p_unary | ||
p_unary = p_exp | ( '-' | '!' ) , p_unary | ||
p_exp = p_call | p_call , '^' , p_exp | ||
p_call = p_primary | p_call , '(' [ expr { ',' expr } ] ')' | ||
p_primary = primary_expr | ||
let a = 0; | ||
let b = 1; | ||
primary_expr = Ident | ||
| Float | ||
| Integer | ||
| 'nil' | ||
| 'true' | ||
| 'false' | ||
| String | ||
| list | ||
| '(' , expr , ')' | ||
| 'break' , expr | ||
| 'loop' , expr , block | ||
| if | ||
loop { | ||
if n == 1 { | ||
break b; | ||
}; | ||
list = '[' [ expr { ',' , expr } ] ']' | ||
let c = a + b; | ||
a = b; | ||
b = c; | ||
if = 'if' , expr , block , [ 'else' , ( block | if ) ] | ||
n = n - 1; | ||
} | ||
} | ||
``` |