mighty

The mighty programming language, compiler and tools (WIP)
Log | Files | Refs

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 } '"' ;