anchor.diff:  cross_identifier : identifier ;
   
   ps_covergroup_identifier
  -	: package_scope? covergroup_identifier
  -	;
  +  : package_scope? covergroup_identifier
  +  ;
   
   // TODO not strictly correct
   c_identifier : identifier ;
  
positive.code: 
  parser grammar SVParser;
  options {
  	tokenVocab=SVLexer;
  }
  @header {
  	package com.github.misfornoyd.systemverilog.generated;
  }
  
  // TODO this is not according to the LRM grammar
  root_element
  	: TIMESCALE | package_import_declaration | description | EOF
  	;
  
  description
  	: attribute_instances package_item
  	| module_declaration
  	| interface_declaration
  	| program_declaration
  	| package_declaration
  	| attribute_instances bind_directive
  	// TODO udp_declaration
  	// TODO config_declaration
  	;
  
  // Note: LRM is wrong, can't have ; here
  bind_directive
  	: KW_BIND bind_target_scope (COLON bind_target_instance_list)? bind_instantiation
  	| KW_BIND bind_target_instance bind_instantiation
  	;
  
  bind_target_scope
  	: module_identifier
  	| interface_identifier
  	;
  
  bind_target_instance
  	: hierarchical_identifier constant_bit_select
  	;
  
  bind_target_instance_list
  	: bind_target_instance (COMMA bind_target_instance)*
  	;
  
  bind_instantiation
  	: program_instantiation
  	| module_instantiation
  	| interface_instantiation
  	| checker_instantiation
  	;
  
  program_instantiation
  	: program_identifier (parameter_value_assignment)? hierarchical_instance (COMMA hierarchical_instance)* SEMI
  	;
  
  interface_instantiation
  	: interface_identifier (parameter_value_assignment)? hierarchical_instance (COMMA hierarchical_instance)* SEMI
  	;
  
  module_instantiation
  	: module_identifier (parameter_value_assignment)? hierarchical_instance (COMMA hierarchical_instance)* SEMI
  	;
  
  // Note: the LRM has an optional block for list_of_port_connections, but that's
  // redundant since one of the alternatives is empty anyway.
  hierarchical_instance
  	: name_of_instance LPAREN list_of_port_connections RPAREN
  	;
  
  list_of_port_connections
  	: ordered_port_connection (COMMA ordered_port_connection)*
  	| named_port_connection (COMMA named_port_connection)*
  	;
  
  ordered_port_connection
  	: attribute_instances expression?
  	;
  
  named_port_connection
  	: attribute_instances DOT port_identifier (LPAREN expression? RPAREN)?
  	| attribute_instances DOT MUL
  	;
  
  class_declaration
  	: KW_VIRTUAL? KW_CLASS lifetime? class_identifier parameter_port_list?
  	class_inherit?
  	class_implement?
  	SEMI
  	class_body
  	KW_ENDCLASS (COLON class_identifier)?
  	;
  
  class_inherit
  	: KW_EXTENDS class_type (LPAREN list_of_arguments RPAREN)?
  	;
  
  class_implement
  	: KW_IMPLEMENTS interface_class_type (COMMA interface_class_type)*
  	;
  
  class_body
  	: class_item*
  	;
  
  class_item
  	: attribute_instances class_property
  	| attribute_instances class_method
  	| attribute_instances class_constraint
  	| attribute_instances class_declaration
  	| attribute_instances covergroup_declaration
  	| local_parameter_declaration SEMI
  	| parameter_declaration SEMI
  	| SEMI
  	;
  
  class_property
  	: property_qualifier* data_declaration
  	| KW_CONST class_item_qualifier* data_type const_identifier (EQ constant_expression)? SEMI
  	;
  
  class_method
  	: method_qualifier* function_declaration
  	| method_qualifier* task_declaration
  	| KW_PURE KW_VIRTUAL class_item_qualifier* method_prototype SEMI
  	| KW_EXTERN method_qualifier* method_prototype SEMI
  	| KW_EXTERN method_qualifier* class_constructor_prototype
  	;
  
  task_declaration
  	: KW_TASK lifetime? task_name_qualifier? task_identifier
  	  task_body_declaration
  	  KW_ENDTASK ( COLON task_identifier )?
  	;
  
  task_body_declaration
  	: SEMI task_body_no_arglist
  	| LPAREN tf_port_list? RPAREN SEMI task_body_arglist
  	;
  
  // Parameters specified in body instead of in parenthesized list
  // NOTE: see comment in function_body_arglist.
  task_body_no_arglist
  	: (tf_item_declaration | statement_or_null)*
  	;
  
  // Parameters specified in parenthesized list
  // NOTE: see comment in function_body_arglist.
  task_body_arglist
  	: (block_item_declaration | statement_or_null)*
  	;
  
  task_name_qualifier
  	: function_name_qualifier
  	;
  
  // [LRM]
  // When the implicit syntax is used, the return type is the same as if the implicit syntax had been
  // immediately preceded by the logic keyword. In particular, the implicit syntax can be empty, in which case
  // the return type is a logic scalar.
  function_declaration
  	: KW_FUNCTION lifetime? function_data_type_or_implicit function_name_qualifier? function_identifier
  	  function_body_declaration
  	  KW_ENDFUNCTION ( COLON function_identifier )?
  	;
  
  function_name_qualifier
  	: interface_identifier DOT
  	| (package_scope parameter_value_assignment?)? (class_identifier parameter_value_assignment? COLON2)+
  	;
  
  // [LRM]
  // A function declaration has the formal arguments either in parentheses (like ANSI C) or in declarations and
  // directions.
  function_body_declaration
  	: SEMI function_body_no_arglist
  	| LPAREN tf_port_list? RPAREN SEMI function_body_arglist
  	;
  
  // Parameters specified in body instead of in parenthesized list
  // NOTE: see comment in function_body_arglist.
  function_body_no_arglist
  	: (tf_item_declaration | function_statement_or_null)*
  	;
  
  // TODO this rule is specified thusly in the LRM grammar:
  //   function_body_arglist : block_item_declaration* function_statement_or_null*
  
