Jancy Grammar Reference

The present page provides the full Jancy grammar for reference purposes.

This listing is auto-generated from .llk files by Graco parser generator, and is basically the very same grammar being used by the Jancy compiler. All the actions, rule attributes and rule arguments removed for readability.

Non-terminals are named using lower-case C-style naming convention (e.g. global_declaration); character terminals are denoted as C char literals (e.g. ';'); non-char terminals have names starting with TokenKind_ prefix (e.g. TokenKind_Identifier).

Grammar Listing

lookahead = 2;

start
nullable
compilation_unit
	:	global_declaration*
	;

global_declaration
	:	common_declaration
	|	import_declaration
	|	namespace_declaration
	|	extension_declaration
	|	normal_item_declaration
	;

common_declaration
	:	using_declaration
	|	alignment_declaration
	|	named_type_specifier
	|	';'
	;

using_declaration
	:	TokenKind_Using using_namespace_kind qualified_name_list ';'
	;

alignment_declaration
	:	TokenKind_Alignment '='? alignment_value ';'
	|	TokenKind_Alignment '(' alignment_value ')'
	;

named_type_specifier
	:	enum_specifier
	|	struct_specifier
	|	union_specifier
	|	class_specifier
	|	library_specifier
	;

import_declaration
	:	TokenKind_Import TokenKind_Literal
	;

namespace_declaration
	:	TokenKind_Namespace qualified_name '{' global_declaration* '}'
	;

extension_declaration
	:	TokenKind_Extension TokenKind_Identifier ':' type_name '{' named_type_block_declaration* '}'
	;

start
normal_item_declaration
	:	item_declaration_w_specifier
	|	item_declaration_wo_specifier
	;

named_type_block_declaration
	:	common_declaration
	|	friend_declaration
	|	access_declaration
	|	normal_item_declaration
	|	setas_declaration
	;

friend_declaration
	:	TokenKind_Friend qualified_name_list ';'
	;

access_declaration
	:	access_specifier ':'
	;

setas_declaration
	:	TokenKind_SetAs '='? setas_value ';'
	|	TokenKind_SetAs '(' setas_value ')'
	;

local_declaration
	:	common_declaration
	|	statement
	|	local_item_declaration
	|	catch_label
	|	finally_label
	|	nested_scope_label
	;

statement
	:	compound_stmt
	|	expression_stmt
	|	if_stmt
	|	switch_stmt
	|	reswitch_stmt
	|	while_stmt
	|	do_stmt
	|	for_stmt
	|	break_stmt
	|	continue_stmt
	|	return_stmt
	|	once_stmt
	|	try_stmt
	|	throw_stmt
	|	unsafe_stmt
	|	assert_stmt
	;

local_item_declaration
	:	item_declaration_w_specifier
	|	item_declaration_wo_specifier
	;

catch_label
	:	TokenKind_Catch ':'
	;

finally_label
	:	TokenKind_Finally ':'
	;

nested_scope_label
	:	TokenKind_NestedScope ':'
	;

qualified_name
	:	qualified_name_impl
	;

type_name
	:	type_name_impl
	;

using_namespace_kind
	:	TokenKind_Namespace
	|	TokenKind_Extension
	;

qualified_name_list
	:	qualified_name (',' qualified_name)*
	;

access_specifier
	:	TokenKind_Public
	|	TokenKind_Protected
	;

alignment_value
	:	TokenKind_Integer
	|	TokenKind_Default
	;

setas_value
	:	type_name
	|	TokenKind_Default
	;

qualified_name_impl
	:	TokenKind_Identifier ('.' TokenKind_Identifier)*
	;

start
qualified_name_save_name
	:	qualified_name
	;

item_declaration_w_specifier
	:	declaration_specifier_list declarator_list
	;

item_declaration_wo_specifier_rslv
	:	declarator_qualifier ('.' declarator_qualifier)* '('
	;

item_declaration_wo_specifier
	:	declarator_list
	;

declaration_specifier_list
	:	declaration_specifier+
	;

declarator_list
	:	declarator declarator_list_terminator
	;

declarator_qualifier
	:	TokenKind_Identifier
	|	TokenKind_Get
	|	TokenKind_Set
	|	TokenKind_PreConstruct
	|	TokenKind_Construct
	|	TokenKind_Destruct
	|	TokenKind_Static TokenKind_Construct
	|	TokenKind_Static TokenKind_Destruct
	|	TokenKind_Operator declarator_operator_qualifier
	;

