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

compilation_unit
	::=	(import_declaration | global_declaration)*

compilation_unit_sync
	::=	TokenKind_Import
	|	global_declaration_sync

import_declaration
	::=	TokenKind_Import TokenKind_Literal

global_declaration
	::=	common_declaration
	|	namespace_declaration
	|	extension_declaration
	|	global_item_declaration
	|	';'

global_declaration_sync
	::=	common_declaration_sync
	|	item_declaration_sync
	|	TokenKind_Namespace
	|	TokenKind_Extension
	|	';'

doxy_comment
	::=	TokenKind_DoxyComment1
	|	TokenKind_DoxyComment2
	|	TokenKind_DoxyComment3
	|	TokenKind_DoxyComment4

common_declaration
	::=	using_declaration
	|	pragma_declaration
	|	named_type_specifier
	|	attribute_block

using_declaration
	::=	TokenKind_Using using_namespace_kind qualified_name_list ';'

pragma_declaration
	::=	TokenKind_Pragma '(' TokenKind_Identifier (',' (constant_integer_expr | TokenKind_Default) | ) ')'

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

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

common_declaration_sync
	::=	TokenKind_Using
	|	TokenKind_Pragma
	|	named_type_specifier_sync

named_type_specifier_sync
	::=	TokenKind_Enum
	|	TokenKind_BitFlagEnum
	|	TokenKind_Struct
	|	TokenKind_Union
	|	TokenKind_Class
	|	TokenKind_OpaqueClass
	|	TokenKind_DynamicLib

namespace_declaration
	::=	TokenKind_Namespace qualified_name TokenKind_Body

extension_declaration
	::=	TokenKind_Extension TokenKind_Identifier ':' type_name TokenKind_Body

global_item_declaration
	::=	normal_item_declaration
	|	special_void_method_declarator
	|	qualified_special_void_method_declaration

item_declaration_sync
	::=	declaration_specifier_sync
	|	special_void_method_declarator_sync

member_block_declaration
	::=	common_declaration
	|	friend_declaration
	|	access_declaration
	|	member_item_declaration
	|	setas_declaration
	|	';'

friend_declaration
	::=	TokenKind_Friend qualified_name_list ';'

access_declaration
	::=	access_specifier ':'

member_item_declaration
	::=	normal_item_declaration
	|	special_void_method_declarator

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

member_block_declaration_sync
	::=	common_declaration_sync
	|	item_declaration_sync
	|	TokenKind_Friend
	|	TokenKind_Public
	|	TokenKind_Protected
	|	TokenKind_SetAs
	|	';'

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

statement
	::=	compound_stmt
	|	expression_stmt
	|	if_stmt
	|	switch_stmt
	|	regex_switch_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
	::=	normal_item_declaration

catch_label
	::=	TokenKind_Catch ':'

finally_label
	::=	TokenKind_Finally ':'

nested_scope_label
	::=	TokenKind_NestedScope ':'

local_declaration_sync
	::=	common_declaration_sync
	|	statement_sync
	|	TokenKind_Catch
	|	TokenKind_Finally
	|	TokenKind_NestedScope

statement_sync
	::=	TokenKind_If
	|	TokenKind_Switch
	|	TokenKind_While
	|	TokenKind_Do
	|	TokenKind_For
	|	TokenKind_Break
	|	TokenKind_Continue
	|	TokenKind_Return
	|	TokenKind_Once
	|	TokenKind_Try
	|	TokenKind_Throw
	|	TokenKind_Unsafe
	|	TokenKind_Assert
	|	';'
	|	'{'

global_declaration_list
	::=	global_declaration*

member_block_declaration_list
	::=	member_block_declaration*

local_declaration_list
	::=	local_declaration*

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

constant_integer_expr
	::=	expression

setas_value
	::=	type_name
	|	TokenKind_Default

qualified_name_impl
	::=	TokenKind_Identifier ('.' TokenKind_Identifier)*

qualified_name_save_name
	::=	qualified_name

normal_item_declaration
	::=	declaration_specifier_list declarator_list

special_void_method_declarator
	::=	special_void_method_declarator_qualifier function_suffix special_void_method_declarator_terminator

qualified_special_void_method_declaration
	::=	declarator_list

declaration_specifier_list
	::=	declaration_specifier+

declarator_list
	::=	declarator declarator_list_terminator

qualified_special_void_method_declaration_rslv
	::=	(TokenKind_Identifier '.')* special_void_method_declarator_sync

