VPL Formal Grammar
Notation
This grammar uses simplified EBNF notation:
|: alternative*: zero or more+: one or more?: optional(): grouping"...": literal terminal
Lexemes
Keywords
STREAM EVENT TYPE LET VAR CONST FN CONFIG CONTEXT
IF ELSE ELIF MATCH FOR WHILE BREAK CONTINUE RETURN
FROM WHERE SELECT JOIN MERGE WINDOW AGGREGATE PARTITION_BY ORDER_BY LIMIT DISTINCT EMIT TO
PATTERN
TRUE FALSE NULL
AND OR NOT IN IS
TRY CATCH FINALLY RAISE
AS EXTENDS IMPORT EXPORT
INT FLOAT BOOL STR TIMESTAMP DURATIONOperators
+ - * / % **
== != < <= > >=
& | ^ ~ << >>
= += -= *= /= %=
. ?. ?? => ->
.. ..=Literals
INTEGER : [0-9]+
FLOAT : [0-9]+ '.' [0-9]+ ([eE] [+-]? [0-9]+)?
STRING : '"' [^"]* '"' | "'" [^']* "'"
DURATION : [0-9]+ ('ns' | 'us' | 'ms' | 's' | 'm' | 'h' | 'd')
TIMESTAMP : '@' ISO8601_DATE
IDENTIFIER : [a-zA-Z_][a-zA-Z0-9_]*Productions
Program
ebnf
program ::= statement*
statement ::= context_decl
| stream_decl
| event_decl
| type_decl
| var_decl
| fn_decl
| config_block
| import_stmtDeclarations
ebnf
context_decl ::= 'context' IDENTIFIER context_params?
context_params ::= '(' context_param (',' context_param)* ')'
context_param ::= 'cores' ':' '[' INTEGER (',' INTEGER)* ']'
stream_decl ::= 'stream' IDENTIFIER (':' type)? '=' stream_expr
| 'stream' IDENTIFIER 'from' IDENTIFIER
event_decl ::= 'event' IDENTIFIER ('extends' IDENTIFIER)? ':' NEWLINE INDENT field_decl+ DEDENT
type_decl ::= 'type' IDENTIFIER '=' type
var_decl ::= ('let' | 'var' | 'const') IDENTIFIER (':' type)? '=' expr
fn_decl ::= 'fn' IDENTIFIER '(' param_list? ')' ('->' type)? ':' block
field_decl ::= IDENTIFIER ':' type NEWLINE
param_list ::= param (',' param)*
param ::= IDENTIFIER ':' typeTypes
ebnf
type ::= primitive_type
| array_type
| map_type
| tuple_type
| optional_type
| stream_type
| IDENTIFIER
primitive_type ::= 'int' | 'float' | 'bool' | 'str' | 'timestamp' | 'duration'
array_type ::= '[' type ']'
map_type ::= '{' type ':' type '}'
tuple_type ::= '(' type (',' type)+ ')'
optional_type ::= type '?'
stream_type ::= 'Stream' '<' type '>'Stream Expressions
ebnf
stream_expr ::= stream_source stream_op*
stream_source ::= IDENTIFIER
| 'merge' '(' stream_list ')'
| 'join' '(' join_clause (',' join_clause)* ')'
stream_list ::= stream_decl (',' stream_decl)*
join_clause ::= stream_decl ('on' expr)?
stream_op ::= '.context' '(' IDENTIFIER ')'
| '.where' '(' expr ')'
| '.select' '(' select_list ')'
| '.window' '(' window_args ')'
| '.aggregate' '(' agg_list ')'
| '.partition_by' '(' expr ')'
| '.order_by' '(' order_list ')'
| '.limit' '(' expr ')'
| '.distinct' '(' expr? ')'
| '.map' '(' lambda ')'
| '.filter' '(' lambda ')'
| '.tap' '(' tap_args ')'
| '.emit' '(' emit_args? ')'
| '.to' '(' connector_target ')'
| '.pattern' '(' pattern_def ')'
| '.concurrent' '(' concurrent_args ')'
| '.process' '(' lambda ')'
| '.on_error' '(' lambda ')'
| '.collect' '(' ')'
| '.forecast' '(' forecast_args? ')'
window_args ::= expr (',' named_arg)*
concurrent_args ::= named_arg (',' named_arg)*
tap_args ::= named_arg (',' named_arg)*
emit_args ::= named_arg (',' named_arg)*
forecast_args ::= named_arg (',' named_arg)*
select_list ::= select_item (',' select_item)*
select_item ::= IDENTIFIER
| IDENTIFIER ':' expr
agg_list ::= agg_item (',' agg_item)*
agg_item ::= IDENTIFIER ':' agg_call
| agg_call
agg_call ::= IDENTIFIER '(' expr? ')'
order_list ::= order_item (',' order_item)*
order_item ::= expr ('asc' | 'desc')?Expressions
ebnf
expr ::= or_expr
or_expr ::= and_expr ('or' and_expr)*
and_expr ::= not_expr ('and' not_expr)*
not_expr ::= 'not' not_expr
| comparison
comparison ::= bitwise_or (comp_op bitwise_or)*
comp_op ::= '==' | '!=' | '<' | '<=' | '>' | '>=' | 'in' | 'not' 'in' | 'is'
bitwise_or ::= bitwise_xor ('|' bitwise_xor)*
bitwise_xor ::= bitwise_and ('^' bitwise_and)*
bitwise_and ::= shift ('&' shift)*
shift ::= additive (('<<' | '>>') additive)*
additive ::= multiplicative (('+' | '-') multiplicative)*
multiplicative ::= power (('*' | '/' | '%') power)*
power ::= unary ('**' power)?
unary ::= ('-' | '~') unary
| postfix
postfix ::= primary (postfix_op)*
postfix_op ::= '.' IDENTIFIER
| '?.' IDENTIFIER
| '[' expr ']'
| '[' expr? ':' expr? ']'
| '(' arg_list? ')'
primary ::= literal
| IDENTIFIER
| '(' expr ')'
| '[' expr_list? ']'
| '{' map_entries? '}'
| lambda
| if_expr
| match_expr
literal ::= INTEGER | FLOAT | STRING | DURATION | TIMESTAMP
| 'true' | 'false' | 'null'
lambda ::= IDENTIFIER '=>' expr
| '(' param_list? ')' '=>' expr
| '(' param_list? ')' '=>' block
if_expr ::= 'if' expr 'then' expr 'else' expr
match_expr ::= 'match' expr ':' NEWLINE INDENT match_arm+ DEDENT
match_arm ::= pattern '=>' expr NEWLINE
pattern ::= literal | IDENTIFIER | '_'
arg_list ::= arg (',' arg)*
arg ::= expr | named_arg
named_arg ::= IDENTIFIER ':' expr
expr_list ::= expr (',' expr)*
map_entries ::= map_entry (',' map_entry)*
map_entry ::= (STRING | IDENTIFIER) ':' exprBlocks and Control Flow
ebnf
block ::= NEWLINE INDENT statement+ DEDENT
| statement
statement ::= var_decl
| if_stmt
| match_stmt
| for_stmt
| while_stmt
| return_stmt
| break_stmt
| continue_stmt
| expr_stmt
if_stmt ::= 'if' expr ':' block ('elif' expr ':' block)* ('else' ':' block)?
for_stmt ::= 'for' IDENTIFIER 'in' expr ':' block
while_stmt ::= 'while' expr ':' block
return_stmt ::= 'return' expr?
break_stmt ::= 'break'
continue_stmt ::= 'continue'
expr_stmt ::= exprConfiguration
ebnf
config_block ::= 'config' ':' NEWLINE INDENT config_item+ DEDENT
config_item ::= IDENTIFIER ':' config_value NEWLINE
| IDENTIFIER ':' NEWLINE INDENT config_item+ DEDENT
config_value ::= literal | IDENTIFIER | '[' config_list ']' | '{' config_map '}'
config_list ::= config_value (',' config_value)*
config_map ::= config_entry (',' config_entry)*
config_entry ::= (STRING | IDENTIFIER) ':' config_valueForecast Parameters
ebnf
forecast_args ::= named_arg (',' named_arg)*
# Valid named arguments for .forecast():
# confidence: float — minimum probability threshold (default 0.5)
# horizon: duration — forecast time window (default = within duration)
# warmup: int — events before forecasting starts (default 100)
# max_depth: int — PST context depth (default 5)Enrichment Parameters
ebnf
enrich_op ::= '.enrich(' IDENTIFIER ',' enrich_params ')'
enrich_params ::= enrich_param (',' enrich_param)*
enrich_param ::= 'key' ':' expression
| 'fields' ':' '[' IDENTIFIER (',' IDENTIFIER)* ']'
| 'cache_ttl' ':' duration
| 'timeout' ':' duration
| 'fallback' ':' literal