declaration_body_pass1
	:	compound_stmt_pass1
	;

compound_stmt_pass1
	:	'{' statement_pass1* '}'
	;

statement_pass1
	:	compound_stmt_pass1
	|	TokenKind_Catch
	|	TokenKind_Finally
	|	TokenKind_NestedScope
	|	TokenKind_Case
	|	TokenKind_Default
	|	any
	;

type_name_impl
	:	type_specifier_modifier_list declarator_prefix* declarator_suffix*
	;

type_specifier_modifier_list
	:	type_specifier_modifier+
	;

declarator_prefix
	:	'*' type_modifier*
	;

declarator_suffix
	:	array_suffix
	|	function_suffix
	|	bitfield_suffix
	;

type_name_list
	:	type_name (',' type_name)*
	;

attribute_block
	:	'[' attribute_declarator (',' attribute_declarator)* ']'
	;

nullable
attribute_declarator
	:	TokenKind_Identifier ('=' expression_pass1)?
	|	epsilon
	;

expression_pass1
	:	expression_pass1_item+
	;

expression_pass1_item
	:	'{' expression_pass1_item* '}'
	|	'[' expression_pass1_item* ']'
	|	'(' expression_pass1_item* ')'
	|	any
	;

arg_list_pass1
	:	'(' arg_list_pass1_item* ')'
	;

arg_list_pass1_item
	:	'(' arg_list_pass1_item* ')'
	|	any
	;

curly_initializer_pass1
	:	curly_initializer_pass1_impl
	;

curly_initializer_pass1_impl
	:	'{' curly_initializer_pass1_item* '}'
	;

curly_initializer_pass1_item
	:	curly_initializer_pass1_impl
	|	any
	;

start
expression_save_value
	:	expression
	;

start
expression
	:	conditional_expr
	;

start
nullable
expression_or_empty_list_save_list
	:	expression_or_empty_list
	;

nullable
expression_or_empty_list
	:	expression (',' expression_or_empty)*
	|	',' expression_or_empty (',' expression_or_empty)*
	|	epsilon
	;

conditional_expr
	:	logical_or_expr ('?' conditional_expr ':' conditional_expr)?
	;

nullable
expression_or_empty
	:	conditional_expr
	|	epsilon
	;

expression_list
	:	expression (',' expression)*
	;

start
constant_expr
	:	conditional_expr
	;

start
constant_integer_expr
	:	expression
	;

logical_or_expr
	:	logical_and_expr (TokenKind_LogOr logical_and_expr)*
	;

logical_and_expr
	:	inclusive_or_expr (TokenKind_LogAnd inclusive_or_expr)*
	;

inclusive_or_expr
	:	exclusive_or_expr ('|' exclusive_or_expr)*
	;

exclusive_or_expr
	:	and_expr ('^' and_expr)*
	;

and_expr
	:	equality_expr ('&' equality_expr)*
	;

equality_expr
	:	relational_expr (equality_operator relational_expr)*
	;

relational_expr
	:	shift_expr (relational_operator shift_expr)*
	;

equality_operator
	:	TokenKind_Eq
	|	TokenKind_Ne
	;

shift_expr
	:	additive_expr (shift_operator additive_expr)*
	;

relational_operator
	:	'<'
	|	'>'
	|	TokenKind_Le
	|	TokenKind_Ge
	;

additive_expr
	:	multiplicative_expr (additive_operator multiplicative_expr)*
	;

shift_operator
	:	TokenKind_Shl
	|	TokenKind_Shr
	;

multiplicative_expr
	:	at_expr (multiplicative_operator at_expr)*
	;

additive_operator
	:	'+'
	|	'-'
	;

at_expr
	:	assignment_expr ('@' assignment_expr)*
	;

multiplicative_operator
	:	'*'
	|	'/'
	|	'%'
	;

assignment_expr
	:	unary_expr assignment_operator_expr?
	;

unary_expr
	:	postfix_expr
	|	unary_operator_expr
	;

assignment_operator_expr
	:	assignment_operator conditional_expr
	|	'=' curly_initializer
	;