special_void_method_declarator_sync
	::=	TokenKind_Construct
	|	TokenKind_StaticConstruct
	|	TokenKind_Destruct
	|	TokenKind_Set
	|	TokenKind_Operator

declaration_specifier_sync
	::=	storage_specifier_sync
	|	access_specifier_sync
	|	type_specifier_sync
	|	type_modifier_sync

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_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
	::=	TokenKind_Body
	|	curly_initializer_pass1_impl

curly_initializer_pass1_impl
	::=	'{' curly_initializer_pass1_item* '}'

curly_initializer_pass1_item
	::=	curly_initializer_pass1_impl
	|	any

expression_save_value
	::=	expression

expression
	::=	conditional_expr

expression_or_empty_list_save_list
	::=	expression_or_empty_list

expression_or_empty_list
	::=	expression (',' expression_or_empty)*
	|	',' expression_or_empty (',' expression_or_empty)*
	|	epsilon

conditional_expr
	::=	logical_or_expr ('?' conditional_expr ':' conditional_expr)?

expression_0
	::=	conditional_expr

expression_or_empty
	::=	conditional_expr
	|	epsilon

expression_list
	::=	expression (',' expression)*

constant_expr
	::=	conditional_expr

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
	|	TokenKind_Match

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

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
	|	cast_operator
	|	TokenKind_New new_operator_type new_operator_curly_initializer?

try_operator
	::=	TokenKind_Try unary_expr

cast_operator
	::=	TokenKind_Dynamic? '(' type_name ')' unary_expr

new_operator_type
	::=	type_name_impl
	|	new_operator_type_w_constructor

new_operator_curly_initializer
	::=	curly_initializer

cast_operator_rslv
	::=	TokenKind_Dynamic? '(' (type_specifier_sync | type_modifier_sync | qualified_type_name_rslv)

type_specifier_sync
	::=	TokenKind_Void
	|	TokenKind_Class
	|	TokenKind_AnyData
	|	TokenKind_Bool
	|	TokenKind_Int
	|	TokenKind_IntPtr
	|	TokenKind_Char
	|	TokenKind_Short
	|	TokenKind_Long
	|	TokenKind_Float
	|	TokenKind_Double

type_modifier_sync
	::=	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
	|	TokenKind_Async

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

new_operator_type_w_constructor
	::=	qualified_type_name TokenKind_Construct? '(' expression_or_empty_list ')'

qualified_type_name
	::=	basetype_qualified_name

primary_expr
	::=	'(' conditional_expr ')'
	|	literal
	|	TokenKind_BaseType
	|	TokenKind_Identifier
	|	TokenKind_This
	|	TokenKind_Integer
	|	TokenKind_Fp
	|	TokenKind_True
	|	TokenKind_False
	|	TokenKind_Null
	|	TokenKind_ReGroup
	|	TokenKind_Await expression
	|	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

literal_atom
	::=	TokenKind_Literal
	|	TokenKind_BinLiteral
	|	TokenKind_FmtLiteral expression TokenKind_FmtSpecifier?
	|	TokenKind_FmtLiteral TokenKind_FmtIndex
	|	TokenKind_FmtLiteral TokenKind_FmtSpecifier

curly_initializer_item
	::=	curly_initializer_named_item
	|	curly_initializer_indexed_item
	|	epsilon

curly_initializer_named_item
	::=	TokenKind_Identifier '=' (curly_initializer | expression)

curly_initializer_indexed_item
	::=	expression
	|	curly_initializer

compound_stmt
	::=	'{' local_declaration_list '}'

constructor_compound_stmt
	::=	'{' btm_construct_stmt* local_declaration_list '}'

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

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

btm_construct_name_rslv
	::=	TokenKind_Identifier '.' (TokenKind_Identifier '.')* TokenKind_Construct

expression_stmt
	::=	expression ';'

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

switch_stmt
	::=	TokenKind_Switch '(' expression ')' '{' switch_block_stmt_list '}'

regex_switch_stmt
	::=	TokenKind_Switch '(' expression (',' expression)? ')' '{' regex_switch_block_stmt_list '}'

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 expression? ';'

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

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

switch_stmt_sync
	::=	local_declaration_sync
	|	TokenKind_Case
	|	TokenKind_Default

switch_block_stmt_list
	::=	switch_block_stmt*

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

regex_switch_stmt_rslv
	::=	TokenKind_Switch '(' expression ','?

regex_switch_block_stmt_list
	::=	regex_switch_block_stmt*

