Skip to content

Grammar

Vow has no checked-in PEG/LALRPOP grammar. The authority is the hand-written recursive-descent Parser in the compiler. What follows is a readable sketch of that surface — enough to navigate the language, not a formal proof artifact.

comment ::= '//' … newline
ident ::= letter (letter | digit | '_')*
number ::= digit+ ('.' digit+)?
string ::= '"' (char | '\' escape | '${' expr '}')* '"'
keyword ::= fn | function | let | var | if | else | while | for | in
| match | switch | case | return | break | continue
| try | catch | new | static
| struct | class | enum | interface | import | pub | as | from
| open | extends | override
| needs | with | requires | ensures | result
| and | or | not | true | false | print | eprint
| test | assert | type | dyn | region
symbol ::= -> | => | :: | == | != | <= | >= | .. | ++ | --
| += | -= | *= | /= | ?? | ?. | ?
| + | - | * | / | % | = | < | > | …
program ::= item*
item ::= import_decl | type_alias | struct_decl | enum_decl
| interface_decl | function_decl | test_decl
function_decl ::= ('fn' | 'function') ident type_params? '(' params ')' '->' type
needs_clause* contract_clause* block
needs_clause ::= 'needs' cap_type
contract_clause ::= 'requires' expr | 'ensures' expr
struct_decl ::= 'open'? ('struct' | 'class') ident ('extends' ident)? '{' field* method* '}'
method ::= 'override'? 'fn' ident '(' 'self' (',' param)* ')' '->' type block
enum_decl ::= 'enum' ident '{' variant (',' variant)* '}'
interface ::= 'interface' ident '{' iface_method* '}'
type_alias ::= 'type' ident '=' type
import_decl ::= 'import' ident
| 'import' ident 'from' path
| 'import' path

Methods and interface methods use fn (not function). Interface methods may include a default body.

stmt ::= let_stmt | var_stmt | assign_stmt | incdec_stmt | if_stmt | while_stmt | for_stmt
| return_stmt | print_stmt | with_stmt | region_stmt | expr_stmt | assert_stmt
| break_stmt | continue_stmt | try_catch_stmt
try_catch_stmt ::= 'try' block 'catch' '(' ident ')' block
| 'try' expr 'catch' '(' ident ')' (block | expr)
let_stmt ::= 'let' ident (':' type)? '=' expr ';'?
var_stmt ::= 'var' ident (':' type)? '=' expr ';'?
incdec_stmt ::= ident ('++' | '--') ';'?
if_stmt ::= 'if' expr block ('else' block)? // no parens around expr
while_stmt::= 'while' expr block // no parens around expr
for_stmt ::= 'for' 'var' init ';' expr ';' update block
| 'for' ident 'in' range_or_expr block
range ::= add_expr '..' add_expr // for-in only (exclusive end)
update ::= ident ('++' | '--') | assign_tail
with_stmt ::= 'with' expr block
region_stmt ::= 'region' block
assert_stmt ::= 'assert' expr ';' // semicolon required today
expr ::= or_expr
or ::= and_expr ('or' and_expr)*
and ::= not_expr ('and' not_expr)*
not ::= 'not' not_expr | comparison
cmp ::= add (('=='|…|'>') add)?
add ::= mul (('+'|'-') mul)*
mul ::= postfix (('*'|'/'|'%') postfix)*
postfix::= primary (call | index | member | '?.' ident call? | '?' | '??' expr)*
primary::= literal | ident | match_expr | switch_expr | if_expr | try_expr | lambda_expr
| struct_lit | array_lit | new_expr | '(' expr ')' | unary_minus
new_expr ::= 'new' ident '(' args ')'
switch_expr ::= 'switch' expr '{' ('case' pattern ':' expr ',')+ '}'
try_expr ::= 'try' expr 'catch' '(' ident ')' expr
lambda_expr ::= '(' params ')' '->' expr
if_expr ::= 'if' expr block 'else' block

match is an expression:

match_expr ::= 'match' expr '{' arm (',' arm)* '}' // no parens around scrutinee
arm ::= pattern '=>' expr
type ::= 'dyn'? ident ('<' type (',' type)* '>')? | qualified_name

Common forms: int, int64, f32, f64, bool, String, Array<T>, Map<String,V>, Option<T>, Result<T, E>, Caps, capability types, dyn Shape.

  • Full pattern grammar (enum variants, _, bindings)
  • Method / interface desugaring into monomorphized functions
  • Builtin call lowering and capability insertion for needs / with
  • String interpolation interior grammar
  • Exact desugar of switchmatch and trymatch on Result