assignment_operator
	:	'='
	|	TokenKind_RefAssign
	|	TokenKind_AddAssign
	|	TokenKind_SubAssign
	|	TokenKind_MulAssign
	|	TokenKind_DivAssign
	|	TokenKind_ModAssign
	|	TokenKind_ShlAssign
	|	TokenKind_ShrAssign
	|	TokenKind_AndAssign
	|	TokenKind_XorAssign
	|	TokenKind_OrAssign
	;

start
curly_initializer
	:	'{' curly_initializer_item (',' curly_initializer_item)* '}'
	;

postfix_expr
	:	primary_expr postfix_operator*
	;

unary_operator_expr
	:	'+' unary_expr
	|	'-' unary_expr
	|	'~' unary_expr
	|	'&' unary_expr
	|	'*' unary_expr
	|	'!' unary_expr
	|	TokenKind_Inc unary_expr
	|	TokenKind_Dec unary_expr
	|	try_operator_expr
	|	TokenKind_Dynamic? '(' type_name ')' unary_expr
	|	TokenKind_New new_operator_type new_operator_curly_initializer?
	;

try_operator_expr
	:	TokenKind_Try unary_expr
	;

cast_operator_rslv
	:	TokenKind_Dynamic? '(' type_specifier_modifier
	;

new_operator_type
	:	type_name_impl
	|	qualified_type_name TokenKind_Construct? '(' expression_or_empty_list ')'
	;

new_operator_curly_initializer
	:	curly_initializer
	;

type_name_w_constructor_rslv
	:	qualified_name TokenKind_Construct? '('
	;

qualified_type_name
	:	basetype_qualified_name
	;

type_specifier_modifier
	:	type_specifier
	|	type_modifier
	;

primary_expr
	:	'(' conditional_expr ')'
	|	literal
	|	TokenKind_BaseType
	|	TokenKind_Identifier
	|	TokenKind_This
	|	TokenKind_Integer
	|	TokenKind_Fp
	|	TokenKind_True
	|	TokenKind_False
	|	TokenKind_Null
	|	TokenKind_SizeOf '(' type_name_or_expr ')'
	|	TokenKind_CountOf '(' type_name_or_expr ')'
	|	TokenKind_TypeOf '(' type_name_or_expr ')'
	|	TokenKind_Dynamic TokenKind_SizeOf '(' expression ')'
	|	TokenKind_Dynamic TokenKind_CountOf '(' expression ')'
	|	TokenKind_Dynamic TokenKind_TypeOf '(' expression ')'
	|	TokenKind_OffsetOf '(' expression_0 ')'
	|	TokenKind_BindingOf '(' conditional_expr ')'
	;

postfix_operator
	:	'(' expression_or_empty_list ')'
	|	'~' '(' expression_or_empty_list ')'
	|	'[' expression_or_empty ']'
	|	TokenKind_Inc
	|	TokenKind_Dec
	|	'.' member_operator
	|	TokenKind_Ptr member_operator
	;

member_operator
	:	TokenKind_Identifier
	|	TokenKind_Get
	|	TokenKind_Set
	;

literal
	:	literal_atom+
	;

type_name_or_expr
	:	type_name
	|	expression_0
	;

start
expression_0
	:	conditional_expr_0
	;

literal_atom
	:	TokenKind_Literal
	|	TokenKind_BinLiteral
	|	TokenKind_FmtLiteral expression TokenKind_FmtSpecifier?
	;

nullable
curly_initializer_item
	:	TokenKind_Identifier '=' (curly_initializer | expression)
	|	expression
	|	curly_initializer
	|	epsilon
	;

start
expression_save_value_0
	:	expression_0
	;

conditional_expr_0
	:	logical_or_expr_0 ('?' conditional_expr_0 ':' conditional_expr_0)?
	;

nullable
expression_or_empty_0
	:	conditional_expr_0
	|	epsilon
	;

expression_list_0
	:	expression_0 (',' expression_0)*
	;

nullable
expression_or_empty_list_0
	:	expression_0 (',' expression_or_empty_0)*
	|	',' expression_or_empty_0 (',' expression_or_empty_0)*
	|	epsilon
	;

logical_or_expr_0
	:	logical_and_expr_0 (TokenKind_LogOr logical_and_expr_0)*
	;

logical_and_expr_0
	:	inclusive_or_expr_0 (TokenKind_LogAnd inclusive_or_expr_0)*
	;

inclusive_or_expr_0
	:	exclusive_or_expr_0 ('|' exclusive_or_expr_0)*
	;

exclusive_or_expr_0
	:	and_expr_0 ('^' and_expr_0)*
	;

