11(* RIDDL Grammar in EBNF *)
2- (* Last updated: January 17 , 2026 *)
2+ (* Last updated: January 28 , 2026 *)
33(* This grammar is automatically included in the riddl language module *)
44(* and can be loaded from the classpath at: riddl/grammar/ebnf-grammar.ebnf *)
55
@@ -16,6 +16,10 @@ hexEscape = "\\x" digit digit [digit [digit [digit [digit [digit [digit]]]]]] ;
1616unicodeEscape = " \\u" digit digit digit digit ;
1717integer = [" +" | " -" ] digit {digit } ;
1818
19+ (* Readability Keywords - these are always optional *)
20+ is = [" is" | " are" | " :" | " =" ] ; (* optional readability word for definitions *)
21+ byAs = [" by" | " as" ] ; (* optional readability word for attribution *)
22+
1923(* Comments *)
2024comment = inline_comment | end_of_line_comment ;
2125inline_comment = " /*" {any_char_except_end_comment } " */" ;
@@ -29,30 +33,30 @@ root_include = "include" literal_string ;
2933bast_import = " import" literal_string ; (* path must end with .bast *)
3034
3135(* Module *)
32- module = " module" identifier " is " " {" {module_content | module_include }+ " }" [with_metadata ] ;
36+ module = " module" identifier is " {" {module_content | module_include }+ " }" [with_metadata ] ;
3337module_include = " include" literal_string ;
3438
3539(* Domain *)
36- domain = " domain" identifier " is " " {" domain_body " }" [with_metadata ] ;
40+ domain = " domain" identifier is " {" domain_body " }" [with_metadata ] ;
3741domain_body = domain_definitions | " ???" ;
3842domain_definitions = {domain_content }+ ;
3943domain_content = vital_definition_contents | author | context | domain | user | epic | saga | import_def | bast_import | domain_include | comment ;
4044import_def = " import" " domain" identifier " from" literal_string ;
4145domain_include = " include" literal_string ;
4246
4347(* Context *)
44- context = " context" identifier " is " " {" context_body " }" [with_metadata ] ;
48+ context = " context" identifier is " {" context_body " }" [with_metadata ] ;
4549context_body = context_definitions | " ???" ;
4650context_definitions = {context_definition }+ ;
4751context_definition = processor_definition_contents | entity | adaptor | group | saga | streamlet | projector | repository | connector | context_include | comment ;
4852context_include = " include" literal_string ;
4953
5054(* Entity *)
51- entity = " entity" identifier " is " " {" entity_body " }" [with_metadata ] ;
55+ entity = " entity" identifier is " {" entity_body " }" [with_metadata ] ;
5256entity_body = entity_definitions | " ???" ;
5357entity_definitions = {entity_content }+ ;
5458entity_content = processor_definition_contents | state | entity_include ;
55- state = " state" identifier (" of" | " is " ) type_ref [with_metadata ] ;
59+ state = " state" identifier (" of" | is ) type_ref [with_metadata ] ;
5660entity_include = " include" literal_string ;
5761
5862(* Processor Definition Contents *)
@@ -61,8 +65,8 @@ vital_definition_contents = type_def | comment ;
6165
6266(* Type Definition *)
6367type_def = def_of_type | def_of_type_kind_type ;
64- def_of_type = " type" identifier " is " type_expression [with_metadata ] ;
65- def_of_type_kind_type = aggregate_use_case identifier (scala_aggregate_definition | (" is " (aliased_type_expression | aggregation ))) [with_metadata ] ;
68+ def_of_type = " type" identifier is type_expression [with_metadata ] ;
69+ def_of_type_kind_type = aggregate_use_case identifier (scala_aggregate_definition | (is (aliased_type_expression | aggregation ))) [with_metadata ] ;
6670aggregate_use_case = " type" | " command" | " query" | " event" | " result" | " record" | " graph" | " table" ;
6771
6872(* Type Expressions *)
@@ -115,8 +119,8 @@ aliased_type_expression = [aggregate_use_case] path_identifier ;
115119scala_aggregate_definition = " (" {field [" ," ]} " )" ;
116120
117121(* Fields and Methods *)
118- field = identifier " is " field_type_expression [with_metadata ] ;
119- method = identifier " (" [arguments ] " )" " is " field_type_expression [with_metadata ] ;
122+ field = identifier is field_type_expression [with_metadata ] ;
123+ method = identifier " (" [arguments ] " )" is field_type_expression [with_metadata ] ;
120124arguments = {method_argument [" ," ]} ;
121125method_argument = identifier " :" field_type_expression ;
122126field_type_expression = cardinality (
@@ -126,7 +130,7 @@ field_type_expression = cardinality(
126130) ;
127131
128132(* Functions *)
129- function = " function" identifier " is " " {" function_body " }" [with_metadata ] ;
133+ function = " function" identifier is " {" function_body " }" [with_metadata ] ;
130134function_body = [func_input ] [func_output ] function_definitions ;
131135func_input = " requires" aggregation ;
132136func_output = " returns" aggregation ;
@@ -165,14 +169,14 @@ processor_ref = adaptor_ref | context_ref | entity_ref | projector_ref | reposit
165169any_interaction_ref = processor_ref | saga_ref | input_ref | output_ref | group_ref | user_ref ;
166170
167171(* Handlers *)
168- handler = " handler" identifier " is " " {" handler_body " }" [with_metadata ] ;
172+ handler = " handler" identifier is " {" handler_body " }" [with_metadata ] ;
169173handler_body = {" ???" | handler_contents } ;
170174handler_contents = {on_clause | comment } ;
171175on_clause = on_init_clause | on_other_clause | on_term_clause | on_message_clause ;
172- on_init_clause = " on init" " is " pseudo_code_block [with_metadata ] ;
173- on_other_clause = " on other" " is " pseudo_code_block [with_metadata ] ;
174- on_term_clause = " on term" " is " pseudo_code_block [with_metadata ] ;
175- on_message_clause = " on" message_ref [" from" [identifier " :" ] message_origins ] " is " pseudo_code_block [with_metadata ] ;
176+ on_init_clause = " on" " init" is pseudo_code_block [with_metadata ] ;
177+ on_other_clause = " on" " other" is pseudo_code_block [with_metadata ] ;
178+ on_term_clause = " on" " term" is pseudo_code_block [with_metadata ] ;
179+ on_message_clause = " on" message_ref [" from" [identifier " :" ] message_origins ] is pseudo_code_block [with_metadata ] ;
176180message_origins = inlet_ref | processor_ref | user_ref | epic_ref ;
177181
178182(* Statements *)
@@ -185,7 +189,7 @@ statement = when_statement | match_statement | send_statement | tell_statement |
185189entity_statement = statement | morph_statement | become_statement ;
186190
187191(* Control flow *)
188- when_statement = " when" literal_string " then" pseudo_code_block " end" ;
192+ when_statement = " when" literal_string " then" pseudo_code_block [ " else " pseudo_code_block ] " end" ;
189193match_statement = " match" literal_string " {" {match_case }+ [" default" " {" {statement } " }" ] " }" ;
190194match_case = " case" literal_string " {" {statement } " }" ;
191195
@@ -211,82 +215,82 @@ become_statement = "become" entity_ref "to" handler_ref ;
211215pseudo_code_block = " ???" | {statement } | " {" {statement } " }" ;
212216
213217(* Constants and Invariants *)
214- constant = " constant" identifier " is " type_expression " =" literal_string [with_metadata ] ;
215- invariant = " invariant" identifier " is " [literal_string ] [with_metadata ] ;
218+ constant = " constant" identifier is type_expression " =" literal_string [with_metadata ] ;
219+ invariant = " invariant" identifier is [literal_string ] [with_metadata ] ;
216220
217221(* Relationship *)
218- relationship = " relationship" identifier " to" processor_ref " as " relationship_cardinality [" label" " as " literal_string ] [with_metadata ] ;
222+ relationship = " relationship" identifier " to" processor_ref byAs relationship_cardinality [" label" byAs literal_string ] [with_metadata ] ;
219223relationship_cardinality = " 1:1" | " 1:N" | " N:1" | " N:N" ;
220224
221225(* Streamlet-related *)
222226streamlet = source | sink | flow | merge | split | router | void ;
223- source = " source" identifier " is " " {" streamlet_body " }" [with_metadata ] ;
224- sink = " sink" identifier " is " " {" streamlet_body " }" [with_metadata ] ;
225- flow = " flow" identifier " is " " {" streamlet_body " }" [with_metadata ] ;
226- merge = " merge" identifier " is " " {" streamlet_body " }" [with_metadata ] ;
227- split = " split" identifier " is " " {" streamlet_body " }" [with_metadata ] ;
228- router = " router" identifier " is " " {" streamlet_body " }" [with_metadata ] ;
229- void = " void" identifier " is " " {" streamlet_body " }" [with_metadata ] ;
227+ source = " source" identifier is " {" streamlet_body " }" [with_metadata ] ;
228+ sink = " sink" identifier is " {" streamlet_body " }" [with_metadata ] ;
229+ flow = " flow" identifier is " {" streamlet_body " }" [with_metadata ] ;
230+ merge = " merge" identifier is " {" streamlet_body " }" [with_metadata ] ;
231+ split = " split" identifier is " {" streamlet_body " }" [with_metadata ] ;
232+ router = " router" identifier is " {" streamlet_body " }" [with_metadata ] ;
233+ void = " void" identifier is " {" streamlet_body " }" [with_metadata ] ;
230234streamlet_body = {" ???" | streamlet_definition } ;
231235streamlet_definition = {inlet | outlet | streamlet_include | processor_definition_contents } ;
232236streamlet_include = " include" literal_string ;
233- inlet = " inlet" identifier " is " type_ref [with_metadata ] ;
234- outlet = " outlet" identifier " is " type_ref [with_metadata ] ;
235- connector = " connector" identifier " is " connector_definitions [with_metadata ] ;
237+ inlet = " inlet" identifier is type_ref [with_metadata ] ;
238+ outlet = " outlet" identifier is type_ref [with_metadata ] ;
239+ connector = " connector" identifier is connector_definitions [with_metadata ] ;
236240connector_definitions = [" (" " from" outlet_ref " to" inlet_ref " )" | " from" outlet_ref " to" inlet_ref ] ;
237241
238242(* Group-related *)
239- group = group_aliases identifier " is " " {" {" ???" | group_definitions } " }" [with_metadata ] ;
243+ group = group_aliases identifier is " {" {" ???" | group_definitions } " }" [with_metadata ] ;
240244group_definitions = {group | contained_group | shown_by | group_output | group_input | comment } ;
241- contained_group = " contains" identifier " as " group_ref [with_metadata ] ;
245+ contained_group = " contains" identifier byAs group_ref [with_metadata ] ;
242246group_output = output_aliases identifier presentation_aliases (literal_string | constant_ref | type_ref ) [output_definitions ] [with_metadata ] ;
243247group_input = input_aliases identifier acquisition_aliases type_ref [input_definitions ] [with_metadata ] ;
244- output_definitions = [" is " " {" {" ???" | (group_output | type_ref )} " }" ] ;
245- input_definitions = [" is " " {" {" ???" | group_input } " }" ] ;
248+ output_definitions = [is " {" {" ???" | (group_output | type_ref )} " }" ] ;
249+ input_definitions = [is " {" {" ???" | group_input } " }" ] ;
246250group_aliases = " group" | " page" | " pane" | " dialog" | " menu" | " popup" | " frame" | " column" | " window" | " section" | " tab" | " flow" | " block" ;
247251output_aliases = " output" | " document" | " list" | " table" | " graph" | " animation" | " picture" ;
248252input_aliases = " input" | " form" | " text" | " button" | " picklist" | " selector" | " item" ;
249253presentation_aliases = " presents" | " shows" | " displays" | " writes" | " emits" ;
250254acquisition_aliases = " acquires" | " reads" | " takes" | " accepts" | " admits" | " initiates" | " submits" | " triggers" | " activates" | " starts" ;
251255
252256(* Repository-related *)
253- repository = " repository" identifier " is " " {" repository_body " }" [with_metadata ] ;
257+ repository = " repository" identifier is " {" repository_body " }" [with_metadata ] ;
254258repository_body = {" ???" | repository_definitions } ;
255259repository_definitions = {processor_definition_contents | schema | repository_include } ;
256260repository_include = " include" literal_string ;
257- schema = " schema" identifier " is " schema_kind {data } {link } {index } [with_metadata ] ;
261+ schema = " schema" identifier is schema_kind {data } {link } {index } [with_metadata ] ;
258262schema_kind = " flat" | " relational" | " time-series" | " graphical" | " hierarchical" | " star" | " document" | " columnar" | " vector" | " other" ;
259- data = " of" identifier " as " type_ref ;
260- link = " link" identifier " as " field_ref " to" field_ref ;
263+ data = " of" identifier byAs type_ref ;
264+ link = " link" identifier byAs field_ref " to" field_ref ;
261265index = " index" " on" field_ref ;
262266
263267(* Adaptor-related *)
264- adaptor = " adaptor" identifier adaptor_direction context_ref " is " " {" adaptor_body " }" [with_metadata ] ;
268+ adaptor = " adaptor" identifier adaptor_direction context_ref is " {" adaptor_body " }" [with_metadata ] ;
265269adaptor_direction = " from" | " to" ;
266270adaptor_body = {" ???" | adaptor_contents } ;
267271adaptor_contents = {processor_definition_contents | handler | adaptor_include } ;
268272adaptor_include = " include" literal_string ;
269273
270274(* Projector-related *)
271- projector = " projector" identifier " is " " {" projector_body " }" [with_metadata ] ;
275+ projector = " projector" identifier is " {" projector_body " }" [with_metadata ] ;
272276projector_body = {" ???" | projector_definitions } ;
273277projector_definitions = {processor_definition_contents | updates | projector_include } ;
274278projector_include = " include" literal_string ;
275279updates = " updates" repository_ref ;
276280
277281(* Saga-related *)
278- saga = " saga" identifier " is " " {" saga_body " }" [with_metadata ] ;
282+ saga = " saga" identifier is " {" saga_body " }" [with_metadata ] ;
279283saga_body = [func_input ] [func_output ] {saga_definitions } ;
280284saga_definitions = {saga_step | inlet | outlet | function | term | saga_include | option } ;
281285saga_include = " include" literal_string ;
282- saga_step = " step" identifier " is " pseudo_code_block " reverted" [" by" ] pseudo_code_block [with_metadata ] ;
286+ saga_step = " step" identifier is pseudo_code_block " reverted" [" by" ] pseudo_code_block [with_metadata ] ;
283287
284288(* Epic-related *)
285- epic = " epic" identifier " is " " {" epic_body " }" [with_metadata ] ;
289+ epic = " epic" identifier is " {" epic_body " }" [with_metadata ] ;
286290epic_body = user_story {epic_definitions } ;
287291epic_definitions = {vital_definition_contents | use_case | shown_by | epic_include } ;
288292epic_include = " include" literal_string ;
289- use_case = " case" identifier " is " " {" user_story {" ???" | interactions } " }" [with_metadata ] ;
293+ use_case = " case" identifier is " {" user_story {" ???" | interactions } " }" [with_metadata ] ;
290294user_story = user_ref " wants" [" to" ] literal_string " so" [" that" ] literal_string ;
291295interactions = {interaction } ;
292296interaction = parallel_interactions | optional_interactions | sequential_interactions | step_interactions ;
@@ -300,17 +304,17 @@ direct_user_to_url = "direct" user_ref "to" http_url [with_metadata] ;
300304select_input_step = user_ref " selects" input_ref [with_metadata ] ;
301305take_input_step = " take" input_ref " from" user_ref [with_metadata ] ;
302306show_output_step = " show" output_ref " to" user_ref [with_metadata ] ;
303- self_processing_step = " for" any_interaction_ref " is " literal_string [with_metadata ] ;
307+ self_processing_step = " for" any_interaction_ref is literal_string [with_metadata ] ;
304308send_message_step = " send" message_ref " from" any_interaction_ref " to" processor_ref [with_metadata ] ;
305309arbitrary_step = " from" any_interaction_ref literal_string [" to" ] any_interaction_ref [with_metadata ] ;
306- vague_step = " is " literal_string literal_string literal_string [with_metadata ] ;
310+ vague_step = is literal_string literal_string literal_string [with_metadata ] ;
307311
308312(* User-related *)
309- user = " user" identifier " is " literal_string [with_metadata ] ;
313+ user = " user" identifier is literal_string [with_metadata ] ;
310314
311315(* Author-related *)
312- author = " author" identifier " is " " {" [(" ???" | (" name" " is " literal_string " email" " is " literal_string
313- [" organization" " is " literal_string ] [" title" " is " literal_string ] [" url" " is " http_url ]))] " }" [with_metadata ] ;
316+ author = " author" identifier is " {" [(" ???" | (" name" is literal_string " email" is literal_string
317+ [" organization" is literal_string ] [" title" is literal_string ] [" url" is http_url ]))] " }" [with_metadata ] ;
314318
315319(* URLs *)
316320http_url = (" http" | " https" ) " ://" host_string [" :" port_num ] " /" [url_path ] ;
@@ -321,13 +325,13 @@ url_path = {letter | digit | "-" | "_" | "." | "~" | "!" | "$" | "&" | "'" | "("
321325(* Metadata *)
322326with_metadata = [" with" " {" {" ???" | {meta_data }} " }" ] ;
323327meta_data = brief_description | description | term | option | author_ref | attachment | ulid_attachment | comment ;
324- brief_description = " briefly" [ " by " | " as " ] literal_string ;
325- description = " described" (( " by " | " as " ) doc_block | (" at" http_url ) | (" in" " file" literal_string )) ;
326- term = " term" identifier " is " doc_block ;
327- option = " option" [ " is " ] option_name [" (" {literal_string } " )" ] ;
328+ brief_description = " briefly" byAs literal_string ;
329+ description = " described" (byAs doc_block | (" at" http_url ) | (" in" " file" literal_string )) ;
330+ term = " term" identifier is doc_block ;
331+ option = " option" is option_name [" (" {literal_string } " )" ] ;
328332option_name = {lower_letter | digit | " _" | " -" } ;
329- attachment = " attachment" identifier " is " mime_type ((" in" " file" literal_string ) | (" as " literal_string )) ;
330- ulid_attachment = " attachment" " ULID" " is " literal_string ;
333+ attachment = " attachment" identifier is mime_type ((" in" " file" literal_string ) | (byAs literal_string )) ;
334+ ulid_attachment = " attachment" " ULID" is literal_string ;
331335doc_block = " {" {markdown_lines | literal_strings | " ???" } " }" | literal_string ;
332336markdown_lines = {markdown_line }+ ;
333337markdown_line = " |" {any_char_except_newline } ;
0 commit comments