mighty

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

commit 2bbd72bef870cf1eb1e211cf566dab8309711d43
parent 791321af39c8203340815bd2747ddc10163b3f2b
Author: keyle <keyle@capsule.org>
Date:   Sat, 16 May 2026 16:40:14 +1000

bnf stuff

Diffstat:
Mlanguage2.bnf | 160+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
1 file changed, 99 insertions(+), 61 deletions(-)

diff --git a/language2.bnf b/language2.bnf @@ -1,67 +1,105 @@ # Mighty language2 sketch grammar -# Layout produces INDENT/DEDENT after `::`. - -program ::= { top } -top ::= namespace | use | struct | function - -namespace ::= "ns" path -use ::= "use" path - -struct ::= "struct" Type "::" block(member) -member ::= field | function -field ::= type names -names ::= name { "," name } - -function ::= { pre } signature { where } body -pre ::= "pre" expr -where ::= "where" expr # may mention contextual `result` -signature ::= type name "(" [ params ] ")" -params ::= param { "," param } -param ::= type [ name ] -body ::= "=" expr | "::" block(stmt) - -stmt ::= binding | ret | expr -binding ::= type name "=" expr -ret ::= "ret" expr - -type ::= path { "[]" } -path ::= name { "." name } - -expr ::= conditional -conditional ::= pipe [ "if" expr "else" expr ] -pipe ::= reduce { "|" ( map | expr ) } -map ::= "@" "(" expr ")" # each: `.` is the current element -reduce ::= [ op "/" ] logic # +/xs, */xs, max/xs - -logic ::= compare { ( "and" | "or" ) compare } -compare ::= range { cmp range } -range ::= add [ ".." add ] -add ::= mul { ( "+" | "-" ) mul } -mul ::= pow { ( "*" | "/" ) pow } -pow ::= unary { "^" unary } -unary ::= [ "-" | "#" ] postfix # #xs is length/count - -postfix ::= atom { call | selector | "." name } -call ::= "(" [ args ] ")" -args ::= expr { "," expr } -selector ::= "[" [ selectors ] "]" # index, gather, mask, or filter expr -selectors ::= expr { [ "," ] expr } - -atom ::= literal | path | subject | array | "(" expr ")" -subject ::= "." [ name ] # current subject/self/element -array ::= "[" [ selectors ] "]" - -literal ::= int | float | string | "true" | "false" -op ::= "+" | "*" | "&" | "|" | "min" | "max" | name -cmp ::= "==" | "!=" | "<" | "<=" | ">" | ">=" - -block(x) ::= INDENT { x } DEDENT + +program ::= { nl | top nl } +nl ::= NEWLINE { NEWLINE } + +top ::= namespace | use | decl +namespace ::= "ns" path +use ::= "use" path +decl ::= [ "pub" ] ( struct | function | operator ) + +struct ::= "struct" Type [ generics ] "::" block(member) +member ::= field | decl +field ::= type names +names ::= name { "," name } + +function ::= { pre nl } signature { where_part } body +pre ::= "pre" expr +where_part ::= [ nl ] where +where ::= "where" constraint # may mention contextual `result` +signature ::= type name [ generics ] "(" [ params ] ")" +params ::= param { "," param } +param ::= type [ name ] +body ::= [ nl ] "=" ( expr | nl expr ) | "::" block(stmt) + +operator ::= "op" op [ generics ] "(" params ")" "->" type body + +stmt ::= binding | ret | expr +binding ::= type name "=" expr +ret ::= "ret" expr + +generics ::= "[" typevar { "," typevar } "]" +typevar ::= Type +constraint ::= expr | type_constraint +type_constraint ::= Type ":" trait { "+" trait } +trait ::= Type + +type ::= primary_type { type_suffix } +primary_type ::= path [ type_args ] | "(" types ")" +type_args ::= "[" type { "," type } "]" +types ::= type { "," type } +type_suffix ::= "[]" # slice/dynamic array + | "[" int_lit "]" # fixed array + | "?" # option: T? + | "!" type # result: T!E + +path ::= name { "." name } + +expr ::= conditional +conditional ::= pipe [ "if" expr "else" expr ] +pipe ::= scan { "|" ( map | expr ) } +map ::= "@" "(" expr ")" # each: `.` is the current element +scan ::= [ op "\\" ] reduce # +\xs, *\xs +reduce ::= [ op "/" ] logic # +/xs, */xs, max/xs + +logic ::= compare { ( "and" | "or" ) compare } +compare ::= range { cmp range } +range ::= add [ ".." [ add ] ] +add ::= mul { ( "+" | "-" ) mul } +mul ::= pow { ( "*" | "/" ) pow } +pow ::= unary { "^" unary } +unary ::= [ "-" | "#" ] postfix # #xs is length/count + +postfix ::= atom { call | selector | "." name } +call ::= "(" [ args ] ")" +args ::= expr { "," expr } +selector ::= "[" [ items ] "]" # index, gather, mask, or filter expr + +atom ::= literal | path | subject | array | record | "(" expr ")" +subject ::= "." [ name ] # current subject/self/element +array ::= "[" [ items ] "]" +items ::= expr { "," expr } +record ::= path "(" [ fields ] ")" +fields ::= field_value { "," field_value } +field_value ::= name ":" expr + +literal ::= int_lit | float_lit | string | "true" | "false" | "nil" +op ::= "+" | "*" | "&" | "|" | "min" | "max" | name +cmp ::= "==" | "!=" | "<" | "<=" | ">" | ">=" + +block(x) ::= INDENT { nl | x nl } DEDENT + +# Lexical sketch: name is an identifier, Type is a capitalized identifier. +# Comments run from // to end of line. # Selector semantics: -# xs[i] scalar index -# xs[is] gather by int[] indices -# xs[mask] compress by bool[] mask -# xs[.valid] filter by expression evaluated per element +# xs[i] scalar index +# xs[[0, 2]] gather by int[] indices +# xs[mask] compress by bool[] mask +# xs[.valid] filter by expression evaluated per element + +# Array literals use commas: [1, 2, 3], [true, false, true]. + +# Named record literals use Type(field: value): Vec2(x: 1.0, y: 2.0). + +# Ranges are half-open. Negative indices are relative to the end. +# xs[0..-1] selects from the first element up to, not including, the last. + +# Reductions over empty collections are invalid unless the operator has a +# defined identity. max/ and min/ require non-empty collections. + +# Values are passed by copy semantically. An implementation may pass by +# read-only reference when that is observationally identical. # `.` semantics: # In methods, `.` is the receiver. In free functions, `.` is the first argument.