and_expr_0
	:	equality_expr_0 ('&' equality_expr_0)*
	;

equality_expr_0
	:	relational_expr_0 (equality_operator relational_expr_0)*
	;

relational_expr_0
	:	shift_expr_0 (relational_operator shift_expr_0)*
	;

shift_expr_0
	:	additive_expr_0 (shift_operator additive_expr_0)*
	;

additive_expr_0
	:	multiplicative_expr_0 (additive_operator multiplicative_expr_0)*
	;

multiplicative_expr_0
	:	at_expr_0 (multiplicative_operator at_expr_0)*
	;

at_expr_0
	:	assignment_expr_0 ('@' assignment_expr_0)*
	;

assignment_expr_0
	:	unary_expr_0 (assignment_operator conditional_expr_0)?
	;

unary_expr_0
	:	postfix_expr_0
	|	unary_operator_expr_0
	;

postfix_expr_0
	:	primary_expr_0 postfix_operator_0*
	;

unary_operator_expr_0
	:	'+' unary_expr_0
	|	'-' unary_expr_0
	|	'~' unary_expr_0
	|	'&' unary_expr_0
	|	'*' unary_expr_0
	|	'!' unary_expr_0
	|	TokenKind_Inc unary_expr_0
	|	TokenKind_Dec unary_expr_0
	|	TokenKind_Try unary_expr_0
	|	'(' type_name ')' unary_expr_0
	|	storage_specifier? TokenKind_New new_operator_sype_0
	;

storage_specifier
	:	TokenKind_Typedef
	|	TokenKind_Alias
	|	TokenKind_Static
	|	TokenKind_ThreadLocal
	|	TokenKind_Abstract
	|	TokenKind_Virtual
	|	TokenKind_Override
	|	TokenKind_Mutable
	|	TokenKind_Disposable
	;

new_operator_sype_0
	:	type_name
	|	qualified_type_name TokenKind_Construct? '(' expression_or_empty_list_0 ')'
	;

primary_expr_0
	:	'(' conditional_expr_0 ')'
	|	literal_0
	|	TokenKind_BaseType
	|	TokenKind_Identifier
	|	TokenKind_This
	|	TokenKind_Integer
	|	TokenKind_Fp
	|	TokenKind_True
	|	TokenKind_False
	|	TokenKind_Null
	|	TokenKind_Dynamic? TokenKind_SizeOf '(' type_name_or_expr_0 ')'
	|	TokenKind_Dynamic? TokenKind_CountOf '(' type_name_or_expr_0 ')'
	|	TokenKind_Dynamic? TokenKind_TypeOf '(' type_name_or_expr_0 ')'
	|	TokenKind_OffsetOf '(' expression_0 ')'
	|	TokenKind_BindingOf '(' conditional_expr_0 ')'
	;

postfix_operator_0
	:	'(' expression_or_empty_list_0 ')'
	|	'~' '(' expression_or_empty_list_0 ')'
	|	'[' expression_or_empty_0 ']'
	|	TokenKind_Inc
	|	TokenKind_Dec
	|	'.' member_operator_0
	|	TokenKind_Ptr member_operator_0
	;

member_operator_0
	:	TokenKind_Identifier
	|	TokenKind_Get
	|	TokenKind_Set
	;

literal_0
	:	literal_atom_0+
	;

type_name_or_expr_0
	:	type_name
	|	expression_0
	;

literal_atom_0
	:	TokenKind_Literal
	|	TokenKind_BinLiteral
	|	TokenKind_FmtLiteral expression_0 TokenKind_FmtSpecifier?
	;

start
compound_stmt
	:	'{' local_declaration* '}'
	;

start
constructor_compound_stmt
	:	'{' btm_construct_stmt* local_declaration* '}'
	;

btm_construct_stmt
	:	btm_construct_name '(' expression_or_empty_list ')'
	|	TokenKind_BaseType '.' TokenKind_Construct '(' expression_or_empty_list ')'
	|	';'
	;

btm_construct_stmt_rslv
	:	TokenKind_Identifier '.' (TokenKind_Identifier '.')* TokenKind_Construct
	;

btm_construct_name
	:	TokenKind_Identifier '.' (TokenKind_Identifier '.')* TokenKind_Construct
	;

start
expression_stmt
	:	expression ';'
	;