regex_switch_block_stmt
	::=	TokenKind_Case regex_switch_case_literal ':'
	|	TokenKind_Default ':'
	|	local_declaration

regex_switch_case_literal
	::=	literal

for_stmt_condition
	::=	expression
	|	epsilon

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

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*

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

reactor_stmt_0
	::=	local_item_declaration
	|	TokenKind_OnEvent any any* reactor_compound_stmt_0
	|	any+

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

declaration_specifier
	::=	storage_specifier
	|	access_specifier
	|	type_specifier
	|	type_modifier

type_specifier
	::=	TokenKind_Void
	|	TokenKind_Class
	|	TokenKind_AnyData
	|	TokenKind_Bool
	|	TokenKind_Int
	|	TokenKind_IntPtr
	|	TokenKind_Char
	|	TokenKind_Short
	|	TokenKind_Long
	|	TokenKind_Float
	|	TokenKind_Double
	|	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
	|	TokenKind_Async

storage_specifier_sync
	::=	TokenKind_Typedef
	|	TokenKind_Alias
	|	TokenKind_Static
	|	TokenKind_ThreadLocal
	|	TokenKind_Abstract
	|	TokenKind_Virtual
	|	TokenKind_Override
	|	TokenKind_Mutable
	|	TokenKind_Disposable

access_specifier_sync
	::=	TokenKind_Public
	|	TokenKind_Protected

type_specifier_modifier
	::=	type_specifier
	|	type_modifier

property_template_specifier
	::=	TokenKind_Property '{' member_block_declaration_list '}'

basetype_qualified_name
	::=	TokenKind_BaseType
	|	TokenKind_BaseType '.' qualified_name_impl
	|	qualified_name_impl

declarator
	::=	declarator_prefix* declarator_name declarator_suffix* declarator_constructor?

declarator_list_terminator
	::=	declarator_w_curly_initializer
	|	declarator_wo_curly_initializer
	|	TokenKind_Body

declarator_name
	::=	declarator_qualifier ('.' declarator_qualifier)*

declarator_constructor
	::=	TokenKind_Construct? arg_list_pass1

special_void_method_declarator_qualifier
	::=	TokenKind_Construct
	|	TokenKind_StaticConstruct
	|	TokenKind_Destruct
	|	TokenKind_Set
	|	TokenKind_Operator operator_declarator_qualifier
	|	TokenKind_PostfixOperator postfix_operator_declarator_qualifier

special_void_method_declarator_terminator
	::=	';'
	|	TokenKind_Body

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

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

declarator_qualifier
	::=	TokenKind_Identifier
	|	TokenKind_Get
	|	special_void_method_declarator_qualifier

operator_declarator_qualifier
	::=	operator_name
	|	type_name
	|	'(' ')'
	|	TokenKind_Ellipsis
	|	TokenKind_Cdecl TokenKind_Ellipsis
	|	TokenKind_BindingOf

postfix_operator_declarator_qualifier
	::=	TokenKind_Inc
	|	TokenKind_Dec

operator_name
	::=	'~'
	|	'!'
	|	TokenKind_Inc
	|	TokenKind_Dec
	|	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 ']'

bitfield_suffix
	::=	':' TokenKind_Integer

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

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
	::=	(TokenKind_Enum | TokenKind_BitFlagEnum) TokenKind_Identifier? (':' type_name)? enum_block

struct_specifier
	::=	TokenKind_Dynamic? TokenKind_Struct TokenKind_Identifier? (':' type_name_list)? member_block

union_specifier
	::=	TokenKind_Dynamic? TokenKind_Union TokenKind_Identifier? member_block

class_specifier
	::=	(TokenKind_Class | TokenKind_OpaqueClass) TokenKind_Identifier (':' type_name_list)? member_block

library_specifier
	::=	TokenKind_DynamicLib TokenKind_Identifier ('{' member_block_declaration_list '}' | TokenKind_Body)

named_type_specifier_save_type
	::=	named_type_specifier

enum_block
	::=	'{' enum_const_list '}'
	|	TokenKind_Body

enum_const_list
	::=	enum_const (',' enum_const)*

enum_const
	::=	attribute_block? TokenKind_Identifier ('=' expression_pass1)?
	|	epsilon

enum_const_sync
	::=	','
	|	'}'

member_block
	::=	'{' member_block_declaration_list '}'
	|	TokenKind_Body

class_specifier_rslv
	::=	(TokenKind_Class | TokenKind_OpaqueClass) TokenKind_Identifier