% SystemVerilog Grammar

This file contains a destilled version of the SystemVerilog grammar, which, as
it is layed out in the standard, is a mixture of both syntax and semantics.

# EXPRESSION
primary
primary assignment_operator expression => operator_assignment
unary_operator primary
"tagged" member_identifier [expression]  => tagged_union_expression
("++"|"--") expression                   => inc_or_dec_expression

expression binary_operator expression
expression "inside" "{" open_range_list "}"  => inside_expression
expression "matches" pattern                 => cond_predicate
expression "&&&" expression_or_cond_pattern  => cond_predicate
expression "?" expression ":" expression     => conditional_expression
expression ("++"|"--")                       => inc_or_dec_expression
expression "." identifier
expression "." "super"
expression "::" identifier
expression "[" range_expression "]"
expression "(" [list_of_arguments] ")"       => function_subroutine_call


# PRIMARY
"this"
"super"
"$"
"null"
"$root"
"$unit"
primary_literal
"{" "}" => empty_queue
"(" expression ")"
"(" expression ":" expression ":" expression ")"        => mintypmax_expression
"{" expression {"," expression} "}"                     => concatenation
"{" expression "{" expression {"," expression} "}" "}"  => multiple_concatenation
"{" ("<<"|">>") [slice_size] stream_concatenation "}"   => streaming_concatenation

## Ignored
casting_type "'" "(" expression ")" => cast
assignment_pattern_expression_type assignment_pattern   => assignment_pattern_expression


# RANGE EXPRESSION
expression
expression ":" expression          => range
expression ("+:"|"-:") expression  => indexed_range


# LIST OF PORTS
According to the standard, the formal syntax for both ANSI and non-ANSI module
ports is as follows:

	// header
	module_nonansi_header
		:= {attribute_instance} module_keyword [lifetime] module_identifier {package_import_declaration} [parameter_port_list] list_of_ports ";"
	module_ansi_header
		:= {attribute_instance} module_keyword [lifetime] module_identifier {package_import_declaration} [parameter_port_list] [list_of_port_declarations] ";"

	// non-ANSI style
	list_of_ports
		:= "(" port {"," port} ")"
	port
		:= [port_expression]
		:= "." port_identifier "(" [port_expression] ")"
	port_expression
		:= port_reference
		:= "{" port_reference {"," port_reference} "}"
	port_reference
		:= port_identifier constant_select

	// ANSI style
	list_of_port_declarations
		:= "(" [{attribute_instance} ansi_port_declaration {"," {attribute_instance} ansi_port_declaration}] ")"
	ansi_port_declaration
		:= [net_port_header | interface_port_header] port_identifier {unpacked_dimension} ["=" constant_expression]
		:= [variable_port_header] port_identifier {variable_dimension} ["=" constant_expression]
		:= [port_direction] "." port_identifier "(" [expression] ")"
	net_port_header
		:= [port_direction] net_port_type
	variable_port_header
		:= [port_direction] variable_port_type
	interface_port_header
		:= interface_identifier ["." modport_identifier]
		:= "interface" ["." modport_identifier]
	port_direction
		:= "input" | "output" | "inout" | "ref"
	net_port_type
		:= [net_type] data_type_or_implicit
	variable_port_type
		:= data_type
		:= "var" data_type_or_implicit

To maintain sanity, the ANSI and non-ANSI variants shall be collapsed into one,
and the verification that a list of declarations is provided in the ANSI case
shall be performed at a later stage, once the AST has been built.

	module_header
		:= {attribute_instance} module_keyword [lifetime] module_identifier {package_import_declaration} [parameter_port_list] [list_of_ports] ";"
	list_of_ports
		:= "(" [{attribute_instance} port {"," {attribute_instance} port}] ")"
	port
		:= [port_expression]
		:= [net_port_header | interface_port_header] port_identifier {unpacked_dimension} ["=" constant_expression]
		:= [variable_port_header] port_identifier {variable_dimension} ["=" constant_expression]
		:= [port_direction] "." port_identifier "(" [expression] ")"
	port_expression
		:= port_reference
		:= "{" port_reference {"," port_reference} "}"
	port_reference
		:= port_identifier constant_select
	net_port_header
		:= [port_direction] net_port_type
	variable_port_header
		:= [port_direction] variable_port_type
	interface_port_header
		:= interface_identifier ["." modport_identifier]
		:= "interface" ["." modport_identifier]
	port_direction
		:= "input" | "output" | "inout" | "ref"
	net_port_type
		:= [net_type] data_type_or_implicit
	variable_port_type
		:= data_type
		:= "var" data_type_or_implicit

Removing all sorts of semantics from the port syntax, postponing verification
interpretation to when the AST has been built, we arrive at the following
syntax. Also, support for attribute instances shall be dropped for now.

	module_header
		:= module_keyword [lifetime] module_identifier {package_import_declaration} [parameter_port_list] [list_of_ports] ";"
	list_of_ports
		:= "(" [port {"," port}] ")"
	port
		:= "{" port_reference {"," port_reference} "}"
		:= [port_direction] [port_header] port_identifier {"[" range_expression "]"} ["=" constant_expression]
		:= [port_direction] "." port_identifier "(" [expression] ")"
	port_reference
		:= port_identifier {"[" range_expression "]"}
	port_header
		:= [net_type | "var"] data_type_or_implicit
		:= (interface_identifier | "interface") ["." modport_identifier]  -> interface_port_header
	port_direction
		:= "input" | "output" | "inout" | "ref"
	net_type
		:= "supply0" | "supply1" | "tri" | "triand" | "trior" | "trireg" | "tri0" | "tri1" | "uwire" | "wire" | "wand" | "wor"

	port_with_first_class_types
		:= "{" expression {"," expression} "}"
		:= [port_direction] expression expression "=" expression  /* careful about precedence */
		:= [port_direction] "." identifier "(" [expression] ")"