if_stmt
	:	TokenKind_If '(' expression ')' statement (TokenKind_Else statement)?
	;

switch_stmt
	:	TokenKind_Switch '(' expression ')' '{' switch_block_stmt* '}'
	;

reswitch_stmt
	:	TokenKind_ReSwitch '(' expression ',' expression (',' expression)? ')' '{' reswitch_block_stmt* '}'
	;

while_stmt
	:	TokenKind_While '(' expression ')' statement
	;

do_stmt
	:	TokenKind_Do statement TokenKind_While '(' expression ')'
	;

for_stmt
	:	TokenKind_For '(' (local_item_declaration | expression_or_empty_list ';') for_stmt_condition ';' expression_list? ')' statement
	;

break_stmt
	:	TokenKind_Break ';'
	;

continue_stmt
	:	TokenKind_Continue ';'
	;

return_stmt
	:	TokenKind_Return expression? ';'
	;

once_stmt
	:	storage_specifier? TokenKind_Once statement
	;

try_stmt
	:	TokenKind_Try '{' local_declaration* '}'
	;

throw_stmt
	:	TokenKind_Throw ';'
	;

unsafe_stmt
	:	TokenKind_Unsafe '{' local_declaration* '}'
	;

assert_stmt
	:	TokenKind_Assert '(' expression_pass1 (',' expression)? ')'
	;

switch_block_stmt
	:	TokenKind_Case constant_integer_expr ':'
	|	TokenKind_Default ':'
	|	local_declaration
	;

reswitch_block_stmt
	:	TokenKind_Case reswitch_case_literal ':'
	|	TokenKind_Default ':'
	|	local_declaration
	;

start
reswitch_case_literal
	:	literal
	;

nullable
for_stmt_condition
	:	expression
	|	epsilon
	;

start
reactor_body
	:	'{' (reactor_stmt | ';')* '}'
	;

reactor_stmt
	:	local_item_declaration
	|	expression_stmt
	|	reactor_onevent_stmt
	;

reactor_onevent_stmt
	:	TokenKind_OnEvent reactor_event_name function_suffix declaration_body_pass1
	;

reactor_event_name
	:	'(' expression_list ')'
	|	TokenKind_BindingOf '(' expression ')'
	|	any+
	;

function_suffix
	:	'(' function_formal_argument_list? ')' function_modifier*
	;

start
reactor_body_0
	:	'{' (reactor_stmt_0 | ';')* '}'
	;

reactor_stmt_0
	:	local_item_declaration
	|	expression_0 ';'
	|	reactor_onevent_stmt_0
	;

reactor_onevent_stmt_0
	:	TokenKind_OnEvent reactor_event_name_0 function_suffix reactor_compound_stmt_0
	;

reactor_event_name_0
	:	'(' expression_list_0 ')'
	|	TokenKind_BindingOf '(' expression_0 ')'
	|	any+
	;

reactor_compound_stmt_0
	:	'{' (reactor_compound_stmt_0 | any)* '}'
	;

declaration_specifier
	:	attribute_block
	|	storage_specifier
	|	access_specifier
	|	type_specifier
	|	type_modifier
	;

type_specifier
	:	TokenKind_Void
	|	TokenKind_Variant
	|	TokenKind_Class
	|	TokenKind_AnyData
	|	TokenKind_Bool
	|	TokenKind_Int
	|	TokenKind_IntPtr
	|	TokenKind_Char
	|	TokenKind_Short
	|	TokenKind_Long
	|	TokenKind_Float
	|	TokenKind_Double
	|	TokenKind_Auto
	|	property_template_specifier
	|	qualified_type_name
	;

type_modifier
	:	TokenKind_Unsigned
	|	TokenKind_BigEndian
	|	TokenKind_Const
	|	TokenKind_ReadOnly
	|	TokenKind_CMut
	|	TokenKind_Volatile
	|	TokenKind_Weak
	|	TokenKind_Thin
	|	TokenKind_Safe
	|	TokenKind_Unsafe
	|	TokenKind_Cdecl
	|	TokenKind_Stdcall
	|	TokenKind_Thiscall
	|	TokenKind_Jnccall
	|	TokenKind_Array
	|	TokenKind_Function
	|	TokenKind_Property
	|	TokenKind_Bindable
	|	TokenKind_AutoGet
	|	TokenKind_Indexed
	|	TokenKind_Multicast
	|	TokenKind_Event
	|	TokenKind_Reactor
	|	TokenKind_ErrorCode
	;