negative.code: // or a statement. This is for now handled by relaxing the grammar to allow interleaved declarations and
  // statements. It is easier to check this requirement in the semantic phase.
  function_body_arglist
    : (block_item_declaration | function_statement_or_null)*
    ;
  
  tf_item_declaration
    : block_item_declaration
    | tf_port_declaration
    ;
  
  tf_port_declaration
    : attribute_instances tf_port_direction KW_VAR? data_type_or_implicit list_of_tf_variable_identifiers SEMI
    ;
  
  block_item_declaration
    : attribute_instances data_declaration
    | attribute_instances local_parameter_declaration SEMI
    | attribute_instances parameter_declaration SEMI
    | attribute_instances overload_declaration
    | attribute_instances let_declaration
    ;
  
  // TODO make sure we treat "a = b;" as an assignment statement rather than a vardecl with implicit type.
  // Otherwise we have an ambiguity between vardecl and assignment statement.
  variable_declaration
    : KW_CONST KW_VAR? lifetime? data_type_or_implicit list_of_variable_decl_assignments SEMI
    | KW_VAR lifetime? data_type_or_implicit list_of_variable_decl_assignments SEMI
    | lifetime data_type_or_implicit list_of_variable_decl_assignments SEMI
    | data_type list_of_variable_decl_assignments SEMI
    ;
  
  function_prototype
    : KW_FUNCTION function_data_type_or_implicit function_identifier ( LPAREN tf_port_list? RPAREN )?
    ;
  
  function_data_type_or_implicit
    : data_type_or_void | implicit_data_type
    ;
  
  class_constructor_prototype
    : KW_FUNCTION KW_NEW (LPAREN tf_port_list? RPAREN)? SEMI
    ;
  
  class_constraint
    : constraint_prototype
    | constraint_declaration
    ;
  
  constraint_prototype
    : constraint_prototype_qualifier? KW_STATIC? KW_CONSTRAINT constraint_identifier SEMI
    ;
  
  cover_cross
    : (cross_identifier COLON)? KW_CROSS list_of_cross_items (KW_IFF LPAREN expression RPAREN)? cross_body
    ;
  
  list_of_cross_items
    : cross_item COMMA cross_item (COMMA cross_item)*
    ;
  
  cross_item
    : cover_point_identifier
    | variable_identifier
    ;
  
  cross_body
    : LCURLY cross_body_item* RCURLY // NOTE: bug in spec, can't have ; here.
    | SEMI
    ;
  
  cross_body_item
    : function_declaration
    | bins_selection_or_option SEMI
    ;
  
  constraint_prototype_qualifier
    : KW_EXTERN | KW_PURE
    ;
  
  class_item_qualifier
    : KW_STATIC
    | KW_PROTECTED
    | KW_LOCAL
    ;
  
  property_qualifier
    : random_qualifier
    | class_item_qualifier
    ;
  
  method_qualifier
    : KW_PURE? KW_VIRTUAL
    | class_item_qualifier
    ;
  
  method_prototype
    : task_prototype
    | function_prototype
    ;
  
  constraint_declaration
    : KW_STATIC? KW_CONSTRAINT constraint_identifier constraint_block
    ;
  
  interface_class_type
    : ps_class_identifier parameter_value_assignment?
    ;
  
  list_of_arguments
    : expression? (COMMA expression?)* (COMMA DOT identifier LPAREN expression? RPAREN)*
    | DOT identifier LPAREN expression? RPAREN (COMMA DOT identifier LPAREN expression? RPAREN)*
    ;
  
  program_declaration
    : program_nonansi_header timeunits_declaration? program_body KW_ENDPROGRAM (COLON program_identifier)?
    | program_ansi_header timeunits_declaration? program_body KW_ENDPROGRAM (COLON program_identifier)?
    | attribute_instances KW_PROGRAM program_identifier LPAREN DOT MUL RPAREN SEMI timeunits_declaration? program_body KW_ENDPROGRAM (COLON program_identifier)?
    | KW_EXTERN program_nonansi_header
    | KW_EXTERN program_ansi_header
    ;
  
  // TODO skip program contents for now.
  program_body
    : (~KW_ENDPROGRAM)*?
    ;
  
  program_nonansi_header
    : attribute_instances KW_PROGRAM lifetime? program_identifier package_import_declaration* parameter_port_list? list_of_ports SEMI
    ;
  
  program_ansi_header
    : attribute_instances KW_PROGRAM lifetime? program_identifier package_import_declaration* parameter_port_list? list_of_port_declarations? SEMI
    ;
  
  package_declaration
    : attribute_instances KW_PACKAGE lifetime? package_identifier SEMI
      timeunits_declaration? package_item* KW_ENDPACKAGE ( COLON package_identifier )?
    ;
  
  package_item
    : package_or_generate_item_declaration
    ;
  
  package_or_generate_item_declaration
    : net_declaration
    | data_declaration
    | task_declaration
    | function_declaration
    | checker_declaration
    | dpi_import_export
    | extern_constraint_declaration
    | class_declaration
    | local_parameter_declaration SEMI
    | parameter_declaration SEMI
    | covergroup_declaration
    | overload_declaration
    | assertion_item_declaration
    | SEMI
    ;
  
  net_declaration
    : net_type (drive_strength | charge_strength)? (KW_VECTORED | KW_SCALARED)? data_type_or_implicit delay3? list_of_net_decl_assignments SEMI
    | net_type_identifier delay_control? list_of_net_decl_assignments SEMI
    | KW_INTERCONNECT implicit_data_type (HASH delay_value)? net_identifier unpacked_dimension* (COMMA net_identifier unpacked_dimension*)? SEMI
    ;
  
  extern_constraint_declaration
    : KW_STATIC? KW_CONSTRAINT class_scope constraint_identifier constraint_block
    ;
  
  list_of_net_decl_assignments
    : net_decl_assignment (COMMA net_decl_assignment)*
    ;
  
  net_decl_assignment
    : net_identifier unpacked_dimension* (EQ expression)?
    ;
  
  specify_block
    : KW_SPECIFY specify_item* KW_ENDSPECIFY
    ;
  
  specify_item
    : specparam_declaration
    | pulsestyle_declaration
    | showcancelled_declaration
    | path_declaration
    | system_timing_check
    ;
  
  pulsestyle_declaration
    : KW_PULSESTYLE_ONEVENT list_of_path_outputs SEMI
    | KW_PULSESTYLE_ONDETECT list_of_path_outputs SEMI
    ;
  
  showcancelled_declaration
    : KW_SHOWCANCELLED list_of_path_outputs SEMI
    | KW_NOSHOWCANCELLED list_of_path_outputs SEMI
    ;
  
  path_declaration
    : simple_path_declaration SEMI
    | edge_sensitive_path_declaration SEMI
    | state_dependent_path_declaration SEMI
    ;
  
  simple_path_declaration
    : parallel_path_description EQ path_delay_value
    | full_path_description EQ path_delay_value
    ;
  
  parallel_path_description
    : LPAREN specify_input_terminal_descriptor polarity_operator? EQ_GT specify_output_terminal_descriptor RPAREN
    ;
  
  full_path_description
    : LPAREN list_of_path_inputs polarity_operator? MUL_GT list_of_path_outputs RPAREN
    ;
  
  list_of_path_inputs
    : specify_input_terminal_descriptor (COMMA specify_input_terminal_descriptor)*
    ;
  
  list_of_path_outputs
    : specify_output_terminal_descriptor (COMMA specify_output_terminal_descriptor)*
    ;
  
  specify_input_terminal_descriptor
    : input_identifier (LSQUARE constant_range_expression RSQUARE)?
    ;
  
  specify_output_terminal_descriptor
    : output_identifier (LSQUARE constant_range_expression RSQUARE)?
    ;
  
  input_identifier
    : input_port_identifier
    | inout_port_identifier
    | interface_identifier DOT port_identifier
    ;
  
  output_identifier
    : output_port_identifier
    | inout_port_identifier
    | interface_identifier DOT port_identifier
    ;
  
  path_delay_value
    : list_of_path_delay_expressions
    | LPAREN list_of_path_delay_expressions RPAREN
    ;
  
  list_of_path_delay_expressions
    : t_path_delay_expression
    | trise_path_delay_expression COMMA tfall_path_delay_expression
    | trise_path_delay_expression COMMA tfall_path_delay_expression COMMA tz_path_delay_expression
    | t01_path_delay_expression COMMA t10_path_delay_expression COMMA t0z_path_delay_expression COMMA tz1_path_delay_expression COMMA t1z_path_delay_expression COMMA tz0_path_delay_expression
    | t01_path_delay_expression COMMA t10_path_delay_expression COMMA t0z_path_delay_expression COMMA tz1_path_delay_expression COMMA t1z_path_delay_expression COMMA tz0_path_delay_expression COMMA t0x_path_delay_expression COMMA tx1_path_delay_expression COMMA t1x_path_delay_expression COMMA tx0_path_delay_expression COMMA txz_path_delay_expression COMMA tzx_path_delay_expression
    ;
  
  t_path_delay_expression : path_delay_expression ;
  trise_path_delay_expression : path_delay_expression ;
  