old-language.bnf (6207B)
---------- plan
5 scalar types: int float bool char str
arrays: T[]
structs
enums
methods
contracts: @pre @post @inv
expression functions with =
block functions with ::
match
conditional expression: x if cond else y
pipes: | f, | f(args), | [pred], | @(mapper)
drop for now:
block if/else
fixed-shape arrays
implicit whitespace arrays
bind-pipe
mutating methods
function overloading
standalone attributes
same-line block bodies
complex # shape semantics
note: pipe rules:
x | f // f(x)
x | f(a, b) // f(x, a, b)
x | [pred] // filter(x, pred)
x | @(mapper) // map(x, mapper)
------------------ ebnf
:: opens a layout block
indent enters the block
dedent exits the block
newline separates statements
; only separates statements on one line
= opens to a single expr line
note: the following is wrong about this
program = { top_decl } EOF ;
top_decl = mod_decl
| use_decl
| type_decl
| const_decl
| func_decl ;
mod_decl = "mod" path CLOSE ;
use_decl = "use" path CLOSE ;
path = ident { "." ident } ;
attr_decl = attr { NEWLINE attr } ;
attr = "@" ident expr ;
const_decl = "const" type ident "=" expr CLOSE ;
func_decl = { attr NEWLINE }
type ident "(" [ params ] ")" func_body ;
func_body = "=" expr CLOSE
| "::" block ;
params = param { "," param } ;
param = [ "mut" ] type ident
| [ "mut" ] "self" ;
type = base_type { array_suffix } ;
base_type = "int"
| "float"
| "bool"
| "char"
| "str"
| ident ;
array_suffix = "[]" ;
shape = int_lit { "," int_lit } ;
block = NEWLINE INDENT block_body DEDENT ;
block_body = { stmt stmt_sep } final_expr CLOSE ;
stmt_sep = NEWLINE | SEP ;
stmt = var_decl
| assign_stmt
| defer_stmt
| expr ;
var_decl = [ "mut" ] type ident "=" expr ;
assign_stmt = lvalue "=" expr ;
defer_stmt = "defer" expr ;
final_expr = expr ;
lvalue = ident
| postfix_expr "." ident
| postfix_expr "[" expr "]" ;
int main() ::
io.put("hello")
0;
// becomes
func_decl
block
stmt: io.put("hello")
final_expr: 0
CLOSE
type_decl = "type" ident "=" type_body CLOSE ;
type_body = struct_type
| enum_type
| type ;
struct_type = "struct" "::" NEWLINE INDENT
{ struct_item }
DEDENT ;
struct_item = field_decl
| method_decl
| attr_decl ;
field_decl = type ident stmt_sep ;
method_decl = { attr NEWLINE }
type ident "(" [ params ] ")" func_body ;
enum_type = "enum" "::" NEWLINE INDENT
{ enum_item }
DEDENT ;
enum_item = enum_case stmt_sep
| method_decl
| attr_decl ;
enum_case = ident [ "(" [ fields ] ")" ] ;
fields = field { "," field } ;
field = type ident ;
primary
postfix: call, index, field
prefix: -, !, #, +/, */, min/, max/, avg/
power: ^
multiplicative: *, /, %
additive: +, -
range: ..
comparison: == != < <= > >=
logical and
logical or
pipe: |
lambda: =>
ebnf
expr = lambda_expr ;
lambda_expr = pipe_expr
| ident "=>" expr ;
pipe_expr = logic_or_expr { "|" pipe_stage } ;
pipe_stage = "[" expr "]" (* filter: x | [pred] *)
| "@(" expr ")" (* map: x | @(f) *)
| ident "=>" expr (* bind: x | y => expr *)
| "." ident "(" [ args ] ")" (* method: x | .len() *)
| postfix_expr ; (* call: x | f or x | f(a) *)
logic_or_expr = logic_and_expr { "or" logic_and_expr } ;
logic_and_expr = compare_expr { "and" compare_expr } ;
compare_expr = range_expr { compare_op range_expr } ;
compare_op = "==" | "!=" | "<" | "<=" | ">" | ">=" ;
range_expr = add_expr [ ".." add_expr ] ;
add_expr = mul_expr { add_op mul_expr } ;
add_op = "+" | "-" ;
mul_expr = power_expr { mul_op power_expr } ;
mul_op = "*" | "/" | "%" ;
power_expr = prefix_expr [ "^" power_expr ] ;
prefix_expr = prefix_op prefix_expr
| postfix_expr ;
prefix_op = "-"
| "!"
| "#"
| "+/"
| "*/"
| "min/"
| "max/"
| "avg/" ;
postfix_expr = primary_expr { postfix_suffix } ;
postfix_suffix = call_suffix
| index_suffix
| field_suffix ;
call_suffix = "(" [ args ] ")" ;
args = expr { "," expr } ;
index_suffix = "[" index_expr "]" ;
index_expr = expr
| [ expr ] ".." [ expr ] ;
field_suffix = "." ident ;
primary_expr = literal
| ident
| array_lit
| if_expr
| match_expr
| "(" expr ")" ;
expr = lambda_expr ;
lambda_expr = if_expr
| ident "=>" expr ;
if_expr = pipe_expr [ "if" expr "else" if_expr ] ;
literal = int_lit
| float_lit
| bool_lit
| char_lit
| str_lit ;
bool_lit = "true" | "false" ;
array_lit = "[" [ expr { "," expr } ] "]"
| scalar_run ;
scalar_run = scalar_atom scalar_atom { scalar_atom } ;
scalar_atom = int_lit
| float_lit
| bool_lit
| char_lit
| str_lit ;
ident = letter { letter | digit | "_" } ;
int_lit = digit { digit } ;
float_lit = digit { digit } "." digit { digit } ;
char_lit = "'" char_body "'" ;
str_lit = '"' { str_char } '"' ;