property_template_specifier
	:	TokenKind_Property named_type_block_impl
	;

qualified_type_name_rslv
	:	basetype_qualified_name ('(' | '[' | '=')?
	;

basetype_qualified_name
	:	TokenKind_BaseType
	|	TokenKind_BaseType '.' qualified_name_impl
	|	qualified_name_impl
	;

start
named_type_block_impl
	:	'{' named_type_block_declaration* '}'
	;

declarator
	:	declarator_prefix* declarator_name declarator_suffix* declarator_constructor?
	;

declarator_list_terminator
	:	declarator_w_curly_initializer
	|	declarator_wo_curly_initializer
	|	declaration_body_pass1
	;

declarator_name
	:	declarator_qualifier ('.' declarator_qualifier)*
	;

declarator_constructor
	:	TokenKind_Construct? arg_list_pass1
	;

declarator_w_curly_initializer
	:	'=' curly_initializer_pass1 (',' declarator_list)?
	;

declarator_wo_curly_initializer
	:	('=' expression_pass1)? (',' declarator_list | ';')
	;

declarator_operator_qualifier
	:	operator_name
	|	type_name
	|	'(' ')'
	|	TokenKind_Ellipsis
	|	TokenKind_Cdecl TokenKind_Ellipsis
	|	TokenKind_BindingOf
	;

operator_name
	:	'~'
	|	'!'
	|	TokenKind_Inc
	|	TokenKind_Dec
	|	TokenKind_Postfix TokenKind_Inc
	|	TokenKind_Postfix TokenKind_Dec
	|	TokenKind_Postfix? TokenKind_Ptr
	|	'+'
	|	'-'
	|	'*'
	|	'/'
	|	'%'
	|	TokenKind_Shl
	|	TokenKind_Shr
	|	'&'
	|	'^'
	|	'|'
	|	TokenKind_Eq
	|	TokenKind_Ne
	|	'<'
	|	TokenKind_Le
	|	'>'
	|	TokenKind_Ge
	|	'='
	|	TokenKind_RefAssign
	|	TokenKind_AddAssign
	|	TokenKind_SubAssign
	|	TokenKind_MulAssign
	|	TokenKind_DivAssign
	|	TokenKind_ModAssign
	|	TokenKind_ShlAssign
	|	TokenKind_ShrAssign
	|	TokenKind_AndAssign
	|	TokenKind_XorAssign
	|	TokenKind_OrAssign
	|	TokenKind_AtAssign
	|	TokenKind_LogAnd
	|	TokenKind_LogOr
	|	'[' ']'
	|	'@'
	;

array_suffix
	:	'[' ']'
	|	'[' expression_pass1 ']'
	;

function_suffix_rslv
	:	'(' ')'
	|	'(' TokenKind_Ellipsis ')'
	|	'(' (type_specifier | type_modifier)
	;

bitfield_suffix
	:	':' TokenKind_Integer
	;

function_formal_argument_list
	:	function_formal_argument (',' function_formal_argument)*
	;

function_modifier
	:	TokenKind_Const
	;

function_formal_argument
	:	declaration_specifier_list declarator_prefix* declarator_name? declarator_suffix* ('=' expression_pass1)?
	|	TokenKind_Ellipsis
	;

enum_specifier
	:	enum_modifier* TokenKind_Enum TokenKind_Identifier? (':' type_name)? enum_block
	;

struct_specifier
	:	TokenKind_Dynamic? TokenKind_Struct TokenKind_Identifier? (':' type_name_list)? named_type_block
	;

union_specifier
	:	TokenKind_Dynamic? TokenKind_Union TokenKind_Identifier? named_type_block
	;

class_specifier
	:	TokenKind_Opaque? TokenKind_Class TokenKind_Identifier (':' type_name_list)? named_type_block
	;

library_specifier
	:	TokenKind_DynamicLib TokenKind_Identifier '{' named_type_block_declaration* '}'
	;

start
named_type_specifier_save_type
	:	named_type_specifier
	;

enum_modifier
	:	TokenKind_Exposed
	|	TokenKind_BitFlag
	;

enum_block
	:	'{' enum_member (',' enum_member)* '}'
	;

nullable
enum_member
	:	TokenKind_Identifier ('=' expression_pass1)?
	|	epsilon
	;

named_type_block
	:	named_type_block_impl
	;