/* eslint-disable-no-undef */
/* eslint-disable-no-unused-vars */
///
// @ts-check
'use strict';
const PREC = {
PARENT: 37, // () [] :: . Left Highest
UNARY: 36, // + - ! ~ & ~& | ~| ^ ~^ ^~ ++ -- (unary)
POW: 35, // ** Left
MUL: 34, // * / % Left
ADD: 33, // + - (binary) Left
SHIFT: 32, // << >> <<< >>> Left
RELATIONAL: 31, // < <= > >= inside dist Left
EQUAL: 30, // == != === !== ==? !=? Left
AND: 29, // & (binary) Left
XOR: 28, // ^ ~^ ^~ (binary) Left
OR: 27, // | (binary) Left
// The matches operator shall have higher precedence than the && and || operators
MATCHES: 26,
LOGICAL_AND: 25, // && Left
LOGICAL_OR: 24, // || Left
CONDITIONAL: 23, // ?: (conditional operator) Right
IMPLICATION: 22, // –> <–> Right
ASSIGN: 21, // = += -= *= /= %= &= ^= |= <<= >>= <<<= >>>= := :/ <= None
CONCAT: 20, // {} {{}} Concatenation Lowest
SPARENT: 19, // [* ] [= ] [-> ]
SHARP2: 18, // ## Left
throughout: 17, // throughout Right
within: 16, // within Left
intersect: 15, // intersect Left
nexttime: 14, // not, nexttime, s_nexttime
and: 13, // and Left
or: 12, // or Left
iff: 11, // iff Right
until: 10, // until, s_until, until_with, s_until_with, implies Right
INCIDENCE: 9, // |->, |=>, #-#, #=# Right
always: 8, // always, s_always, eventually, s_eventually, —
// if-else, case , accept_on, reject_on,
// sync_accept_on, sync_reject_on
};
/**
*
* @param {(Rule|string|RegExp)[]} rules
*
* @returns {ChoiceRule}
*/
function optseq(...rules) {
return optional(prec.left(seq(...rules)));
}
/**
*
* @param {(Rule|string|RegExp)[]} rules
*
* @returns {RepeatRule}
*/
function repseq(...rules) {
return repeat(prec.left(seq(...rules)));
}
/**
* Creates a rule to match one or more of the rules separated by the separator
*
* @param {string} separator - The separator to use.
* @param {Rule} rule
*
* @returns {PrecLeftRule}
*/
function sep1(separator, rule) {
return prec.left(seq(
rule,
repeat(prec.left(seq(separator, rule))),
));
}
/**
*
* @param {number} precedence
* @param {string} separator
* @param {Rule} rule
*
* @returns {PrecLeftRule}
*/
function psep1(precedence, separator, rule) {
return prec.left(precedence, seq(
rule,
repeat(prec.left(seq(separator, rule))),
));
}
/**
*
* @param {GrammarSymbols} $
* @param {number} prior
* @param {Rule|string} ops
*
* @returns {PrecLeftRule}
*/
function exprOp($, prior, ops) {
return prec.left(prior, seq($.expression, ops, repeat($.attribute_instance), $.expression));
}
/**
*
* @param {GrammarSymbols} $
* @param {number} prior
* @param {Rule|string} ops
*
* @returns {PrecLeftRule}
*/
function constExprOp($, prior, ops) {
return prec.left(prior, seq($.constant_expression, ops, repeat($.attribute_instance), $.constant_expression));
}
/**
*
* @param {string} command
*
* @returns {AliasRule}
*/
function directive(command) {
return alias(new RegExp('`' + command), 'directive_' + command);
}
/*
Verilog parser grammar based on IEEE Std 1800-2017.
*/
module.exports = grammar({
name: 'verilog',
conflicts: $ => [
[$.constant_primary, $.primary],
[$.implicit_class_handle, $.primary],
[$.param_expression, $.primary],
[$.primary, $.queue_dimension],
[$._checker_or_generate_item, $._module_common_item],
[$._checker_generate_item, $._module_common_item],
[$.dpi_function_import_property, $.dpi_task_import_property],
[$.checker_or_generate_item_declaration, $.package_or_generate_item_declaration],
[$._module_or_generate_item_declaration, $.checker_or_generate_item_declaration],
[$.interface_or_generate_item, $.module_or_generate_item],
[$.array_method_name, $.method_call_body],
[$.constraint_set, $.empty_unpacked_array_concatenation],
[$._non_port_interface_item, $.interface_declaration],
[$.non_port_program_item, $.program_declaration],
[$.list_of_port_declarations, $.list_of_ports],
[$.expression_or_dist, $.mintypmax_expression],
[$.class_constructor_declaration, $.implicit_class_handle],
[$.action_block, $.statement_or_null],
[$.ansi_port_declaration, $.port_reference],
[$.ansi_port_declaration, $.port],
[$.net_port_header1, $.variable_port_header],
[$._variable_dimension, $.ansi_port_declaration],
[$._non_port_module_item, $.module_declaration],
[$._expression_or_cond_pattern, $.tagged_union_expression],
[$._covergroup_expression, $.mintypmax_expression],
[$._covergroup_expression, $.concatenation],
[$.delay2, $.delay_control],
[$.delay3, $.delay_control],
[$.delay_control, $.param_expression],
[$.delay2, $.delay_control, $.param_expression],
[$.property_expr, $.property_spec],
[$.property_expr, $.sequence_expr],
[$.nonrange_select1, $.select1],
[$.class_method, $.constraint_prototype_qualifier],
[$.class_method, $.method_qualifier],
[$.bind_target_instance, $.bind_target_scope],
[$.class_type, $.package_scope],
[$._var_data_type, $.data_type_or_implicit1],
[$.list_of_port_identifiers, $.list_of_variable_identifiers],
[$.list_of_port_identifiers, $.list_of_variable_port_identifiers],
[$.class_type, $.data_type, $.tf_port_item1],
[$.class_type, $.data_type, $.interface_port_header, $.net_port_type1],
[$.class_type, $.data_type, $.net_port_type1],
[$._variable_dimension, $.list_of_port_identifiers],
[$._sequence_actual_arg, $.property_expr],
[$._hierarchical_event_identifier, $._sequence_identifier, $.event_control],
[$._hierarchical_event_identifier, $.event_control],
[$.let_list_of_arguments, $.sequence_list_of_arguments],
[$.input_identifier, $.output_identifier],
[$.constant_primary, $.path_delay_expression],
[$.scalar_timing_check_condition, $.unary_operator],
[$.mintypmax_expression, $.scalar_timing_check_condition],
[$.delayed_data, $.delayed_reference],
[$.list_of_arguments_parent, $.system_tf_call],
[$.class_item_qualifier, $.lifetime],
[$._property_qualifier, $.method_qualifier],
[$.class_property, $.data_type_or_implicit1],
[$.list_of_arguments_parent, $.mintypmax_expression],
[$.module_path_primary, $.tf_call],
[$._package_item, $.package_declaration],
[$.concurrent_assertion_item, $.deferred_immediate_assertion_item, $.generate_block_identifier],
[$.clockvar, $.variable_lvalue],
[$._seq_input_list, $.combinational_entry],
[$.constant_primary, $.primary],
[$.let_expression, $.primary],
[$.constant_primary, $.let_expression, $.primary],
[$.primary, $.tf_call],
[$.let_expression, $.primary, $.tf_call],
[$.constant_primary, $.let_expression, $.primary, $.tf_call],
[$.let_expression, $.primary, $.select_expression, $.tf_call],
[$.constant_primary, $.let_expression, $.primary, $.select_expression, $.tf_call],
[$.constant_primary, $.primary],
[$.primary, $.variable_lvalue],
[$.constant_primary, $.net_lvalue],
[$.net_lvalue, $.variable_lvalue],
[$.constant_primary, $.port_reference],
[$.let_expression, $.primary],
[$.constant_primary, $.let_expression, $.primary],
[$.let_expression, $.primary, $.variable_lvalue],
[$.constant_primary, $.let_expression, $.primary, $.variable_lvalue],
[$.primary, $.tf_call],
[$.primary, $.tf_call, $.variable_lvalue],
[$.net_lvalue, $.primary, $.tf_call, $.variable_lvalue],
[$.primary, $.sequence_instance, $.tf_call],
[$.net_lvalue, $.primary, $.sequence_instance, $.tf_call],
[$.let_expression, $.primary, $.tf_call],
[$.constant_primary, $.let_expression, $.primary, $.tf_call],
[$.let_expression, $.primary, $.tf_call, $.variable_lvalue],
[$.constant_primary, $.let_expression, $.primary, $.tf_call, $.variable_lvalue],
[$.let_expression, $.port_reference, $.primary, $.tf_call],
[$.constant_primary, $.let_expression, $.port_reference, $.primary, $.tf_call, $.variable_lvalue],
[$.constant_primary, $.generate_block_identifier],
[$.constant_primary, $.generate_block_identifier, $.primary, $.sequence_instance, $.tf_call],
[$.constant_primary, $.generate_block_identifier, $.primary, $.sequence_instance, $.tf_call, $.variable_lvalue],
[$.constant_primary, $.generate_block_identifier, $.port_reference, $.primary, $.sequence_instance, $.tf_call, $.variable_lvalue],
[$._sequence_identifier, $.let_expression],
[$._sequence_identifier, $.let_expression, $.primary],
[$._sequence_identifier, $.constant_primary, $.let_expression, $.primary],
[$._sequence_identifier, $.let_expression, $.primary, $.variable_lvalue],
[$._sequence_identifier, $.let_expression, $.sequence_instance, $.tf_call],
[$._sequence_identifier, $.let_expression, $.primary, $.sequence_instance, $.tf_call],
[$._sequence_identifier, $.constant_primary, $.let_expression, $.primary, $.sequence_instance, $.tf_call],
[$._sequence_identifier, $.generate_block_identifier, $.let_expression, $.primary, $.sequence_instance, $.tf_call],
[$._sequence_identifier, $.generate_block_identifier, $.let_expression, $.primary, $.sequence_instance, $.tf_call, $.variable_lvalue],
[$._sequence_identifier, $.generate_block_identifier, $.let_expression, $.net_lvalue, $.primary, $.sequence_instance, $.tf_call, $.variable_lvalue],
[$._assignment_pattern_expression_type, $.variable_lvalue],
[$._assignment_pattern_expression_type, $.let_expression, $.primary],
[$._assignment_pattern_expression_type, $.let_expression, $.primary, $.tf_call],
[$.list_of_arguments_parent, $.sequence_instance],
[$.let_expression, $.list_of_arguments_parent],
[$.let_expression, $.list_of_arguments_parent, $.sequence_instance],
[$.module_path_primary, $.primary],
[$.module_path_primary, $.tf_call],
[$.constant_primary, $.module_path_primary, $.tf_call],
[$.constant_primary, $.let_expression, $.module_path_primary, $.primary, $.tf_call],
[$.constant_primary, $.let_expression, $.module_path_primary, $.primary, $.tf_call, $.variable_lvalue],
[$.constant_primary, $.data_type],
[$.constant_primary, $.data_type, $.generate_block_identifier],
[$.constant_primary, $.data_type, $.generate_block_identifier, $.primary, $.sequence_instance, $.tf_call, $.variable_lvalue],
[$.class_type, $.data_type],
[$.class_type, $.constant_primary, $.data_type],
[$.class_type, $.data_type, $.let_expression, $.primary],
[$.class_type, $.constant_primary, $.data_type, $.let_expression, $.primary],
[$.class_type, $.data_type, $.let_expression, $.primary, $.tf_call],
[$.class_type, $.constant_primary, $.data_type, $.let_expression, $.primary, $.tf_call],
[$.let_expression, $.primary],
[$.primary, $.tf_call],
[$.primary, $.sequence_instance, $.tf_call],
[$.let_expression, $.primary, $.tf_call],
[$.let_expression, $.primary, $.terminal_identifier, $.tf_call],
[$._sequence_identifier, $.let_expression],
[$._sequence_identifier, $.let_expression, $.primary],
[$._sequence_identifier, $.let_expression, $.sequence_instance, $.tf_call],
[$._sequence_identifier, $.let_expression, $.primary, $.sequence_instance, $.tf_call],
[$._sequence_identifier, $.let_expression, $.sequence_instance, $.terminal_identifier, $.tf_call],
[$.net_lvalue, $.variable_lvalue],
[$._simple_type, $.constant_primary],
[$.constant_primary, $.primary],
[$.constant_primary, $.generate_block_identifier],
[$.interface_instantiation, $.program_instantiation],
[$.interface_instantiation, $.module_instantiation, $.program_instantiation],
[$.data_type, $.net_type_declaration],
[$.class_type, $.data_type],
[$.class_type, $.data_type, $.net_declaration],
[$.class_type, $.data_type, $.net_type_declaration],
[$.checker_instantiation, $.class_type, $.data_type],
[$.checker_instantiation, $.class_type, $.data_type, $.net_declaration],
[$.checker_instantiation, $.class_type, $.data_type, $.interface_port_declaration, $.net_declaration],
[$.checker_instantiation, $.class_type, $.data_type, $.interface_instantiation, $.net_declaration, $.program_instantiation],
[$.checker_instantiation, $.class_type, $.data_type, $.interface_instantiation, $.interface_port_declaration, $.net_declaration, $.program_instantiation],
[
$.checker_instantiation,
$.class_type,
$.data_type,
$.interface_instantiation,
$.module_instantiation,
$.net_declaration,
$.program_instantiation,
$.udp_instantiation,
],
[
$.checker_instantiation,
$.class_type,
$.data_type,
$.interface_instantiation,
$.interface_port_declaration,
$.module_instantiation,
$.net_declaration,
$.program_instantiation,
$.udp_instantiation,
],
[$.nonrange_variable_lvalue, $.variable_lvalue],
[$._method_call_root, $.class_qualifier],
[$._variable_dimension, $.variable_decl_assignment],
[$._variable_dimension, $.packed_dimension],
[$._variable_dimension, $.packed_dimension, $.variable_decl_assignment],
[$._simple_type, $.constant_primary],
[$._assignment_pattern_expression_type, $._simple_type, $.class_qualifier, $.constant_primary],
[$.constant_primary, $.data_type],
[$._assignment_pattern_expression_type, $._simple_type, $.class_qualifier, $.constant_primary, $.data_type],
[$.constant_select1, $.unpacked_dimension],
[$.packed_dimension, $.unpacked_dimension],
[$._constant_part_select_range, $.packed_dimension],
[$._constant_part_select_range, $.packed_dimension, $.unpacked_dimension],
[$._part_select_range, $.packed_dimension],
[$._part_select_range, $.packed_dimension, $.unpacked_dimension],
[$._constant_part_select_range, $._part_select_range],
[$._constant_part_select_range, $._part_select_range, $.packed_dimension],
[$.inout_port_identifier, $.input_port_identifier],
[$.inout_port_identifier, $.output_port_identifier],
[$.inout_port_identifier, $.input_port_identifier, $.output_port_identifier],
[$.checker_instantiation, $.named_port_connection],
[$.checker_instantiation, $.hierarchical_instance],
[$._sequence_actual_arg, $.event_expression],
[$.event_expression, $.expression_or_dist],
[$.event_expression, $.expression_or_dist, $.named_port_connection],
[$.event_expression, $.expression_or_dist, $.ordered_port_connection],
[$.event_expression, $.expression_or_dist, $.let_actual_arg],
[$.module_path_primary, $.primary],
[$.module_path_primary, $.primary_literal],
],
extras: $ => [/\s/, $.comment],
inline: $ => [
$.hierarchical_identifier,
$._hierarchical_net_identifier,
$._hierarchical_variable_identifier,
$._hierarchical_tf_identifier,
$._hierarchical_sequence_identifier,
$._hierarchical_property_identifier,
$._hierarchical_block_identifier,
$._hierarchical_task_identifier,
$.ps_or_hierarchical_net_identifier,
$.ps_or_hierarchical_tf_identifier,
$.ps_or_hierarchical_sequence_identifier,
$.ps_or_hierarchical_property_identifier,
$.ps_class_identifier,
$.ps_covergroup_identifier,
$.ps_parameter_identifier,
$.ps_type_identifier,
$.ps_checker_identifier,
$.parameter_identifier,
$.class_identifier,
$.covergroup_identifier,
$.enum_identifier,
$.formal_port_identifier,
$.genvar_identifier,
$.specparam_identifier,
$.tf_identifier,
$._type_identifier,
$._net_type_identifier,
$._variable_identifier,
$._udp_identifier,
$.package_identifier,
$.dynamic_array_variable_identifier,
$.class_variable_identifier,
$.interface_instance_identifier,
$.interface_identifier,
$._module_identifier,
$.let_identifier,
$._net_identifier,
$.program_identifier,
$.checker_identifier,
$.member_identifier,
$.port_identifier,
$._block_identifier,
$.instance_identifier,
$.property_identifier,
$.cover_point_identifier,
$.cross_identifier,
],
word: $ => $.simple_identifier,
rules: {
source_file: $ => repeat($._description),
/* 22. Compiler directives */
/* 22-1 `include */
double_quoted_string: $ => seq(
'"', token.immediate(prec(1, /[^\\"\n]+/)), '"',
),
include_compiler_directive_standard: $ => seq(
'<', token.immediate(prec(1, /[^\\>\n]+/)), '>',
),
include_compiler_directive: $ => seq(
directive('include'),
choice(
$.double_quoted_string,
$.include_compiler_directive_standard,
),
),
/* 22-2 `define */
default_text: $ => /\w+/,
macro_text: $ => /(\\(.|\r?\n)|[^\\\n])*/,
text_macro_name: $ => seq(
$.text_macro_identifier,
optseq('(', $.list_of_formal_arguments, ')'),
),
list_of_formal_arguments: $ => sep1(',', $.formal_argument),
formal_argument: $ => seq(
$.simple_identifier,
optseq('=', $.default_text),
),
text_macro_identifier: $ => $._identifier,
/* 22-5 define */
text_macro_definition: $ => seq(
directive('define'),
$.text_macro_name,
optional($.macro_text),
'\n',
),
/* 22-3 usage */
text_macro_usage: $ => seq(
'`',
$.text_macro_identifier,
optseq('(', $.list_of_actual_arguments, ')'),
),
simple_text_macro_usage: $ => seq(
'`',
$.text_macro_identifier,
),
/* 22-4 22-5 */
id_directive: $ => seq(
choice(
directive('ifdef'),
directive('ifndef'),
directive('elsif'),
directive('undef'), /* 22-5-2 */
),
$.text_macro_identifier,
),
zero_directive: $ => choice(
directive('resetall'), /* 22-3 */
directive('undefineall'), /* 22-5-3 */
directive('endif'),
directive('else'),
directive('nounconnected_drive'),
directive('celldefine'), /* 22-10 */
directive('endcelldefine'),
directive('end_keywords'), /* 22.14 */
),
/* 22-7 timescale */
timescale_compiler_directive: $ => seq(
directive('timescale'),
$.time_literal, // time_unit,
'/',
$.time_literal, // time_precision
'\n',
),
/* 22-8 default_nettype */
default_nettype_compiler_directive: $ => seq(
directive('default_nettype'),
$.default_nettype_value,
'\n',
),
default_nettype_value: $ => choice('wire', 'tri', 'tri0', 'tri1', 'wand', 'triand', 'wor', 'trior', 'trireg', 'uwire', 'none'),
/* 22-9 */
unconnected_drive: $ => seq(
directive('unconnected_drive'),
choice('pull0', 'pull1'),
'\n',
),
/* 22-12 */
line_compiler_directive: $ => seq(
directive('line'),
$.unsigned_number,
$.double_quoted_string,
$.unsigned_number,
'\n',
),
/* 22.13 */
/* `__FILE__ and `__LINE__ */
/* 22.14 */
begin_keywords: $ => seq(
directive('begin_keywords'),
$.double_quoted_string,
),
_directives: $ => choice(
$.line_compiler_directive,
$.include_compiler_directive,
$.text_macro_definition,
$.text_macro_usage,
$.id_directive,
$.zero_directive,
$.timescale_compiler_directive,
$.default_nettype_compiler_directive,
$.unconnected_drive,
$.begin_keywords,
),
// TODO missing arguments, empty list of arguments
list_of_actual_arguments: $ => sep1(',', $._actual_argument),
_actual_argument: $ => $.expression,
/* A.1.1 Library source text */
// library_text: $ => repeat($.library_description),
// library_description: $ => choice(
// $.library_declaration,
// $.include_statement,
// $.config_declaration,
// ';'
// ),
//
// library_declaration: $ => seq(
// 'library',
// $.library_identifier,
// sep1(',', $.file_path_spec),
// optseq('-incdir', sep1(',', $.file_path_spec)),
// ';'
// ),
//
// include_statement: $ => seq('include', $.file_path_spec, ';'),
/* A.1.2 SystemVerilog source text */
_description: $ => choice(
$._directives,
$.module_declaration,
$.udp_declaration,
$.interface_declaration,
$.program_declaration,
$.package_declaration,
seq(repeat($.attribute_instance), $._package_item),
seq(repeat($.attribute_instance), $.bind_directive),
// $.config_declaration,
),
// 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 ] ';'
//
// module_declaration: $ =>
// module_nonansi_header [ timeunits_declaration ] { module_item }
// 'endmodule' [ ':' _module_identifier ]
// | module_ansi_header [ timeunits_declaration ] { non_port_module_item }
// 'endmodule' [ ':' _module_identifier ]
// | { attribute_instance } module_keyword [ lifetime ] _module_identifier '(' '.*' ')' ';'
// [ timeunits_declaration ] { module_item } 'endmodule' [ ':' _module_identifier ]
// | 'extern' module_nonansi_header
// | 'extern' module_ansi_header
module_header: $ => seq(
repeat($.attribute_instance),
$.module_keyword,
optional($.lifetime),
$._module_identifier,
),
module_nonansi_header: $ => seq(
repeat($.package_import_declaration),
optional($.parameter_port_list),
$.list_of_ports,
),
module_ansi_header: $ => seq(
repeat($.package_import_declaration),
choice(
seq($.parameter_port_list, optional($.list_of_port_declarations)),
$.list_of_port_declarations,
),
),
module_declaration: $ => choice(
seq(
$.module_header,
optional(choice(
$.module_nonansi_header,
$.module_ansi_header,
seq('(', '.*', ')'),
)),
';',
optional($.timeunits_declaration),
repeat($._module_item),
'endmodule', optseq(':', $._module_identifier),
),
seq('extern', $.module_header, choice(
$.module_nonansi_header,
$.module_ansi_header,
)),
),
module_keyword: $ => choice('module', 'macromodule'),
interface_declaration: $ => choice(
seq(
$.interface_nonansi_header,
optional($.timeunits_declaration),
repeat($.interface_item),
'endinterface', optseq(':', $.interface_identifier),
),
seq(
$.interface_ansi_header,
optional($.timeunits_declaration),
repeat($._non_port_interface_item),
'endinterface', optseq(':', $.interface_identifier),
),
seq(
repeat($.attribute_instance),
'interface',
$.interface_identifier,
'(', '.*', ')', ';',
optional($.timeunits_declaration),
repeat($.interface_item),
'endinterface', optseq(':', $.interface_identifier),
),
seq('extern', $.interface_nonansi_header),
seq('extern', $.interface_ansi_header),
),
interface_nonansi_header: $ => seq(
repeat($.attribute_instance),
'interface',
optional($.lifetime),
$.interface_identifier,
repeat($.package_import_declaration),
optional($.parameter_port_list),
$.list_of_ports,
';',
),
interface_ansi_header: $ => seq(
repeat($.attribute_instance),
'interface',
optional($.lifetime),
$.interface_identifier,
repeat($.package_import_declaration),
optional($.parameter_port_list),
optional($.list_of_port_declarations),
';',
),
program_declaration: $ => choice(
seq(
$.program_nonansi_header,
optional($.timeunits_declaration),
repeat($.program_item),
'endprogram', optseq(':', $.program_identifier),
),
seq(
$.program_ansi_header,
optional($.timeunits_declaration),
repeat($.non_port_program_item),
'endprogram', optseq(':', $.program_identifier),
),
seq(
repeat($.attribute_instance),
'program',
$.program_identifier,
'(', '.*', ')', ';',
optional($.timeunits_declaration),
repeat($.program_item),
'endprogram', optseq(':', $.program_identifier),
),
seq('extern', $.program_nonansi_header),
seq('extern', $.program_ansi_header),
),
program_nonansi_header: $ => seq(
repeat($.attribute_instance),
'program',
optional($.lifetime),
$.program_identifier,
repeat($.package_import_declaration),
optional($.parameter_port_list),
$.list_of_ports,
';',
),
program_ansi_header: $ => seq(
repeat($.attribute_instance),
'program',
optional($.lifetime),
$.program_identifier,
repeat($.package_import_declaration),
optional($.parameter_port_list),
optional($.list_of_port_declarations),
';',
),
checker_declaration: $ => seq(
'checker',
$.checker_identifier,
optseq('(', optional($.checker_port_list), ')'),
';',
repseq(
repeat($.attribute_instance),
$._checker_or_generate_item,
),
'endchecker', optseq(':', $.checker_identifier),
),
class_declaration: $ => seq(
optional('virtual'),
'class',
optional($.lifetime),
$.class_identifier,
optional($.parameter_port_list),
optseq(
'extends', $.class_type, optional($.list_of_arguments_parent),
),
optseq(
'implements', sep1(',', $.interface_class_type),
),
';',
repeat($.class_item),
'endclass', optseq(':', $.class_identifier),
),
interface_class_type: $ => seq(
$.ps_class_identifier,
optional($.parameter_value_assignment),
),
interface_class_declaration: $ => seq(
'interface', 'class',
$.class_identifier,
optional($.parameter_port_list),
optseq(
'extends', optional(sep1(',', $.interface_class_type)), ';',
),
repeat($.interface_class_item),
'endclass', optseq(':', $.class_identifier),
),
interface_class_item: $ => choice(
$.type_declaration,
seq(repeat($.attribute_instance), $.interface_class_method),
seq($._any_parameter_declaration, ';'),
';',
),
interface_class_method: $ => seq('pure', 'virtual', $._method_prototype, ';'),
package_declaration: $ => seq(
repeat($.attribute_instance),
'package', optional($.lifetime), $.package_identifier, ';',
optional($.timeunits_declaration),
repseq(repeat($.attribute_instance), $._package_item),
'endpackage', optseq(':', $.package_identifier),
),
timeunits_declaration: $ => choice(
prec.left(seq('timeunit', $.time_literal, optseq('/', $.time_literal), ';')),
prec.left(seq('timeprecision', $.time_literal, ';')),
prec.left(seq('timeunit', $.time_literal, ';', 'timeprecision', $.time_literal, ';')),
prec.left(seq('timeprecision', $.time_literal, ';', 'timeunit', $.time_literal, ';')),
),
/* A.1.3 Module parameters and ports */
parameter_port_list: $ => seq(
'#', '(',
optional(choice(
seq($.list_of_param_assignments, repseq(',', $.parameter_port_declaration)),
sep1(',', $.parameter_port_declaration),
)),
')',
),
parameter_port_declaration: $ => choice(
$._any_parameter_declaration,
seq($.data_type, $.list_of_param_assignments),
seq('type', $.list_of_type_assignments),
),
list_of_ports: $ => seq(
'(',
optional(sep1(',', seq(
optional($.line_compiler_directive),
$.port,
optional($.line_compiler_directive),
))),
')',
),
list_of_port_declarations: $ => seq(
'(',
optional(sep1(',', seq(
repeat($.attribute_instance),
$.ansi_port_declaration,
))),
')',
),
port_declaration: $ => seq(
repeat($.attribute_instance),
choice(
$.inout_declaration,
$.input_declaration,
$.output_declaration,
$.ref_declaration,
$.interface_port_declaration,
),
),
port: $ => choice(
$._port_expression,
seq('.', $.port_identifier, '(', optional($._port_expression), ')'),
),
_port_expression: $ => choice(
$.port_reference,
seq('{', sep1(',', $.port_reference), '}'),
),
port_reference: $ => seq(
$.port_identifier,
optional($.constant_select1),
),
port_direction: $ => choice('input', 'output', 'inout', 'ref'),
net_port_header1: $ => choice(
seq(optional($.port_direction), $.net_port_type1),
$.port_direction,
),
variable_port_header: $ => seq(
optional($.port_direction),
$._variable_port_type,
),
interface_port_header: $ => seq(
choice(
$.interface_identifier,
'interface',
),
optseq('.', $.modport_identifier),
),
ansi_port_declaration: $ => choice(
seq(
optional(choice($.net_port_header1, $.interface_port_header)),
$.port_identifier,
repeat($.unpacked_dimension),
optseq('=', $.constant_expression),
),
seq(
optional($.variable_port_header),
$.port_identifier,
repeat($._variable_dimension),
optseq('=', $.constant_expression),
),
seq(
optional($.port_direction), '.', $.port_identifier,
'(', optional($.expression), ')',
),
),
/* A.1.4 Module items */
elaboration_system_task: $ => choice(
seq(
'$fatal',
optseq(
'(', $.finish_number, optseq(',', $.list_of_arguments), ')',
),
';',
),
seq(
choice('$error', '$warning', '$info'),
optional($.list_of_arguments_parent),
';',
),
),
finish_number: $ => choice('0', '1', '2'),
_module_common_item: $ => choice(
$._module_or_generate_item_declaration,
$.interface_instantiation,
$.program_instantiation,
$._assertion_item,
$.bind_directive,
$.continuous_assign,
$.net_alias,
$.initial_construct,
$.final_construct,
$.always_construct,
$.loop_generate_construct,
$._conditional_generate_construct,
$.elaboration_system_task,
),
_module_item: $ => choice(
seq($.port_declaration, ';'),
$._non_port_module_item,
),
module_or_generate_item: $ => seq(
repeat($.attribute_instance),
choice(
$.parameter_override,
$.gate_instantiation,
$.udp_instantiation,
$.module_instantiation,
$._module_common_item,
),
),
_module_or_generate_item_declaration: $ => choice(
$.package_or_generate_item_declaration,
$.genvar_declaration,
$.clocking_declaration,
seq('default', 'clocking', $.clocking_identifier, ';'),
seq('default', 'disable', 'iff', $.expression_or_dist, ';'),
),
_non_port_module_item: $ => choice(
$._directives,
$.generate_region,
$.module_or_generate_item,
$.specify_block,
seq(repeat($.attribute_instance), $.specparam_declaration),
$.program_declaration,
$.module_declaration,
$.interface_declaration,
$.timeunits_declaration,
),
parameter_override: $ => seq(
'defparam',
$.list_of_defparam_assignments,
';',
),
bind_directive: $ => seq(
'bind',
choice(
seq(
$.bind_target_scope,
optseq(':', $.bind_target_instance_list),
),
$.bind_target_instance,
),
$._bind_instantiation,
';',
),
bind_target_scope: $ => choice(
$._module_identifier,
// $.interface_identifier
),
bind_target_instance: $ => seq(
$.hierarchical_identifier,
optional($.constant_bit_select1),
),
bind_target_instance_list: $ => sep1(',', $.bind_target_instance),
_bind_instantiation: $ => choice(
$.program_instantiation,
$.module_instantiation,
$.interface_instantiation,
$.checker_instantiation,
),
/* A.1.5 Configuration source text */
config_declaration: $ => seq(
'config', $.config_identifier, ';',
repseq($.local_parameter_declaration, ';'),
$.design_statement,
repeat($.config_rule_statement),
'endconfig', optseq(':', $.config_identifier),
),
design_statement: $ => seq(
'design',
repseq(
optseq($.library_identifier, '.'),
$.cell_identifier,
),
';',
),
config_rule_statement: $ => choice(
seq($.default_clause, $.liblist_clause, ';'),
seq($.inst_clause, $.liblist_clause, ';'),
seq($.inst_clause, $.use_clause, ';'),
seq($.cell_clause, $.liblist_clause, ';'),
seq($.cell_clause, $.use_clause, ';'),
),
default_clause: $ => 'default',
inst_clause: $ => seq('instance', $.inst_name),
inst_name: $ => seq($.topmodule_identifier, repseq('.', $.instance_identifier)),
cell_clause: $ => seq('cell', optseq($.library_identifier, '.'), $.cell_identifier),
liblist_clause: $ => seq('liblist', repeat($.library_identifier)),
use_clause: $ => seq(
'use',
choice(
sep1(',', $.named_parameter_assignment),
seq(
optseq($.library_identifier, '.'),
$.cell_identifier,
optional(sep1(',', $.named_parameter_assignment)),
),
),
optseq(':', 'config'),
),
/* A.1.6 Interface items */
interface_or_generate_item: $ => choice(
seq(repeat($.attribute_instance), $._module_common_item),
seq(repeat($.attribute_instance), $.extern_tf_declaration),
),
extern_tf_declaration: $ => choice(
seq('extern', $._method_prototype, ';'),
seq('extern', 'forkjoin', $.task_prototype, ';'),
),
interface_item: $ => choice(
seq($.port_declaration, ';'),
$._non_port_interface_item,
),
_non_port_interface_item: $ => choice(
$.generate_region,
$.interface_or_generate_item,
$.program_declaration,
$.modport_declaration,
$.interface_declaration,
$.timeunits_declaration,
),
/* A.1.7 Program items */
program_item: $ => choice(
seq($.port_declaration, ';'),
$.non_port_program_item,
),
non_port_program_item: $ => choice(
seq(repeat($.attribute_instance), $.continuous_assign),
seq(repeat($.attribute_instance), $._module_or_generate_item_declaration),
seq(repeat($.attribute_instance), $.initial_construct),
seq(repeat($.attribute_instance), $.final_construct),
seq(repeat($.attribute_instance), $.concurrent_assertion_item),
$.timeunits_declaration,
$._program_generate_item,
),
_program_generate_item: $ => choice(
$.loop_generate_construct,
$._conditional_generate_construct,
$.generate_region,
$.elaboration_system_task,
),
/* A.1.8 Checker items */
checker_port_list: $ => sep1(',', $.checker_port_item),
checker_port_item: $ => seq(
repeat($.attribute_instance),
optional($.checker_port_direction),
optional($.property_formal_type1),
$.formal_port_identifier,
repeat($._variable_dimension),
optseq('=', $._property_actual_arg),
),
checker_port_direction: $ => choice('input', 'output'),
_checker_or_generate_item: $ => choice(
$.checker_or_generate_item_declaration,
$.initial_construct,
$.always_construct,
$.final_construct,
$._assertion_item,
$.continuous_assign,
$._checker_generate_item,
),
checker_or_generate_item_declaration: $ => choice(
seq(optional('rand'), $.data_declaration),
$.function_declaration,
$.checker_declaration,
$._assertion_item_declaration,
$.covergroup_declaration,
$.genvar_declaration,
$.clocking_declaration,
seq('default', 'clocking', $.clocking_identifier, ';'),
prec.right(PREC.iff, seq('default', 'disable', 'iff', $.expression_or_dist, ';')),
';',
),
_checker_generate_item: $ => choice(
$.loop_generate_construct,
$._conditional_generate_construct,
$.generate_region,
$.elaboration_system_task,
),
/* A.1.9 Class items */
class_item: $ => choice(
$._directives,
seq(repeat($.attribute_instance), $.class_property),
seq(repeat($.attribute_instance), $.class_method),
seq(repeat($.attribute_instance), $._class_constraint),
seq(repeat($.attribute_instance), $.class_declaration),
seq(repeat($.attribute_instance), $.covergroup_declaration),
seq($._any_parameter_declaration, ';'),
';',
),
class_property: $ => choice(
seq(repeat($._property_qualifier), $.data_declaration),
seq(
'const',
repeat($.class_item_qualifier),
$.data_type,
$.const_identifier,
optseq('=', $.constant_expression),
';',
),
),
class_method: $ => choice(
seq(repeat($.method_qualifier), $.task_declaration),
seq(repeat($.method_qualifier), $.function_declaration),
seq('pure', 'virtual', repeat($.class_item_qualifier), $._method_prototype, ';'),
seq('extern', repeat($.method_qualifier), $._method_prototype, ';'),
seq(repeat($.method_qualifier), $.class_constructor_declaration),
seq('extern', repeat($.method_qualifier), $.class_constructor_prototype),
),
class_constructor_prototype: $ => seq(
'function', 'new', optseq('(', optional($.tf_port_list), ')'), ';',
),
_class_constraint: $ => choice(
$.constraint_prototype,
$.constraint_declaration,
),
class_item_qualifier: $ => choice('static', 'protected', 'local'),
_property_qualifier: $ => choice(
$.random_qualifier,
$.class_item_qualifier,
),
random_qualifier: $ => choice('rand', 'randc'),
method_qualifier: $ => choice(
seq(optional('pure'), 'virtual'),
$.class_item_qualifier,
),
_method_prototype: $ => choice(
$.task_prototype,
$.function_prototype,
),
class_constructor_declaration: $ => seq(
'function',
optional($.class_scope),
'new',
optseq('(', optional($.tf_port_list), ')'),
';',
repeat($.block_item_declaration),
optseq(
'super', '.', 'new',
optional($.list_of_arguments_parent),
';',
),
repeat($.function_statement_or_null),
'endfunction', optseq(':', 'new'),
),
/* A.1.10 Constraints */
constraint_declaration: $ => seq(
optional('static'),
'constraint',
$.constraint_identifier,
$.constraint_block,
),
constraint_block: $ => seq('{', repeat($.constraint_block_item), '}'),
constraint_block_item: $ => choice(
seq('solve', $.solve_before_list, 'before', $.solve_before_list, ';'),
$.constraint_expression,
),
solve_before_list: $ => sep1(',', $.constraint_primary),
constraint_primary: $ => seq(
optional(choice(
seq($.implicit_class_handle, '.'),
$.class_scope,
)),
$.hierarchical_identifier,
optional($.select1),
),
constraint_expression: $ => choice(
seq(optional('soft'), $.expression_or_dist, ';'),
seq($.uniqueness_constraint, ';'),
prec.right(PREC.IMPLICATION, seq($.expression, '–>', $.constraint_set)),
prec.left(seq(
'if', '(', $.expression, ')', $.constraint_set,
optseq('else', $.constraint_set),
)),
seq(
'foreach', '(',
$.ps_or_hierarchical_array_identifier,
'[', optional($.loop_variables1), ']',
')',
$.constraint_set,
),
seq('disable', 'soft', $.constraint_primary, ';'),
),
uniqueness_constraint: $ => seq(
'unique', '{', $.open_range_list, '}',
),
constraint_set: $ => choice(
$.constraint_expression,
seq('{', repeat($.constraint_expression), '}'),
),
dist_list: $ => sep1(',', $.dist_item),
dist_item: $ => seq($.value_range, optional($.dist_weight)),
dist_weight: $ => seq(choice(':=', ':/'), $.expression),
constraint_prototype: $ => seq(
optional($.constraint_prototype_qualifier),
optional('static'),
'constraint',
$.constraint_identifier,
';',
),
constraint_prototype_qualifier: $ => choice('extern', 'pure'),
extern_constraint_declaration: $ => seq(
optional('static'),
'constraint',
$.class_scope,
$.constraint_identifier,
$.constraint_block,
),
identifier_list: $ => sep1(',', $._identifier),
/* A.1.11 Package items */
_package_item: $ => choice(
$.package_or_generate_item_declaration,
$.anonymous_program,
$.package_export_declaration,
$.timeunits_declaration,
),
package_or_generate_item_declaration: $ => choice(
$.net_declaration,
$.data_declaration,
$.task_declaration,
$.function_declaration,
$.checker_declaration,
$.dpi_import_export,
$.extern_constraint_declaration,
$.class_declaration,
$.interface_class_declaration, // not in spec
$.class_constructor_declaration,
seq($._any_parameter_declaration, ';'),
$.covergroup_declaration,
$.overload_declaration,
$._assertion_item_declaration,
';',
),
anonymous_program: $ => seq(
'program', ';', repeat($.anonymous_program_item), 'endprogram',
),
anonymous_program_item: $ => choice(
$.task_declaration,
$.function_declaration,
$.class_declaration,
$.covergroup_declaration,
$.class_constructor_declaration,
';',
),
/* A.2 Declarations */
/* A.2.1 Declaration types */
/* A.2.1.1 Module parameter declarations */
local_parameter_declaration: $ => seq(
'localparam',
choice(
seq(
optional($.data_type_or_implicit1),
$.list_of_param_assignments,
),
seq('type', $.list_of_type_assignments),
),
),
parameter_declaration: $ => seq(
'parameter',
choice(
seq(
optional($.data_type_or_implicit1),
$.list_of_param_assignments,
),
seq('type', $.list_of_type_assignments),
),
),
_any_parameter_declaration: $ => choice(
$.local_parameter_declaration,
$.parameter_declaration,
),
specparam_declaration: $ => seq(
'specparam',
optional($.packed_dimension),
$.list_of_specparam_assignments,
';',
),
/* A.2.1.2 Port declarations */
inout_declaration: $ => seq(
'inout', optional($.net_port_type1), $.list_of_port_identifiers,
),
input_declaration: $ => seq(
'input',
choice(
seq(optional($.net_port_type1), $.list_of_port_identifiers),
seq(optional($._variable_port_type), $.list_of_variable_identifiers),
),
),
output_declaration: $ => seq(
'output',
choice(
seq(optional($.net_port_type1), $.list_of_port_identifiers),
seq(optional($._variable_port_type), $.list_of_variable_port_identifiers),
),
),
interface_port_declaration: $ => seq(
$.interface_identifier,
optseq('.', $.modport_identifier),
$.list_of_interface_identifiers,
),
ref_declaration: $ => seq(
'ref', $._variable_port_type, $.list_of_variable_identifiers,
),
// A.2.1.3 Type declarations
data_declaration: $ => choice(
seq(
optional('const'),
optional('var'),
optional($.lifetime),
optional($.data_type_or_implicit1),
$.list_of_variable_decl_assignments,
';',
),
$.type_declaration,
$.package_import_declaration,
$.net_type_declaration,
),
package_import_declaration: $ => seq(
'import', sep1(',', $.package_import_item), ';',
),
package_import_item: $ => seq(
$.package_identifier, '::', choice($._identifier, '*'),
),
package_export_declaration: $ => seq(
'export', choice('*::*', sep1(',', $.package_import_item)), ';',
),
genvar_declaration: $ => seq(
'genvar', $.list_of_genvar_identifiers, ';',
),
net_declaration: $ => choice(
seq(
$.net_type,
optional(choice($.drive_strength, $.charge_strength)),
optional(choice('vectored', 'scalared')),
optional($.data_type_or_implicit1),
optional($.delay3),
$.list_of_net_decl_assignments,
';',
),
seq(
$._net_type_identifier,
optional($.delay_control),
$.list_of_net_decl_assignments,
';',
),
seq(
'interconnect',
optional($.implicit_data_type1),
optseq('#', $.delay_value),
sep1(',', seq($._net_identifier, repeat($.unpacked_dimension))),
';',
),
),
type_declaration: $ => seq(
'typedef',
choice(
seq($.data_type, $._type_identifier, repeat($._variable_dimension)),
seq(
$.interface_instance_identifier, optional($.constant_bit_select1),
'.', $._type_identifier, $._type_identifier,
),
seq(
optional(choice(
'enum', 'struct', 'union', 'class', seq('interface', 'class'),
)),
$._type_identifier,
),
),
';',
),
net_type_declaration: $ => seq(
'nettype',
choice(
seq(
$.data_type,
$._net_type_identifier,
optseq(
'with',
optional(choice($.package_scope, $.class_scope)),
$.tf_identifier,
),
),
seq(
optional(choice($.package_scope, $.class_scope)),
$._net_type_identifier,
$._net_type_identifier,
),
),
';',
),
lifetime: $ => choice('static', 'automatic'),
/* A.2.2 Declaration data types */
/* A.2.2.1 Net and variable types */
casting_type: $ => choice(
$._simple_type,
$.constant_primary,
$._signing,
'string',
'const',
),
data_type: $ => choice(
seq($.integer_vector_type, optional($._signing), repeat($.packed_dimension)),
seq($.integer_atom_type, optional($._signing)),
$.non_integer_type,
seq(
$.struct_union,
optseq('packed', optional($._signing)),
'{', repeat1($.struct_union_member), '}',
repeat($.packed_dimension),
),
seq(
'enum', optional($.enum_base_type),
'{', sep1(',', $.enum_name_declaration), '}',
repeat($.packed_dimension),
),
'string',
'chandle',
prec.left(seq(
'virtual', optional('interface'),
$.interface_identifier,
optional($.parameter_value_assignment),
optseq('.', $.modport_identifier),
)),
seq(
optional(choice($.class_scope, $.package_scope)),
$._type_identifier,
repeat($.packed_dimension),
),
$.class_type,
'event',
$.ps_covergroup_identifier,
$.type_reference,
),
data_type_or_implicit1: $ => choice(
$.data_type,
$.implicit_data_type1,
),
implicit_data_type1: $ => choice( // reordered : repeat -> repeat1
seq($._signing, repeat($.packed_dimension)),
repeat1($.packed_dimension),
),
enum_base_type: $ => choice(
seq(
$.integer_atom_type, optional($._signing),
),
seq(
$.integer_vector_type, optional($._signing), optional($.packed_dimension),
),
seq(
$._type_identifier, optional($.packed_dimension),
),
),
enum_name_declaration: $ => seq(
$.enum_identifier,
optseq(
'[', $.integral_number, optseq(':', $.integral_number), ']',
),
optseq('=', $.constant_expression),
),
class_scope: $ => seq($.class_type, '::'),
// class_type: $ => prec.left(PREC.PARENT, seq(
class_type: $ => prec.right(seq(
$.ps_class_identifier,
optional($.parameter_value_assignment),
repseq(
'::',
$.class_identifier,
optional($.parameter_value_assignment),
),
)),
_integer_type: $ => choice(
$.integer_vector_type,
$.integer_atom_type,
),
integer_atom_type: $ => choice('byte', 'shortint', 'int', 'longint', 'integer', 'time'),
integer_vector_type: $ => choice('bit', 'logic', 'reg'),
non_integer_type: $ => choice('shortreal', 'real', 'realtime'),
net_type: $ => choice('supply0', 'supply1', 'tri', 'triand', 'trior', 'trireg', 'tri0', 'tri1', 'uwire', 'wire', 'wand', 'wor'),
net_port_type1: $ => choice(
prec.left(-1, seq($.net_type, $.data_type_or_implicit1)),
$.net_type,
$.data_type_or_implicit1,
$._net_type_identifier,
seq('interconnect', optional($.implicit_data_type1)),
),
_variable_port_type: $ => $._var_data_type,
_var_data_type: $ => prec.left(choice(
$.data_type,
seq('var', optional($.data_type_or_implicit1)),
)),
_signing: $ => choice('signed', 'unsigned'),
_simple_type: $ => choice(
$._integer_type,
$.non_integer_type,
$.ps_type_identifier,
$.ps_parameter_identifier,
),
struct_union_member: $ => seq(
repeat($.attribute_instance),
optional($.random_qualifier),
$.data_type_or_void,
$.list_of_variable_decl_assignments,
';',
),
data_type_or_void: $ => choice(
$.data_type,
'void',
),
struct_union: $ => choice(
'struct',
seq('union', optional('tagged')),
),
type_reference: $ => seq(
'type', '(',
choice(
$.expression,
$.data_type,
),
')',
),
// A.2.2.2 Strengths
drive_strength: $ => seq(
'(',
choice(
seq($.strength0, ',', $.strength1),
seq($.strength1, ',', $.strength0),
seq($.strength0, ',', 'highz1'),
seq($.strength1, ',', 'highz0'),
seq('highz0', ',', $.strength1),
seq('highz1', ',', $.strength0),
),
')',
),
strength0: $ => choice('supply0', 'strong0', 'pull0', 'weak0'),
strength1: $ => choice('supply1', 'strong1', 'pull1', 'weak1'),
charge_strength: $ => seq('(', choice('small', 'medium', 'large'), ')'),
// A.2.2.3 Delays
delay3: $ => seq('#', choice(
$.delay_value,
seq(
'(', $.mintypmax_expression,
optseq($.mintypmax_expression,
optional($.mintypmax_expression),
),
')',
),
)),
delay2: $ => seq('#', choice(
$.delay_value,
seq('(', $.mintypmax_expression, optional($.mintypmax_expression), ')'),
)),
delay_value: $ => choice(
$.unsigned_number,
$.real_number,
$.ps_identifier,
$.time_literal,
'1step',
),
/* A.2.3 Declaration lists */
list_of_defparam_assignments: $ => sep1(',', $.defparam_assignment),
list_of_genvar_identifiers: $ => sep1(',', $.genvar_identifier),
list_of_interface_identifiers: $ => sep1(',', seq(
$.interface_identifier,
repeat($.unpacked_dimension),
)),
list_of_net_decl_assignments: $ => sep1(',', $.net_decl_assignment),
list_of_param_assignments: $ => sep1(',', $.param_assignment),
list_of_port_identifiers: $ => sep1(',', seq(
$.port_identifier,
repeat($.unpacked_dimension),
)),
list_of_udp_port_identifiers: $ => sep1(',', $.port_identifier),
list_of_specparam_assignments: $ => sep1(',', $.specparam_assignment),
list_of_tf_variable_identifiers: $ => sep1(',', seq(
$.port_identifier,
repeat($._variable_dimension),
optseq('=', $.expression),
)),
list_of_type_assignments: $ => sep1(',', $.type_assignment),
list_of_variable_decl_assignments: $ => sep1(',', $.variable_decl_assignment),
list_of_variable_identifiers: $ => sep1(',', seq(
$._variable_identifier,
repeat($._variable_dimension),
)),
list_of_variable_port_identifiers: $ => sep1(',', seq(
$.port_identifier,
repeat($._variable_dimension),
optseq('=', $.constant_expression),
)),
/* A.2.4 Declaration assignments */
defparam_assignment: $ => seq(
$._hierarchical_parameter_identifier,
'=',
$.constant_mintypmax_expression,
),
net_decl_assignment: $ => prec.left(PREC.ASSIGN, seq(
$._net_identifier,
repeat($.unpacked_dimension),
optseq('=', $.expression),
)),
param_assignment: $ => seq(
$.parameter_identifier,
repeat($.unpacked_dimension),
optseq('=', $.constant_param_expression),
),
specparam_assignment: $ => choice(
seq($.specparam_identifier, '=', $.constant_mintypmax_expression),
$.pulse_control_specparam,
),
type_assignment: $ => seq(
$._type_identifier,
optseq('=', $.data_type),
),
pulse_control_specparam: $ => choice(
seq(
'PATHPULSE$=',
'(',
$.reject_limit_value,
optseq(',', $.error_limit_value),
')',
),
// seq(
// 'PATHPULSE$',
// $.specify_input_terminal_descriptor,
// '$',
// $.specify_output_terminal_descriptor,
// '=', '(', $.reject_limit_value, optseq(',', $.error_limit_value), ')'
// )
),
error_limit_value: $ => $.limit_value,
reject_limit_value: $ => $.limit_value,
limit_value: $ => $.constant_mintypmax_expression,
variable_decl_assignment: $ => choice(
seq(
$._variable_identifier,
repeat($._variable_dimension),
optseq('=', $.expression),
),
seq(
$.dynamic_array_variable_identifier,
$.unsized_dimension,
repeat($._variable_dimension),
optseq('=', $.dynamic_array_new),
),
seq(
$.class_variable_identifier,
optseq('=', $.class_new),
),
),
class_new: $ => choice(
seq(
optional($.class_scope), 'new', optional($.list_of_arguments_parent),
),
seq('new', $.expression),
),
dynamic_array_new: $ => seq(
'new', '[', $.expression, ']', optseq('(', $.expression, ')'),
),
// A.2.5 Declaration ranges
unpacked_dimension: $ => seq(
'[', choice(
$.constant_range,
$.constant_expression,
), ']',
),
packed_dimension: $ => choice(
seq('[', $.constant_range, ']'),
$.unsized_dimension,
),
associative_dimension: $ => seq(
'[', choice($.data_type, '*'), ']',
),
_variable_dimension: $ => choice(
$.unsized_dimension,
$.unpacked_dimension,
$.associative_dimension,
$.queue_dimension,
),
queue_dimension: $ => seq(
'[', '$', optseq(':', $.constant_expression), ']',
),
unsized_dimension: $ => seq('[', ']'),
// A.2.6 Function declarations
function_data_type_or_implicit1: $ => choice(
$.data_type_or_void,
$.implicit_data_type1,
),
function_declaration: $ => seq(
'function',
optional($.lifetime),
$.function_body_declaration,
),
function_body_declaration: $ => seq(
optional($.function_data_type_or_implicit1),
optional(choice(
seq($.interface_identifier, '.'),
$.class_scope,
)),
$.function_identifier,
choice(
seq(
';',
repeat($.tf_item_declaration),
),
seq(
'(', optional($.tf_port_list), ')', ';',
repeat($.block_item_declaration),
),
),
repeat($.function_statement_or_null),
'endfunction',
optseq(':', $.function_identifier),
),
function_prototype: $ => seq(
'function',
$.data_type_or_void,
$.function_identifier,
optseq(
'(', optional($.tf_port_list), ')',
),
),
dpi_import_export: $ => choice(
seq(
'import',
$.dpi_spec_string,
optional($.dpi_function_import_property),
optseq($.c_identifier, '='),
$.dpi_function_proto,
';',
),
seq(
'import',
$.dpi_spec_string,
optional($.dpi_task_import_property),
optseq($.c_identifier, '='),
$.dpi_task_proto,
';',
),
seq(
'export',
$.dpi_spec_string,
optseq($.c_identifier, '='),
'function',
$.function_identifier,
';',
),
seq(
'export',
$.dpi_spec_string,
optseq($.c_identifier, '='),
'task',
$.task_identifier,
';',
),
),
dpi_spec_string: $ => choice('"DPI-C"', '"DPI"'),
dpi_function_import_property: $ => choice('context', 'pure'),
dpi_task_import_property: $ => 'context',
dpi_function_proto: $ => $.function_prototype,
dpi_task_proto: $ => $.task_prototype,
// A.2.7 Task declarations
task_declaration: $ => seq(
'task',
optional($.lifetime),
$.task_body_declaration,
),
task_body_declaration: $ => seq(
optional(choice(
seq($.interface_identifier, '.'),
$.class_scope,
)),
$.task_identifier,
choice(
seq(
';',
repeat($.tf_item_declaration),
),
seq(
'(', optional($.tf_port_list), ')', ';',
repeat($.block_item_declaration),
),
),
repeat($.statement_or_null),
'endtask',
optseq(':', $.task_identifier),
),
tf_item_declaration: $ => choice(
$.block_item_declaration,
$.tf_port_declaration,
),
tf_port_list: $ => sep1(',', $.tf_port_item1),
tf_port_item1: $ => seq(
repeat($.attribute_instance),
optional($.tf_port_direction),
optional('var'),
choice(
seq(
$.data_type_or_implicit1,
optseq(
$.port_identifier,
repeat($._variable_dimension),
optseq('=', $.expression),
),
),
seq(
$.port_identifier,
repeat($._variable_dimension),
optseq('=', $.expression),
),
),
),
tf_port_direction: $ => choice(
$.port_direction,
seq('const', 'ref'),
),
tf_port_declaration: $ => seq(
repeat($.attribute_instance),
$.tf_port_direction,
optional('var'),
optional($.data_type_or_implicit1),
$.list_of_tf_variable_identifiers,
';',
),
task_prototype: $ => seq(
'task',
$.task_identifier,
optseq('(', optional($.tf_port_list), ')'),
),
// A.2.8 Block item declarations
block_item_declaration: $ => seq(
repeat($.attribute_instance),
choice(
$.data_declaration,
seq($._any_parameter_declaration, ';'),
$.overload_declaration,
$.let_declaration,
),
),
overload_declaration: $ => seq(
'bind',
$.overload_operator,
'function',
$.data_type,
$.function_identifier,
'(',
$.overload_proto_formals,
')',
';',
),
overload_operator: $ => choice('+', '++', '–', '––', '*', '**', '/', '%', '==', '!=', '<', '<=', '>', '>=', '='),
overload_proto_formals: $ => sep1(',', $.data_type),
/* A.2.9 Interface declarations */
modport_declaration: $ => seq('modport', sep1(',', $.modport_item), ';'),
modport_item: $ => seq(
$.modport_identifier,
'(', sep1(',', $.modport_ports_declaration), ')',
),
modport_ports_declaration: $ => seq(
repeat($.attribute_instance),
choice(
$.modport_simple_ports_declaration,
$.modport_tf_ports_declaration,
$.modport_clocking_declaration,
),
),
modport_clocking_declaration: $ => seq('clocking', $.clocking_identifier),
modport_simple_ports_declaration: $ => seq(
$.port_direction,
sep1(',', $.modport_simple_port),
),
modport_simple_port: $ => choice(
$.port_identifier,
seq('.', $.port_identifier, '(', optional($.expression), ')'),
),
modport_tf_ports_declaration: $ => seq(
$.import_export, sep1(',', $._modport_tf_port),
),
_modport_tf_port: $ => choice(
$._method_prototype,
$.tf_identifier,
),
import_export: $ => choice('import', 'export'),
// A.2.10 Assertion declarations
concurrent_assertion_item: $ => choice(
seq(
optseq($._block_identifier, ':'),
$._concurrent_assertion_statement,
),
$.checker_instantiation,
),
_concurrent_assertion_statement: $ => choice(
$.assert_property_statement,
$.assume_property_statement,
$.cover_property_statement,
$.cover_sequence_statement,
$.restrict_property_statement,
),
assert_property_statement: $ => seq(
'assert', 'property', '(', $.property_spec, ')', $.action_block,
),
assume_property_statement: $ => seq(
'assume', 'property', '(', $.property_spec, ')', $.action_block,
),
cover_property_statement: $ => seq(
'cover', 'property', '(', $.property_spec, ')', $.statement_or_null,
),
expect_property_statement: $ => seq(
'expect', '(', $.property_spec, ')', $.action_block,
),
cover_sequence_statement: $ => seq(
'cover', 'sequence', '(',
optional($.clocking_event),
optional(prec.right(PREC.iff, seq(
'disable', 'iff', '(', $.expression_or_dist, ')',
))),
$.sequence_expr,
')',
$.statement_or_null,
),
restrict_property_statement: $ => seq(
'restrict', 'property', '(', $.property_spec, ')', ';',
),
property_instance: $ => seq(
$.ps_or_hierarchical_property_identifier,
optseq('(', optional($.property_list_of_arguments), ')'),
),
property_list_of_arguments: $ => choice(
seq(
sep1(',', optional($._property_actual_arg)),
repeat1(seq( // TODO remove 1
',', '.', $._identifier, '(', optional($._property_actual_arg), ')',
)),
),
sep1(',', seq(
'.', $._identifier, '(', optional($._property_actual_arg), ')',
)),
),
_property_actual_arg: $ => choice(
$.property_expr,
$._sequence_actual_arg,
),
_assertion_item_declaration: $ => choice(
$.property_declaration,
$.sequence_declaration,
$.let_declaration,
),
property_declaration: $ => seq(
'property',
$.property_identifier,
optseq('(', optional($.property_port_list), ')'),
';',
repeat($.assertion_variable_declaration),
$.property_spec,
optional(';'),
'endproperty', optseq(':', $.property_identifier),
),
property_port_list: $ => sep1(',', $.property_port_item),
property_port_item: $ => seq(
repeat($.attribute_instance),
optseq(
'local',
optional($.property_lvar_port_direction),
),
optional($.property_formal_type1),
$.formal_port_identifier,
repeat($._variable_dimension),
optseq('=', $._property_actual_arg),
),
property_lvar_port_direction: $ => 'input',
property_formal_type1: $ => choice(
$.sequence_formal_type1,
'property',
),
property_spec: $ => seq(
optional($.clocking_event),
optional(prec.right(PREC.iff, seq(
'disable', 'iff', '(', $.expression_or_dist, ')',
))),
$.property_expr,
),
property_expr: $ => choice(
$.sequence_expr,
seq('strong', '(', $.sequence_expr, ')'),
seq('weak', '(', $.sequence_expr, ')'),
prec.left(PREC.PARENT, seq('(', $.property_expr, ')')),
// FIXME no assosiativity rules per spec
prec.left(PREC.nexttime, seq('not', $.property_expr)),
prec.left(PREC.or, seq($.property_expr, 'or', $.property_expr)),
prec.left(PREC.and, seq($.property_expr, 'and', $.property_expr)),
prec.right(PREC.INCIDENCE, seq($.sequence_expr, '|->', $.property_expr)),
prec.right(PREC.INCIDENCE, seq($.sequence_expr, '|=>', $.property_expr)),
// FIXME no assosiativity rules per spec
prec.left(seq('if', '(', $.expression_or_dist, ')', $.property_expr, optseq('else', $.property_expr))), // FIXME spec bug ( ) are not red
seq('case', '(', $.expression_or_dist, ')', repeat1($.property_case_item), 'endcase'), // FIXME spec bug ( ) are not red
prec.right(PREC.INCIDENCE, seq($.sequence_expr, '#-#', $.property_expr)),
prec.right(PREC.INCIDENCE, seq($.sequence_expr, '#=#', $.property_expr)),
// FIXME no assosiativity rules per spec
prec.left(PREC.nexttime, seq('nexttime', $.property_expr)),
prec.left(PREC.nexttime, seq('nexttime', '[', $.constant_expression, ']', $.property_expr)), // FIXME spec bug constant _expression with the space
prec.left(PREC.nexttime, seq('s_nexttime', $.property_expr)),
prec.left(PREC.nexttime, seq('s_nexttime', '[', $.constant_expression, ']', $.property_expr)),
prec.left(PREC.always, seq('always', $.property_expr)),
prec.left(PREC.always, seq('always', '[', $.cycle_delay_const_range_expression, ']', $.property_expr)),
prec.left(PREC.always, seq('s_always', '[', $.constant_range, ']', $.property_expr)),
prec.left(PREC.always, seq('s_eventually', $.property_expr)),
prec.left(PREC.always, seq('eventually', '[', $.constant_range, ']', $.property_expr)),
prec.left(PREC.always, seq('s_eventually', '[', $.cycle_delay_const_range_expression, ']', $.property_expr)),
prec.right(PREC.until, seq($.property_expr,
choice('until', 's_until', 'until_with', 's_until_with', 'implies'),
$.property_expr,
)),
prec.right(PREC.iff, seq($.property_expr, 'iff', $.property_expr)),
// FIXME no assosiativity rules per spec
prec.left(PREC.always, seq(
choice('accept_on', 'reject_on', 'sync_accept_on', 'sync_reject_on'),
'(', $.expression_or_dist, ')', $.property_expr,
)),
// $.property_instance,
prec.left(seq($.clocking_event, $.property_expr)), // FIXME no assosiativity rules per spec
),
property_case_item: $ => choice(
seq(
sep1(',', $.expression_or_dist), ':', $.property_expr, ';',
),
seq(
'default', optional(':'), $.property_expr, ';',
),
),
sequence_declaration: $ => seq(
'sequence',
$._sequence_identifier,
optseq(
'(', optional($.sequence_port_list), ')',
),
';',
repeat($.assertion_variable_declaration),
$.sequence_expr,
optional(';'),
'endsequence', optseq(':', $._sequence_identifier),
),
sequence_port_list: $ => sep1(',', $.sequence_port_item),
sequence_port_item: $ => seq(
repeat($.attribute_instance),
optseq(
'local',
optional($.sequence_lvar_port_direction),
),
optional($.sequence_formal_type1),
$.formal_port_identifier,
repeat($._variable_dimension),
optseq(
'=', $._sequence_actual_arg,
),
),
sequence_lvar_port_direction: $ => choice('input', 'inout', 'output'),
sequence_formal_type1: $ => choice(
$.data_type_or_implicit1,
'sequence',
'untyped',
),
sequence_expr: $ => choice(
prec.left(sep1(',', $.cycle_delay_range)), // FIXME precedence?
prec.left(PREC.SHARP2, seq($.sequence_expr, repeat1(seq($.cycle_delay_range, $.sequence_expr)))),
seq($.expression_or_dist, optional($._boolean_abbrev)),
seq($.sequence_instance, optional($.sequence_abbrev)),
prec.left(seq('(', $.sequence_expr, repseq(',', $._sequence_match_item), ')', optional($.sequence_abbrev))),
prec.left(PREC.and, seq($.sequence_expr, 'and', $.sequence_expr)),
prec.left(PREC.intersect, seq($.sequence_expr, 'intersect', $.sequence_expr)),
prec.left(PREC.or, seq($.sequence_expr, 'or', $.sequence_expr)),
seq('first_match', '(', $.sequence_expr, repseq(',', $._sequence_match_item), ')'),
prec.right(PREC.throughout, seq($.expression_or_dist, 'throughout', $.sequence_expr)),
prec.left(PREC.within, seq($.sequence_expr, 'within', $.sequence_expr)),
prec.left(seq($.clocking_event, $.sequence_expr)), // FIXME precedence?
),
cycle_delay_range: $ => choice(
prec.left(seq('##', $.constant_primary)),
prec.left(seq('##', '[', $.cycle_delay_const_range_expression, ']')),
'##[*]',
'##[+]',
),
sequence_method_call: $ => seq($.sequence_instance, '.', $.method_identifier),
_sequence_match_item: $ => choice(
$.operator_assignment,
$.inc_or_dec_expression,
$.subroutine_call,
),
sequence_instance: $ => seq(
$.ps_or_hierarchical_sequence_identifier,
optseq('(', optional($.sequence_list_of_arguments), ')'),
),
sequence_list_of_arguments: $ => choice(
// seq(
// sep1(',', optional($._sequence_actual_arg)),
// repseq(',', '.', $._identifier, '(', optional($._sequence_actual_arg), ')')
// ),
sep1(',', seq('.', $._identifier, '(', optional($._sequence_actual_arg), ')')),
),
_sequence_actual_arg: $ => choice(
$.event_expression,
$.sequence_expr,
),
_boolean_abbrev: $ => choice(
$.consecutive_repetition,
$.non_consecutive_repetition,
$.goto_repetition,
),
sequence_abbrev: $ => $.consecutive_repetition,
consecutive_repetition: $ => choice(
seq('[*', $._const_or_range_expression, ']'),
'[*]',
'[+]',
),
non_consecutive_repetition: $ => seq('[=', $._const_or_range_expression, ']'),
goto_repetition: $ => seq('[->', $._const_or_range_expression, ']'),
_const_or_range_expression: $ => choice(
$.constant_expression,
$.cycle_delay_const_range_expression,
),
cycle_delay_const_range_expression: $ => choice(
seq($.constant_expression, ':', $.constant_expression),
seq($.constant_expression, ':', '$'),
),
expression_or_dist: $ => seq(
$.expression,
optional(prec.left(PREC.RELATIONAL, seq('dist', '{', $.dist_list, '}'))),
),
assertion_variable_declaration: $ => seq(
$._var_data_type,
$.list_of_variable_decl_assignments,
';',
),
// A.2.11 Covergroup declarations
covergroup_declaration: $ => seq(
'covergroup', $.covergroup_identifier,
optseq('(', optional($.tf_port_list), ')'),
optional($.coverage_event),
';',
repeat($.coverage_spec_or_option),
'endgroup', optseq(':', $.covergroup_identifier),
),
coverage_spec_or_option: $ => choice(
seq(repeat($.attribute_instance), $._coverage_spec),
seq(repeat($.attribute_instance), $.coverage_option, ';'),
),
coverage_option: $ => choice(
seq('option', '.', $.member_identifier, '=', $.expression),
seq('type_option', '.', $.member_identifier, '=', $.constant_expression),
),
_coverage_spec: $ => choice($.cover_point, $.cover_cross),
coverage_event: $ => choice(
$.clocking_event,
seq('with', 'function', 'sample', '(', optional($.tf_port_list), ')'),
seq('@@', '(', $.block_event_expression, ')'),
),
block_event_expression: $ => choice(
prec.left(PREC.or, seq($.block_event_expression, 'or', $.block_event_expression)),
seq('begin', $.hierarchical_btf_identifier),
seq('end', $.hierarchical_btf_identifier),
),
hierarchical_btf_identifier: $ => choice(
$._hierarchical_tf_identifier,
$._hierarchical_block_identifier,
prec.left(PREC.PARENT, seq(
choice(seq($.hierarchical_identifier, '.'), $.class_scope),
$.method_identifier,
)),
),
cover_point: $ => seq(
optseq(optional($.data_type_or_implicit1), $.cover_point_identifier, ':'),
'coverpoint', $.expression,
optional(prec.right(PREC.iff, seq('iff', '(', $.expression, ')'))),
$.bins_or_empty,
),
bins_or_empty: $ => choice(
seq('{', repeat($.attribute_instance), repseq($.bins_or_options, ';'), '}'),
';',
),
bins_or_options: $ => choice(
$.coverage_option,
seq(
'wildcard',
$.bins_keyword,
$._bin_identifier,
optseq('[', optional($._covergroup_expression), ']'),
'=',
'{', $.covergroup_range_list, '}',
optseq('with', '(', $._with_covergroup_expression, ')'),
optional(prec.right(PREC.iff, seq('iff', '(', $.expression, ')'))),
),
seq(
'wildcard',
$.bins_keyword,
$._bin_identifier,
optseq('[', optional($._covergroup_expression), ']'),
'=',
$.cover_point_identifier,
'with', '(', $._with_covergroup_expression, ')',
optional(prec.right(PREC.iff, seq('iff', '(', $.expression, ')'))),
),
seq(
'wildcard',
$.bins_keyword,
$._bin_identifier,
optseq('[', optional($._covergroup_expression), ']'),
'=',
$._set_covergroup_expression,
optional(prec.right(PREC.iff, seq('iff', '(', $.expression, ')'))),
),
seq(
'wildcard',
$.bins_keyword,
$._bin_identifier,
optseq('[', ']'),
'=',
$.trans_list,
optional(prec.right(PREC.iff, seq('iff', '(', $.expression, ')'))),
),
seq(
$.bins_keyword,
$._bin_identifier,
optseq('[', optional($._covergroup_expression), ']'),
'=',
'default',
optional(prec.right(PREC.iff, seq('iff', '(', $.expression, ')'))),
),
seq(
$.bins_keyword,
$._bin_identifier,
'=',
'default',
'sequence',
optional(prec.right(PREC.iff, seq('iff', '(', $.expression, ')'))),
),
),
bins_keyword: $ => choice('bins', 'illegal_bins', 'ignore_bins'),
trans_list: $ => sep1(',', seq('(', $.trans_set, ')')),
trans_set: $ => sep1('=>', $.trans_range_list),
trans_range_list: $ => choice(
$.trans_item,
seq($.trans_item, '[*', $.repeat_range, ']'),
seq($.trans_item, '[–>', $.repeat_range, ']'),
seq($.trans_item, '[=', $.repeat_range, ']'),
),
trans_item: $ => $.covergroup_range_list,
repeat_range: $ => seq(
$._covergroup_expression, optseq(':', $._covergroup_expression),
),
cover_cross: $ => seq(
optseq($.cross_identifier, ':'),
'cross',
$.list_of_cross_items,
optional(prec.right(PREC.iff, seq('iff', '(', $.expression, ')'))),
$.cross_body,
),
list_of_cross_items: $ => seq($._cross_item, ',', sep1(',', $._cross_item)),
_cross_item: $ => choice(
$.cover_point_identifier,
// $._variable_identifier
),
cross_body: $ => choice(
seq('{', repseq($.cross_body_item, ';'), '}'),
';',
),
cross_body_item: $ => choice(
$.function_declaration, // FIXME standard function_declaraton => function_declaration
seq($.bins_selection_or_option, ';'),
),
bins_selection_or_option: $ => choice(
seq(repeat($.attribute_instance), $.coverage_option),
seq(repeat($.attribute_instance), $.bins_selection),
),
bins_selection: $ => seq(
$.bins_keyword, $._bin_identifier, '=', $.select_expression,
optional(prec.right(PREC.iff, seq('iff', '(', $.expression, ')'))),
),
select_expression: $ => choice(
$.select_condition,
prec.left(PREC.UNARY, seq('!', $.select_condition)),
prec.left(PREC.LOGICAL_AND, seq($.select_expression, '&&', $.select_expression)),
prec.left(PREC.LOGICAL_OR, seq($.select_expression, '||', $.select_expression)),
prec.left(PREC.PARENT, seq('(', $.select_expression, ')')),
seq(
$.select_expression, 'with', '(', $._with_covergroup_expression, ')',
optseq('matches', $._integer_covergroup_expression),
),
$.cross_identifier,
seq(
$._cross_set_expression,
optseq('matches', $._integer_covergroup_expression),
),
),
select_condition: $ => seq(
'binsof', '(', $.bins_expression, ')',
optseq('intersect', '{', $.covergroup_range_list, '}'),
),
bins_expression: $ => choice(
$._variable_identifier,
prec.left(PREC.PARENT, seq($.cover_point_identifier, optseq('.', $._bin_identifier))),
),
covergroup_range_list: $ => sep1(',', $.covergroup_value_range),
covergroup_value_range: $ => choice(
$._covergroup_expression,
seq('[', $._covergroup_expression, ':', $._covergroup_expression, ']'),
),
_with_covergroup_expression: $ => $._covergroup_expression,
_set_covergroup_expression: $ => $._covergroup_expression,
_integer_covergroup_expression: $ => $._covergroup_expression,
_cross_set_expression: $ => $._covergroup_expression,
_covergroup_expression: $ => $.expression,
/* A.2.12 Let declarations */
let_declaration: $ => seq(
'let', $.let_identifier,
optseq('(', optional($.let_port_list), ')'),
'=', $.expression, ';',
),
let_identifier: $ => $._identifier,
let_port_list: $ => sep1(',', $.let_port_item),
let_port_item: $ => seq(
repeat($.attribute_instance),
optional($.let_formal_type1),
$.formal_port_identifier,
repeat($._variable_dimension),
optseq('=', $.expression),
),
let_formal_type1: $ => choice(
$.data_type_or_implicit1,
'untyped',
),
let_expression: $ => prec.left(seq(
optional($.package_scope),
$.let_identifier,
optseq('(', optional($.let_list_of_arguments), ')'),
)),
let_list_of_arguments: $ => choice(
// FIXME empty string
// seq(
// sep1(',', optional($.let_actual_arg)),
// repseq(',', '.', $._identifier, '(', optional($.let_actual_arg), ')')
// ),
sep1(',', seq('.', $._identifier, '(', optional($.let_actual_arg), ')')),
),
let_actual_arg: $ => $.expression,
// A.3 Primitive instances
// A.3.1 Primitive instantiation and instances
gate_instantiation: $ => seq(
choice(
seq(
$.cmos_switchtype,
optional($.delay3),
sep1(',', $.cmos_switch_instance),
),
seq(
$.enable_gatetype,
optional($.drive_strength), optional($.delay3),
sep1(',', $.enable_gate_instance),
),
seq(
$.mos_switchtype,
optional($.delay3),
sep1(',', $.mos_switch_instance),
),
seq(
$.n_input_gatetype,
optional($.drive_strength), optional($.delay2),
sep1(',', $.n_input_gate_instance),
),
seq(
$.n_output_gatetype,
optional($.drive_strength), optional($.delay2),
sep1(',', $.n_output_gate_instance),
),
seq(
$.pass_en_switchtype,
optional($.delay2),
sep1(',', $.pass_enable_switch_instance),
),
seq(
$.pass_switchtype,
sep1(',', $.pass_switch_instance),
),
seq(
'pulldown',
optional($.pulldown_strength),
sep1(',', $.pull_gate_instance),
),
seq(
'pullup',
optional($.pullup_strength),
sep1(',', $.pull_gate_instance),
),
),
';',
),
cmos_switch_instance: $ => seq(
optional($.name_of_instance),
'(',
$.output_terminal, ',',
$.input_terminal, ',',
$.ncontrol_terminal, ',',
$.pcontrol_terminal,
')',
),
enable_gate_instance: $ => seq(
optional($.name_of_instance),
'(', $.output_terminal, ',', $.input_terminal, ',', $.enable_terminal, ')',
),
mos_switch_instance: $ => seq(
optional($.name_of_instance),
'(', $.output_terminal, ',', $.input_terminal, ',', $.enable_terminal, ')',
),
n_input_gate_instance: $ => seq(
optional($.name_of_instance),
'(', $.output_terminal, ',', sep1(',', $.input_terminal), ')',
),
n_output_gate_instance: $ => seq(
optional($.name_of_instance),
'(', sep1(',', $.output_terminal), ',', $.input_terminal, ')',
),
pass_switch_instance: $ => seq(
optional($.name_of_instance),
'(', $.inout_terminal, ',', $.inout_terminal, ')',
),
pass_enable_switch_instance: $ => seq(
optional($.name_of_instance),
'(', $.inout_terminal, ',', $.inout_terminal, ',', $.enable_terminal, ')',
),
pull_gate_instance: $ => seq(
optional($.name_of_instance),
'(', $.output_terminal, ')',
),
// A.3.2 Primitive strengths
pulldown_strength: $ => choice(
seq('(', $.strength0, ',', $.strength1, ')'),
seq('(', $.strength1, ',', $.strength0, ')'),
seq('(', $.strength0, ')'),
),
pullup_strength: $ => choice(
seq(',', $.strength0, ',', $.strength1, ')'),
seq(',', $.strength1, ',', $.strength0, ')'),
seq(',', $.strength1, ')'),
),
// A.3.3 Primitive terminals
enable_terminal: $ => $.expression,
inout_terminal: $ => $.net_lvalue,
input_terminal: $ => $.expression,
ncontrol_terminal: $ => $.expression,
output_terminal: $ => $.net_lvalue,
pcontrol_terminal: $ => $.expression,
// A.3.4 Primitive gate and switch types
cmos_switchtype: $ => choice('cmos', 'rcmos'),
enable_gatetype: $ => choice('bufif0', 'bufif1', 'notif0', 'notif1'),
mos_switchtype: $ => choice('nmos', 'pmos', 'rnmos', 'rpmos'),
n_input_gatetype: $ => choice('and', 'nand', 'or', 'nor', 'xor', 'xnor'),
n_output_gatetype: $ => choice('buf', 'not'),
pass_en_switchtype: $ => choice('tranif0', 'tranif1', 'rtranif1', 'rtranif0'),
pass_switchtype: $ => choice('tran', 'rtran'),
// A.4 Instantiations
// A.4.1 Instantiation
// A.4.1.1 Module instantiation
module_instantiation: $ => seq(
$._module_identifier,
optional($.parameter_value_assignment),
sep1(',', $.hierarchical_instance),
';',
),
parameter_value_assignment: $ => seq(
'#', '(', optional($.list_of_parameter_assignments), ')',
),
list_of_parameter_assignments: $ => choice(
sep1(',', $.ordered_parameter_assignment),
sep1(',', $.named_parameter_assignment),
),
ordered_parameter_assignment: $ => alias($.param_expression, $._ordered_parameter_assignment),
named_parameter_assignment: $ => seq(
'.', $.parameter_identifier, '(', optional($.param_expression), ')',
),
hierarchical_instance: $ => seq(
$.name_of_instance, '(', optional($.list_of_port_connections), ')',
),
name_of_instance: $ => seq(
$.instance_identifier, repeat($.unpacked_dimension),
),
// Reordered
list_of_port_connections: $ => choice(
sep1(',', $.named_port_connection),
sep1(',', $.ordered_port_connection),
),
ordered_port_connection: $ => seq(
repeat($.attribute_instance),
$.expression,
),
// from spec:
// named_port_connection: $ =>
// { attribute_instance } . port_identifier [ ( [ expression ] ) ]
// | { attribute_instance } .*
named_port_connection: $ => seq(
repeat($.attribute_instance),
choice(
seq('.', $.port_identifier, optseq(
'(', optional($.expression), ')',
)),
'.*',
),
),
/* A.4.1.2 Interface instantiation */
interface_instantiation: $ => seq(
$.interface_identifier,
optional($.parameter_value_assignment),
sep1(',', $.hierarchical_instance),
';',
),
/* A.4.1.3 Program instantiation */
program_instantiation: $ => seq(
$.program_identifier,
optional($.parameter_value_assignment),
sep1(',', $.hierarchical_instance),
';',
),
/* A.4.1.4 Checker instantiation */
checker_instantiation: $ => seq(
$.ps_checker_identifier,
$.name_of_instance,
'(',
// optional($.list_of_checker_port_connections),
choice(
sep1(',', optseq(
repeat($.attribute_instance),
optional($._property_actual_arg),
)),
// sep1(',', $.named_checker_port_connection)
sep1(',', choice(
seq(
repeat($.attribute_instance), '.', $.formal_port_identifier,
optseq('(', optional($._property_actual_arg), ')'),
),
seq(
repeat($.attribute_instance), '.*',
),
)),
),
')',
';',
),
// list_of_checker_port_connections1: $ => choice(
// sep1(',', optional($.ordered_checker_port_connection1)),
// sep1(',', $.named_checker_port_connection)
// ),
// ordered_checker_port_connection: $ => seq(
// repeat($.attribute_instance),
// optional($._property_actual_arg)
// ),
// named_checker_port_connection: $ => choice(
// seq(
// repeat($.attribute_instance), '.', $.formal_port_identifier,
// optseq('(', optional($._property_actual_arg), ')')
// ),
// seq(
// repeat($.attribute_instance, '.*')
// )
// ),
/* A.4.2 Generated instantiation */
generate_region: $ => seq(
'generate', repeat($._generate_item), 'endgenerate',
),
loop_generate_construct: $ => seq(
'for', '(',
$.genvar_initialization, ';', $._genvar_expression, ';', $.genvar_iteration,
')',
$.generate_block,
),
genvar_initialization: $ => seq(
optional('genvar'),
$.genvar_identifier,
'=',
$.constant_expression,
),
genvar_iteration: $ => choice(
seq($.genvar_identifier, $.assignment_operator, $._genvar_expression),
seq($.inc_or_dec_operator, $.genvar_identifier),
seq($.genvar_identifier, $.inc_or_dec_operator),
),
_conditional_generate_construct: $ => choice(
$.if_generate_construct,
$.case_generate_construct,
),
if_generate_construct: $ => prec.left(seq(
'if', '(', $.constant_expression, ')', $.generate_block,
optseq('else', $.generate_block),
)),
case_generate_construct: $ => seq(
'case', '(', $.constant_expression, ')', $.case_generate_item,
repeat($.case_generate_item),
'endcase',
),
case_generate_item: $ => choice(
seq(sep1(',', $.constant_expression), ':', $.generate_block),
seq('default', optional(':'), $.generate_block),
),
generate_block: $ => choice(
$._generate_item,
seq(
optseq($.generate_block_identifier, ':'),
'begin',
optseq(':', $.generate_block_identifier),
repeat($._generate_item),
'end',
optseq(':', $.generate_block_identifier),
),
),
_generate_item: $ => choice(
$.module_or_generate_item,
$.interface_or_generate_item,
$._checker_or_generate_item,
),
/* A.5 UDP declaration and instantiation */
/* A.5.1 UDP declaration */
udp_nonansi_declaration: $ => seq(
repeat($.attribute_instance), 'primitive', $._udp_identifier, '(', $.udp_port_list, ')', ';',
),
udp_ansi_declaration: $ => seq(
repeat($.attribute_instance), 'primitive', $._udp_identifier, '(', $.udp_declaration_port_list, ')', ';',
),
udp_declaration: $ => choice(
seq(
$.udp_nonansi_declaration, $.udp_port_declaration, repeat($.udp_port_declaration),
$._udp_body,
'endprimitive', optseq(':', $._udp_identifier),
),
seq($.udp_ansi_declaration, $._udp_body, 'endprimitive', optseq(':', $._udp_identifier)),
seq('extern', $.udp_nonansi_declaration),
seq('extern', $.udp_ansi_declaration),
seq(
repeat($.attribute_instance), 'primitive', $._udp_identifier, '(', '.*', ')', ';',
repeat($.udp_port_declaration),
$._udp_body,
'endprimitive', optseq(':', $._udp_identifier),
),
),
/* A.5.2 UDP ports */
udp_port_list: $ => seq(
$.output_port_identifier, ',', sep1(',', $.input_port_identifier),
),
udp_declaration_port_list: $ => seq(
$.udp_output_declaration, ',', sep1(',', $.udp_input_declaration),
),
udp_port_declaration: $ => seq(
choice(
$.udp_output_declaration,
$.udp_input_declaration,
$.udp_reg_declaration,
),
';',
),
udp_output_declaration: $ => seq(
repeat($.attribute_instance),
'output',
choice(
$.port_identifier,
seq('reg', $.port_identifier, optseq('=', $.constant_expression)),
),
),
udp_input_declaration: $ => seq(
repeat($.attribute_instance), 'input', $.list_of_udp_port_identifiers,
),
udp_reg_declaration: $ => seq(
repeat($.attribute_instance), 'reg', $._variable_identifier,
),
/* A.5.3 UDP body */
_udp_body: $ => choice($.combinational_body, $.sequential_body),
combinational_body: $ => seq(
'table', repeat1($.combinational_entry), 'endtable',
),
combinational_entry: $ => seq($.level_input_list, ':', $.output_symbol, ';'),
sequential_body: $ => seq(
optional($.udp_initial_statement),
'table', repeat1($.sequential_entry), 'endtable',
),
udp_initial_statement: $ => seq(
'initial', $.output_port_identifier, '=', $.init_val, ';',
),
init_val: $ => choice(
'1\'b0', '1\'b1', '1\'bx', '1\'bX', '1\'B0', '1\'B1', '1\'Bx', '1\'BX', '1', '0',
),
sequential_entry: $ => seq(
$._seq_input_list, ':', $._current_state, ':', $.next_state, ';',
),
_seq_input_list: $ => choice($.level_input_list, $.edge_input_list),
level_input_list: $ => repeat1($.level_symbol),
edge_input_list: $ => seq(repeat($.level_symbol), $.edge_indicator, repeat($.level_symbol)),
edge_indicator: $ => choice(
seq('(', $.level_symbol, $.level_symbol, ')'),
$.edge_symbol,
),
_current_state: $ => $.level_symbol,
next_state: $ => choice($.output_symbol, '-'),
output_symbol: $ => /[01xX]/,
level_symbol: $ => /[01xX?bB]/,
edge_symbol: $ => /[rRfFpPnN*]/,
/* A.5.4 UDP instantiation */
udp_instantiation: $ => seq(
$._udp_identifier,
optional($.drive_strength),
optional($.delay2),
sep1(',', $.udp_instance),
';',
),
udp_instance: $ => seq(
optional($.name_of_instance),
'(', $.output_terminal, ',', sep1(',', $.input_terminal), ')',
),
// A.6 Behavioral statements
// A.6.1 Continuous assignment and net alias statements
continuous_assign: $ => seq(
'assign',
choice(
seq(
optional($.drive_strength),
optional($.delay3),
$.list_of_net_assignments,
),
seq(
optional($.delay_control),
$.list_of_variable_assignments,
),
),
';',
),
list_of_net_assignments: $ => sep1(',', $.net_assignment),
list_of_variable_assignments: $ => sep1(',', $.variable_assignment),
net_alias: $ => prec.left(PREC.ASSIGN, seq(
'alias', $.net_lvalue, '=', sep1(',', seq('=', $.net_lvalue)), ';',
)),
net_assignment: $ => prec.left(PREC.ASSIGN,
seq($.net_lvalue, '=', $.expression),
),
// A.6.2 Procedural blocks and assignments
initial_construct: $ => seq('initial', $.statement_or_null),
always_construct: $ => seq($.always_keyword, $.statement),
always_keyword: $ => choice(
'always', 'always_comb', 'always_latch', 'always_ff',
),
final_construct: $ => seq('final', $.function_statement),
blocking_assignment: $ => choice(
prec.left(PREC.ASSIGN, seq(
$.variable_lvalue, '=', $.delay_or_event_control, $.expression,
)),
prec.left(PREC.ASSIGN, seq(
$.nonrange_variable_lvalue, '=', $.dynamic_array_new,
)),
// seq(
// optional(choice(
// seq($.implicit_class_handle, '.'),
// $.class_scope,
// $.package_scope
// )),
// $._hierarchical_variable_identifier
// $.select,
// '=',
// $.class_new
// ),
$.operator_assignment,
),
operator_assignment: $ => prec.left(PREC.ASSIGN,
seq($.variable_lvalue, $.assignment_operator, $.expression),
),
assignment_operator: $ => choice(
'=', '+=', '-=', '*=', '/=', '%=', '&=', '|=', '^=', '<<=', '>>=', '<<<=', '>>>=',
),
nonblocking_assignment: $ => prec.left(PREC.ASSIGN, seq(
$.variable_lvalue,
'<=',
optional($.delay_or_event_control),
$.expression,
)),
procedural_continuous_assignment: $ => choice(
seq('assign', $.variable_assignment),
seq('deassign', $.variable_lvalue),
seq('force', $.variable_assignment),
seq('force', $.net_assignment),
seq('release', $.variable_lvalue),
seq('release', $.net_lvalue),
),
variable_assignment: $ => prec.left(PREC.ASSIGN, seq(
$.variable_lvalue,
'=',
$.expression,
)),
// A.6.3 Parallel and sequential blocks
action_block: $ => choice(
$.statement_or_null,
seq(optional($.statement), 'else', $.statement_or_null),
),
seq_block: $ => seq(
'begin', optseq(':', $._block_identifier),
repeat($.block_item_declaration),
repeat($.statement_or_null),
'end', optseq(':', $._block_identifier),
),
par_block: $ => seq(
'fork', optseq(':', $._block_identifier),
repeat($.block_item_declaration),
repeat($.statement_or_null),
$.join_keyword, optseq(':', $._block_identifier),
),
join_keyword: $ => choice('join', 'join_any', 'join_none'),
// A.6.4 Statements
statement_or_null: $ => choice(
$.statement,
seq(repeat($.attribute_instance), ';'),
),
statement: $ => seq(
optseq($._block_identifier, ':'),
repeat($.attribute_instance),
$.statement_item,
),
statement_item: $ => choice(
seq($.blocking_assignment, ';'),
seq($.nonblocking_assignment, ';'),
seq($.procedural_continuous_assignment, ';'),
seq($.system_tf_call, ';'),
$.case_statement,
$.conditional_statement,
seq($.inc_or_dec_expression, ';'),
// $.subroutine_call_statement,
$.disable_statement,
$.event_trigger,
$.loop_statement,
$.jump_statement,
$.par_block,
$.seq_block,
$.procedural_timing_control_statement,
$.wait_statement,
$._procedural_assertion_statement,
seq($.clocking_drive, ';'),
// $.randsequence_statement,
$.randcase_statement,
$.expect_property_statement,
),
function_statement: $ => $.statement,
function_statement_or_null: $ => choice(
$.function_statement,
seq(repeat($.attribute_instance), ';'),
),
variable_identifier_list: $ => sep1(',', $._variable_identifier),
// A.6.5 Timing control statements
procedural_timing_control_statement: $ => seq(
$._procedural_timing_control, $.statement_or_null, // statement_or_null1
),
delay_or_event_control: $ => choice(
$.delay_control,
$.event_control,
seq('repeat', '(', $.expression, ')', $.event_control),
),
delay_control: $ => seq('#', choice(
$.delay_value,
seq('(', $.mintypmax_expression, ')'),
)),
event_control: $ => choice(
seq('@', $._hierarchical_event_identifier),
seq('@', '(', $.event_expression, ')'),
'@*',
seq('@', '(', '*', ')'),
seq('@', $.ps_or_hierarchical_sequence_identifier),
),
event_expression: $ => choice( // reordered : brake recursion
prec.left(seq($.event_expression, 'or', $.event_expression)),
prec.left(seq($.event_expression, ',', $.event_expression)),
seq(
optional($.edge_identifier),
$.expression,
), // reordered : help parser
// seq(
// optional($.edge_identifier),
// $.expression,
// optseq('iff', $.expression)
// ),
// seq(
// $.sequence_instance,
// optseq('iff', $.expression)
// ),
// seq('(', $.event_expression, ')')
),
// event_expression_2: $ => choice( // reordered : help parser
// seq($.edge_identifier, $.expression), // reordered : help parser
// seq(
// optional($.edge_identifier),
// $.expression,
// optseq('iff', $.expression)
// ),
// // seq(
// // $.sequence_instance,
// // optseq('iff', $.expression)
// // ),
// seq('(', $.event_expression, ')')
// ),
_procedural_timing_control: $ => choice(
$.delay_control,
$.event_control,
$.cycle_delay,
),
jump_statement: $ => choice(
seq('return', optional($.expression), ';'),
seq('break', ';'),
seq('continue', ';'),
),
wait_statement: $ => choice(
seq('wait', '(', $.expression, ')', $.statement_or_null),
seq('wait', 'fork', ';'),
seq('wait_order', '(', sep1(',', $.hierarchical_identifier), ')', $.action_block),
),
event_trigger: $ => choice(
seq('->', $._hierarchical_event_identifier, ';'),
seq('->>', optional($.delay_or_event_control), $._hierarchical_event_identifier, ';'),
),
disable_statement: $ => choice(
seq('disable', $._hierarchical_task_identifier, ';'),
seq('disable', $._hierarchical_block_identifier, ';'),
seq('disable', 'fork', ';'),
),
// A.6.6 Conditional statements
conditional_statement: $ => prec.left(seq(
optional($.unique_priority),
'if', '(', $.cond_predicate, ')', $.statement_or_null,
// repseq('else', 'if', '(', $.cond_predicate, ')', $.statement_or_null),
optseq('else', $.statement_or_null),
)),
unique_priority: $ => choice('unique', 'unique0', 'priority'),
cond_predicate: $ => psep1(PREC.PARENT, '&&&', $._expression_or_cond_pattern), // FIXME precedence
_expression_or_cond_pattern: $ => choice(
$.expression,
$.cond_pattern,
),
cond_pattern: $ => prec.left(PREC.MATCHES, seq($.expression, 'matches', $.pattern)),
// A.6.7 Case statements
case_statement: $ => seq(
optional($.unique_priority),
seq(
$.case_keyword,
'(', $.case_expression, ')',
choice(
repeat1($.case_item),
seq('matches', repeat1($.case_pattern_item)),
seq('inside', repeat1($.case_inside_item)), // only case
),
),
'endcase',
),
case_keyword: $ => choice('case', 'casez', 'casex'),
case_expression: $ => $.expression,
case_item: $ => choice(
seq(sep1(',', $.case_item_expression), ':', $.statement_or_null),
seq('default', optional(':'), $.statement_or_null),
),
case_pattern_item: $ => choice(
seq($.pattern, optseq('&&&', $.expression), ':', $.statement_or_null),
seq('default', optional(':'), $.statement_or_null),
),
case_inside_item: $ => choice(
seq($.open_range_list, ':', $.statement_or_null),
seq('default', optional(':'), $.statement_or_null),
),
case_item_expression: $ => $.expression,
randcase_statement: $ => seq(
'randcase', $.randcase_item, repeat($.randcase_item), 'endcase',
),
randcase_item: $ => seq($.expression, ':', $.statement_or_null),
open_range_list: $ => sep1(',', $.open_value_range),
open_value_range: $ => $.value_range,
// A.6.7.1 Patterns
pattern: $ => choice(
seq('.', $._variable_identifier),
'.*',
$.constant_expression,
seq('tagged', $.member_identifier, optional($.pattern)),
seq('\'{', sep1(',', $.pattern), '}'),
seq('\'{', sep1(',', seq($.member_identifier, ':', $.pattern)), '}'),
),
assignment_pattern: $ => seq(
'\'{',
choice(
sep1(',', $.expression),
// sep1(',', seq($._structure_pattern_key, ':', $.expression)),
sep1(',', seq($._array_pattern_key, ':', $.expression)),
seq($.constant_expression, '{', sep1(',', $.expression), '}'),
),
'}',
),
_structure_pattern_key: $ => choice(
$.member_identifier,
$.assignment_pattern_key,
),
_array_pattern_key: $ => choice(
$.constant_expression,
$.assignment_pattern_key,
),
assignment_pattern_key: $ => choice(
$._simple_type,
'default',
),
assignment_pattern_expression: $ => seq(
optional($._assignment_pattern_expression_type), $.assignment_pattern,
),
_assignment_pattern_expression_type: $ => choice(
$.ps_type_identifier,
// $.ps_parameter_identifier,
$.integer_atom_type,
$.type_reference,
),
constant_assignment_pattern_expression: $ => $.assignment_pattern_expression,
assignment_pattern_net_lvalue: $ => seq(
'\'{', sep1(',', $.net_lvalue), '}',
),
assignment_pattern_variable_lvalue: $ => seq(
'\'{', sep1(',', $.variable_lvalue), '}',
),
// A.6.8 Looping statements
loop_statement: $ => choice(
seq('forever', $.statement_or_null),
seq('repeat', '(', $.expression, ')', $.statement_or_null),
seq('while', '(', $.expression, ')', $.statement_or_null),
seq(
'for', '(',
optional($.for_initialization), ';',
optional($.expression), ';',
optional($.for_step),
')',
$.statement_or_null,
),
seq('do', $.statement_or_null, 'while', '(', $.expression, ')', ';'),
seq(
'foreach', '(',
$.ps_or_hierarchical_array_identifier,
'[',
optional($.loop_variables1),
']',
')',
$.statement,
),
),
for_initialization: $ => choice(
$.list_of_variable_assignments,
sep1(',', $.for_variable_declaration),
),
for_variable_declaration: $ => seq(
optional('var'), $.data_type,
sep1(',', seq(
$._variable_identifier, '=', $.expression,
)),
),
for_step: $ => sep1(',', $._for_step_assignment),
_for_step_assignment: $ => choice(
$.operator_assignment,
$.inc_or_dec_expression,
$.function_subroutine_call,
),
loop_variables1: $ => seq(
$.index_variable_identifier,
repseq(',', optional($.index_variable_identifier)),
),
// A.6.9 Subroutine call statements
subroutine_call_statement: $ => choice(
seq($.subroutine_call, ';'),
seq('void\'', '(', $.function_subroutine_call, ')', ';'),
),
// A.6.10 Assertion statements
_assertion_item: $ => choice(
$.concurrent_assertion_item,
$.deferred_immediate_assertion_item,
),
deferred_immediate_assertion_item: $ => seq(
optseq(
$._block_identifier, ':',
),
$._deferred_immediate_assertion_statement,
),
_procedural_assertion_statement: $ => choice(
$._concurrent_assertion_statement,
$._immediate_assertion_statement,
$.checker_instantiation,
),
_immediate_assertion_statement: $ => choice(
$._simple_immediate_assertion_statement,
$._deferred_immediate_assertion_statement,
),
_simple_immediate_assertion_statement: $ => choice(
$.simple_immediate_assert_statement,
$.simple_immediate_assume_statement,
$.simple_immediate_cover_statement,
),
simple_immediate_assert_statement: $ => seq(
'assert', '(', $.expression, ')', $.action_block,
),
simple_immediate_assume_statement: $ => seq(
'assume', '(', $.expression, ')', $.action_block,
),
simple_immediate_cover_statement: $ => seq(
'cover', '(', $.expression, ')', $.statement_or_null,
),
_deferred_immediate_assertion_statement: $ => choice(
$.deferred_immediate_assert_statement,
$.deferred_immediate_assume_statement,
$.deferred_immediate_cover_statement,
),
deferred_immediate_assert_statement: $ => seq(
'assert',
choice('#0', 'final'),
'(', $.expression, ')', $.action_block,
),
deferred_immediate_assume_statement: $ => seq(
'assume',
choice('#0', 'final'),
'(', $.expression, ')', $.action_block,
),
deferred_immediate_cover_statement: $ => seq(
'cover',
choice('#0', 'final'),
'(', $.expression, ')', $.statement_or_null,
),
/* A.6.11 Clocking block */
clocking_declaration: $ => choice(
seq(
optional('default'),
'clocking', optional($.clocking_identifier), $.clocking_event, ';',
repeat($.clocking_item),
'endclocking', optseq(':', $.clocking_identifier),
),
seq(
'global',
'clocking', optional($.clocking_identifier), $.clocking_event, ';',
'endclocking', optseq(':', $.clocking_identifier),
),
),
clocking_event: $ => seq('@', choice(
$._identifier,
seq('(', $.event_expression, ')'),
)),
clocking_item: $ => choice(
seq('default', $.default_skew, ';'),
seq($.clocking_direction, $.list_of_clocking_decl_assign, ';'),
seq(repeat($.attribute_instance), $._assertion_item_declaration),
),
default_skew: $ => choice(
seq('input', $.clocking_skew),
seq('output', $.clocking_skew),
seq('input', $.clocking_skew, 'output', $.clocking_skew),
),
clocking_direction: $ => choice(
seq('input', optional($.clocking_skew)),
seq('output', optional($.clocking_skew)),
seq('input', optional($.clocking_skew), 'output', optional($.clocking_skew)),
seq('inout'),
),
list_of_clocking_decl_assign: $ => sep1(',', $.clocking_decl_assign),
clocking_decl_assign: $ => seq($._signal_identifier, optseq('=', $.expression)),
clocking_skew: $ => choice(
seq($.edge_identifier, optional($.delay_control)),
$.delay_control,
),
clocking_drive: $ => prec.left(PREC.ASSIGN,
seq($.clockvar_expression, '<=', optional($.cycle_delay), $.expression),
),
cycle_delay: $ => prec.left(seq('##', choice(
$.integral_number,
$._identifier,
seq('(', $.expression, ')'),
))),
clockvar: $ => $.hierarchical_identifier,
clockvar_expression: $ => seq(
$.clockvar,
optional($.select1),
),
// A.6.12 Randsequence
// randsequence_statement = randsequence ( [ production_identifier ] )
// production { production }
// endsequence
// production
// = [ data_type_or_void ] production_identifier
// [ ( tf_port_list ) ] : rs_rule { | rs_rule } ;
// rs_rule = rs_production_list [ := weight_specification [ rs_code_block ] ]
// rs_production_list =
// rs_prod { rs_prod }
// | rand join [ ( expression ) ] production_item
// production_item { production_item }
// weight_specification =
// integral_number
// | ps_identifier
// | ( expression )
// rs_code_block = { { data_declaration } { statement_or_null } }
// rs_prod =
// production_item
// | rs_code_block
// | rs_if_else
// | rs_repeat
// | rs_case
// production_item = production_identifier [ ( list_of_arguments ) ]
// rs_if_else = if ( expression ) production_item [ else production_item ]
// rs_repeat = repeat ( expression ) production_item
// rs_case = case ( case_expression ) rs_case_item { rs_case_item } endcase
// rs_case_item =
// case_item_expression { , case_item_expression } : production_item ;
// | default [ : ] production_item ;
// A.7 Specify section
// A.7.1 Specify block declaration
specify_block: $ => seq('specify', repeat($._specify_item), 'endspecify'),
_specify_item: $ => choice(
$.specparam_declaration,
$.pulsestyle_declaration,
$.showcancelled_declaration,
$.path_declaration,
$._system_timing_check,
),
pulsestyle_declaration: $ => seq(
choice('pulsestyle_onevent', 'pulsestyle_ondetect'),
$.list_of_path_outputs,
';',
),
showcancelled_declaration: $ => seq(
choice('showcancelled', 'noshowcancelled'),
$.list_of_path_outputs,
';',
),
// A.7 Specify section
// A.7.1 Specify block declaration
// A.7.2 Specify path declarations
path_declaration: $ => seq(
choice(
$.simple_path_declaration,
$.edge_sensitive_path_declaration,
$.state_dependent_path_declaration,
),
';',
),
simple_path_declaration: $ => seq(
choice($.parallel_path_description, $.full_path_description),
'=',
$.path_delay_value,
),
parallel_path_description: $ => seq(
'(',
$.specify_input_terminal_descriptor,
optional($.polarity_operator),
'=>',
$.specify_output_terminal_descriptor,
')',
),
full_path_description: $ => seq(
'(',
$.list_of_path_inputs,
optional($.polarity_operator),
'*>',
$.list_of_path_outputs,
')',
),
list_of_path_inputs: $ => sep1(',', $.specify_input_terminal_descriptor),
list_of_path_outputs: $ => sep1(',', $.specify_output_terminal_descriptor),
// A.7.3 Specify block terminals
specify_input_terminal_descriptor: $ => seq(
$.input_identifier, optseq('[', $._constant_range_expression, ']'),
),
specify_output_terminal_descriptor: $ => seq(
$.output_identifier, optseq('[', $._constant_range_expression, ']'),
),
input_identifier: $ => choice(
$.input_port_identifier,
$.inout_port_identifier,
seq($.interface_identifier, '.', $.port_identifier), // FIXME glue dot?
),
output_identifier: $ => choice(
$.output_port_identifier,
$.inout_port_identifier,
seq($.interface_identifier, '.', $.port_identifier),
),
/* A.7.4 Specify path delays */
path_delay_value: $ => choice(
$.list_of_path_delay_expressions,
seq('(', $.list_of_path_delay_expressions, ')'),
),
list_of_path_delay_expressions: $ => sep1(',', $.path_delay_expression),
// list_of_path_delay_expressions: $ => choice(
// $.t_path_delay_expression,
// seq($.trise_path_delay_expression, ',', $.tfall_path_delay_expression),
// seq(
// $.trise_path_delay_expression, ',', $.tfall_path_delay_expression, ',',
// $.tz_path_delay_expression
// ),
// seq(
// $.t01_path_delay_expression, ',', $.t10_path_delay_expression, ',',
// $.t0z_path_delay_expression, ',', $.tz1_path_delay_expression, ',',
// $.t1z_path_delay_expression, ',', $.tz0_path_delay_expression
// ),
// seq(
// $.t01_path_delay_expression, ',', $.t10_path_delay_expression, ',',
// $.t0z_path_delay_expression, ',', $.tz1_path_delay_expression, ',',
// $.t1z_path_delay_expression, ',', $.tz0_path_delay_expression, ',',
// $.t0x_path_delay_expression, ',', $.tx1_path_delay_expression, ',',
// $.t1x_path_delay_expression, ',', $.tx0_path_delay_expression, ',',
// $.txz_path_delay_expression, ',', $.tzx_path_delay_expression
// )
// ),
//
// t_path_delay_expression: $ => alias($.path_delay_expression, $.t_path_delay_expression),
// trise_path_delay_expression: $ => alias($.path_delay_expression, $.trise_path_delay_expression),
// tfall_path_delay_expression: $ => alias($.path_delay_expression, $.tfall_path_delay_expression),
// tz_path_delay_expression: $ => alias($.path_delay_expression, $.tz_path_delay_expression),
// t01_path_delay_expression: $ => alias($.path_delay_expression, $.t01_path_delay_expression),
// t10_path_delay_expression: $ => alias($.path_delay_expression, $.t10_path_delay_expression),
// t0z_path_delay_expression: $ => alias($.path_delay_expression, $.t0z_path_delay_expression),
// tz1_path_delay_expression: $ => alias($.path_delay_expression, $.tz1_path_delay_expression),
// t1z_path_delay_expression: $ => alias($.path_delay_expression, $.t1z_path_delay_expression),
// tz0_path_delay_expression: $ => alias($.path_delay_expression, $.tz0_path_delay_expression),
// t0x_path_delay_expression: $ => alias($.path_delay_expression, $.t0x_path_delay_expression),
// tx1_path_delay_expression: $ => alias($.path_delay_expression, $.tx1_path_delay_expression),
// t1x_path_delay_expression: $ => alias($.path_delay_expression, $.t1x_path_delay_expression),
// tx0_path_delay_expression: $ => alias($.path_delay_expression, $.tx0_path_delay_expression),
// txz_path_delay_expression: $ => alias($.path_delay_expression, $.txz_path_delay_expression),
// tzx_path_delay_expression: $ => alias($.path_delay_expression, $.tzx_path_delay_expression),
path_delay_expression: $ => $.constant_mintypmax_expression,
edge_sensitive_path_declaration: $ => seq(
choice(
$.parallel_edge_sensitive_path_description,
$.full_edge_sensitive_path_description,
),
'=', $.path_delay_value,
),
parallel_edge_sensitive_path_description: $ => seq(
'(',
optional($.edge_identifier),
$.specify_input_terminal_descriptor,
optional($.polarity_operator),
'=>',
'(',
$.specify_output_terminal_descriptor,
optional($.polarity_operator),
':',
$.data_source_expression,
')',
')',
),
full_edge_sensitive_path_description: $ => seq(
'(',
optional($.edge_identifier),
$.list_of_path_inputs,
optional($.polarity_operator),
'*>',
'(',
$.list_of_path_outputs,
optional($.polarity_operator),
':',
$.data_source_expression,
')',
')',
),
data_source_expression: $ => $.expression,
edge_identifier: $ => choice('posedge', 'negedge', 'edge'),
state_dependent_path_declaration: $ => choice(
seq('if', '(', $.module_path_expression, ')', $.simple_path_declaration),
seq('if', '(', $.module_path_expression, ')', $.edge_sensitive_path_declaration),
seq('ifnone', $.simple_path_declaration),
),
polarity_operator: $ => choice('+', '-'),
/* A.7.5 System timing checks */
/* A.7.5.1 System timing check commands */
_system_timing_check: $ => choice(
$.$setup_timing_check,
$.$hold_timing_check,
$.$setuphold_timing_check,
$.$recovery_timing_check,
$.$removal_timing_check,
$.$recrem_timing_check,
$.$skew_timing_check,
$.$timeskew_timing_check,
$.$fullskew_timing_check,
$.$period_timing_check,
$.$width_timing_check,
$.$nochange_timing_check,
),
$setup_timing_check: $ => seq(
'$setup', '(',
$.data_event, ',', $.reference_event, ',', $.timing_check_limit,
optseq(',', optional($.notifier)),
')', ';',
),
$hold_timing_check: $ => seq(
'$hold', '(',
$.reference_event, ',', $.data_event, ',', $.timing_check_limit,
optseq(',', optional($.notifier)),
')', ';',
),
$setuphold_timing_check: $ => seq(
'$setuphold', '(',
$.reference_event, ',', $.data_event, ',', $.timing_check_limit, ',', $.timing_check_limit,
optseq(
',',
optional($.notifier),
optseq(
',',
optional($.timestamp_condition),
optseq(
',',
optional($.timecheck_condition),
optseq(
',',
optional($.delayed_reference),
optseq(
',',
optional($.delayed_data),
),
),
),
),
),
')', ';',
),
$recovery_timing_check: $ => seq(
'$recovery', '(',
$.reference_event, ',', $.data_event, ',', $.timing_check_limit,
optseq(',', optional($.notifier)),
')', ';',
),
$removal_timing_check: $ => seq(
'$removal', '(',
$.reference_event, ',', $.data_event, ',', $.timing_check_limit,
optseq(',', optional($.notifier)),
')', ';',
),
$recrem_timing_check: $ => seq(
'$recrem', '(',
$.reference_event, ',', $.data_event, ',', $.timing_check_limit, ',', $.timing_check_limit,
optseq(
',',
optional($.notifier),
optseq(',',
optional($.timestamp_condition),
optseq(',', optional($.timecheck_condition)),
optseq(
',',
optional($.delayed_reference),
optseq(',', optional($.delayed_data)),
),
),
),
')', ';',
),
$skew_timing_check: $ => seq(
'$skew', '(',
$.reference_event, ',', $.data_event, ',', $.timing_check_limit,
optseq(',', optional($.notifier)),
')', ';',
),
$timeskew_timing_check: $ => seq(
'$timeskew', '(',
$.reference_event, ',', $.data_event, ',', $.timing_check_limit,
optseq(',',
optional($.notifier),
optseq(',',
optional($.event_based_flag),
optseq(',', optional($.remain_active_flag)),
),
),
')', ';',
),
$fullskew_timing_check: $ => seq(
'$fullskew', '(',
$.reference_event, ',', $.data_event, ',', $.timing_check_limit, ',', $.timing_check_limit,
optseq(',',
optional($.notifier),
optseq(',',
optional($.event_based_flag),
optseq(',', optional($.remain_active_flag)),
),
),
')', ';',
),
$period_timing_check: $ => seq(
'$period', '(', $.controlled_reference_event, ',', $.timing_check_limit,
optseq(',', optional($.notifier)),
')', ';',
),
$width_timing_check: $ => seq(
'$width', '(',
$.controlled_reference_event, ',', $.timing_check_limit, ',', $.threshold,
optseq(',', optional($.notifier)),
')', ';',
),
$nochange_timing_check: $ => seq(
'$nochange', '(',
$.reference_event, ',', $.data_event, ',', $.start_edge_offset, ',', $.end_edge_offset,
optseq(',', optional($.notifier)),
')', ';',
),
// A.7.5.2 System timing check command arguments
timecheck_condition: $ => $.mintypmax_expression,
controlled_reference_event: $ => alias($.controlled_timing_check_event, $.controlled_reference_event),
data_event: $ => $.timing_check_event,
delayed_data: $ => seq(
$.terminal_identifier, optional($.constant_mintypmax_expression),
),
delayed_reference: $ => seq(
$.terminal_identifier, optional($.constant_mintypmax_expression),
),
end_edge_offset: $ => $.mintypmax_expression,
event_based_flag: $ => $.constant_expression,
notifier: $ => $._variable_identifier,
reference_event: $ => $.timing_check_event,
remain_active_flag: $ => $.constant_mintypmax_expression,
timestamp_condition: $ => $.mintypmax_expression,
start_edge_offset: $ => $.mintypmax_expression,
threshold: $ => $.constant_expression,
timing_check_limit: $ => $.expression,
// A.7.5.3 System timing check event definitions
timing_check_event: $ => seq(
optional($.timing_check_event_control),
$._specify_terminal_descriptor,
optseq('&&&', $.timing_check_condition),
),
controlled_timing_check_event: $ => seq(
$.timing_check_event_control,
$._specify_terminal_descriptor,
optseq('&&&', $.timing_check_condition),
),
timing_check_event_control: $ => choice(
'posedge', 'negedge', 'edge', $.edge_control_specifier,
),
_specify_terminal_descriptor: $ => choice(
$.specify_input_terminal_descriptor,
$.specify_output_terminal_descriptor,
),
edge_control_specifier: $ => seq(
'edge', '[', sep1(',', $.edge_descriptor), ']',
),
// Note: Embedded spaces are illegal.
edge_descriptor: $ => choice(
'01',
'10',
/[xXzZ][01]/,
/[01][xXzZ]/,
),
timing_check_condition: $ => choice(
$.scalar_timing_check_condition,
seq('(', $.scalar_timing_check_condition, ')'),
),
scalar_timing_check_condition: $ => choice(
$.expression,
seq('~', $.expression),
seq($.expression, '==', $.scalar_constant),
seq($.expression, '===', $.scalar_constant),
seq($.expression, '!=', $.scalar_constant),
seq($.expression, '!==', $.scalar_constant),
),
scalar_constant: $ => choice(
'1\'b0',
'1\'b1',
'1\'B0',
'1\'B1',
'\'b0',
'\'b1',
'\'B0',
'\'B1',
'1',
'0',
),
// A.8 Expressions
// A.8.1 Concatenations
concatenation: $ => seq(
'{', psep1(PREC.CONCAT, ',', $.expression), '}',
),
constant_concatenation: $ => seq(
'{', psep1(PREC.CONCAT, ',', $.constant_expression), '}',
),
constant_multiple_concatenation: $ => prec.left(PREC.CONCAT, seq(
'{', $.constant_expression, $.constant_concatenation, '}',
)),
module_path_concatenation: $ => seq(
'{', psep1(PREC.CONCAT, ',', $.module_path_expression), '}',
),
module_path_multiple_concatenation: $ => prec.left(PREC.CONCAT, seq(
'{', $.constant_expression, $.module_path_concatenation, '}',
)),
multiple_concatenation: $ => prec.left(PREC.CONCAT, seq(
'{', $.expression, $.concatenation, '}',
)),
streaming_concatenation: $ => prec.left(PREC.CONCAT, seq(
'{', $.stream_operator, optional($.slice_size), $.stream_concatenation, '}',
)),
stream_operator: $ => choice('>>', '<<'),
slice_size: $ => choice($._simple_type, $.constant_expression),
stream_concatenation: $ => prec.left(PREC.CONCAT, seq(
'{', sep1(',', $.stream_expression), '}',
)),
stream_expression: $ => seq($.expression, optseq('with', '[', $.array_range_expression, ']')),
array_range_expression: $ => seq(
$.expression,
optional(choice(
seq(':', $.expression),
seq('+:', $.expression),
seq('-:', $.expression),
)),
),
empty_unpacked_array_concatenation: $ => seq('{', '}'),
/* A.8.2 Subroutine calls */
constant_function_call: $ => $.function_subroutine_call,
tf_call: $ => prec.left(seq(
$._hierarchical_tf_identifier, // FIXME
// $.ps_or_hierarchical_tf_identifier,
repeat($.attribute_instance),
optional($.list_of_arguments_parent),
)),
system_tf_call: $ => prec.left(seq(
$.system_tf_identifier,
optional(choice(
$.list_of_arguments_parent,
seq(
'(',
choice(
seq($.data_type, optseq(',', $.expression)),
prec.left(seq(
sep1(',', $.expression),
optseq(',', optional($.clocking_event)),
)),
),
')',
),
)),
)),
subroutine_call: $ => choice(
$.tf_call,
$.system_tf_call,
$.method_call,
seq(optseq('std', '::'), $.randomize_call),
),
function_subroutine_call: $ => $.subroutine_call,
list_of_arguments: $ => choice(
// seq(
// sep1(',', optional($.expression)),
// repseq(',', '.', $._identifier, '(', optional($.expression), ')')
// ),
sep1(',', seq('.', $._identifier, '(', optional($.expression), ')')),
),
list_of_arguments_parent: $ => seq(
'(',
choice(
sep1(',', $.expression),
// sep1(',', optional($.expression)), // FIXME
seq(
repseq(',', '.', $._identifier, '(', optional($.expression), ')'),
),
sep1(',', seq(',', '.', $._identifier, '(', optional($.expression), ')')),
),
')',
),
method_call: $ => seq($._method_call_root, '.', $.method_call_body),
method_call_body: $ => choice(
prec.left(seq(
$.method_identifier,
repeat($.attribute_instance),
optional($.list_of_arguments_parent),
)),
$._built_in_method_call,
),
_built_in_method_call: $ => choice(
$.array_manipulation_call,
$.randomize_call,
),
array_manipulation_call: $ => prec.left(seq(
$.array_method_name,
repeat($.attribute_instance),
optional($.list_of_arguments_parent),
optseq('with', '(', $.expression, ')'),
)),
randomize_call: $ => prec.left(seq(
'randomize',
repeat($.attribute_instance),
optseq(
'(',
optional(choice(
$.variable_identifier_list,
'null',
)),
')',
),
optseq(
'with',
optseq(
'(',
optional($.identifier_list),
')',
),
$.constraint_block,
),
)),
_method_call_root: $ => choice($.primary, $.implicit_class_handle),
array_method_name: $ => choice(
$.method_identifier, 'unique', 'and', 'or', 'xor',
),
// A.8.3 Expressions
inc_or_dec_expression: $ => choice(
seq($.inc_or_dec_operator, repeat($.attribute_instance), $.variable_lvalue),
seq($.variable_lvalue, repeat($.attribute_instance), $.inc_or_dec_operator),
),
conditional_expression: $ => prec.right(PREC.CONDITIONAL, seq(
$.cond_predicate,
'?',
repeat($.attribute_instance), $.expression,
':',
$.expression,
)),
constant_expression: $ => choice(
$.constant_primary,
prec.left(PREC.UNARY, seq(
$.unary_operator, repeat($.attribute_instance), $.constant_primary,
)),
constExprOp($, PREC.ADD, choice('+', '-')),
constExprOp($, PREC.MUL, choice('*', '/', '%')),
constExprOp($, PREC.EQUAL, choice('==', '!=', '===', '!==', '==?', '!=?')),
constExprOp($, PREC.LOGICAL_AND, '&&'),
constExprOp($, PREC.LOGICAL_OR, '||'),
constExprOp($, PREC.POW, '**'),
constExprOp($, PREC.RELATIONAL, choice('<', '<=', '>', '>=')),
constExprOp($, PREC.AND, '&'),
constExprOp($, PREC.OR, '|'),
constExprOp($, PREC.XOR, choice('^', '^~', '~^')),
constExprOp($, PREC.SHIFT, choice('>>', '<<', '>>>', '<<<')),
constExprOp($, PREC.IMPLICATION, choice('->', '<->')),
prec.right(PREC.CONDITIONAL, seq(
$.constant_expression,
'?',
repeat($.attribute_instance), $.constant_expression,
':',
$.constant_expression,
)),
),
constant_mintypmax_expression: $ => seq(
$.constant_expression,
optseq(':', $.constant_expression, ':', $.constant_expression),
),
constant_param_expression: $ => choice(
$.constant_mintypmax_expression,
$.data_type,
'$',
),
param_expression: $ => choice(
$.mintypmax_expression,
$.data_type,
'$',
),
_constant_range_expression: $ => choice(
$.constant_expression,
$._constant_part_select_range,
),
_constant_part_select_range: $ => choice(
$.constant_range,
$.constant_indexed_range,
),
constant_range: $ => seq($.constant_expression, ':', $.constant_expression),
constant_indexed_range: $ => seq(
$.constant_expression, choice('+:', '-:'), $.constant_expression,
),
expression: $ => choice(
$.primary,
prec.left(PREC.UNARY, seq(
$.unary_operator, repeat($.attribute_instance), $.primary,
)),
prec.left(PREC.UNARY, $.inc_or_dec_expression),
prec.left(PREC.PARENT, seq('(', $.operator_assignment, ')')),
exprOp($, PREC.ADD, choice('+', '-')),
exprOp($, PREC.MUL, choice('*', '/', '%')),
exprOp($, PREC.EQUAL, choice('==', '!=', '===', '!==', '==?', '!=?')),
exprOp($, PREC.LOGICAL_AND, '&&'),
exprOp($, PREC.LOGICAL_OR, '||'),
exprOp($, PREC.POW, '**'),
exprOp($, PREC.RELATIONAL, choice('<', '<=', '>', '>=')),
exprOp($, PREC.AND, '&'),
exprOp($, PREC.OR, '|'),
exprOp($, PREC.XOR, choice('^', '^~', '~^')),
exprOp($, PREC.SHIFT, choice('>>', '<<', '>>>', '<<<')),
exprOp($, PREC.IMPLICATION, choice('->', '<->')),
$.conditional_expression,
$.inside_expression,
$.tagged_union_expression,
),
tagged_union_expression: $ => prec.left(seq(
'tagged',
$.member_identifier,
optional($.expression),
)),
inside_expression: $ => prec.left(PREC.RELATIONAL, seq(
$.expression, 'inside', '{', $.open_range_list, '}',
)),
value_range: $ => choice(
$.expression,
seq('[', $.expression, ':', $.expression, ']'),
),
mintypmax_expression: $ => seq(
$.expression,
optseq(':', $.expression, ':', $.expression),
),
module_path_conditional_expression: $ => seq(
$.module_path_expression,
'?',
repeat($.attribute_instance), $.module_path_expression,
':',
$.module_path_expression,
),
module_path_expression: $ => choice(
$.module_path_primary,
// seq($.unary_module_path_operator, repeat($.attribute_instance), $.module_path_primary),
// seq(
// $.module_path_expression,
// $.binary_module_path_operator,
// repeat($.attribute_instance),
// $.module_path_expression
// ),
// $.module_path_conditional_expression
),
module_path_mintypmax_expression: $ => seq(
$.module_path_expression,
optseq(
':', $.module_path_expression,
':', $.module_path_expression,
),
),
_part_select_range: $ => choice(
$.constant_range,
$.indexed_range,
),
indexed_range: $ => seq(
$.expression, choice('+:', '-:'), $.constant_expression,
),
_genvar_expression: $ => $.constant_expression,
/* A.8.4 Primaries */
// FIXME FIXME FIXME
constant_primary: $ => choice(
$.primary_literal,
seq($.ps_parameter_identifier, optional($.constant_select1)),
// seq($.specparam_identifier, optseq('[', $._constant_range_expression, ']')),
// $.genvar_identifier,
// seq($.formal_port_identifier, optional($.constant_select1)),
// seq(optional(choice($.package_scope, $.class_scope)), $.enum_identifier),
seq($.constant_concatenation, optseq('[', $._constant_range_expression, ']')),
seq($.constant_multiple_concatenation, optseq('[', $._constant_range_expression, ']')),
// $.constant_function_call,
// $._constant_let_expression,
seq('(', $.constant_mintypmax_expression, ')'),
// $.constant_cast,
// // $.constant_assignment_pattern_expression,
$.type_reference,
'null',
),
module_path_primary: $ => choice(
$._number,
$._identifier,
$.module_path_concatenation,
$.module_path_multiple_concatenation,
$.function_subroutine_call,
seq('(', $.module_path_mintypmax_expression, ')'),
),
primary: $ => choice(
$.primary_literal,
seq(
optional(choice($.class_qualifier, $.package_scope)),
$.hierarchical_identifier,
optional($.select1),
),
$.empty_unpacked_array_concatenation,
seq($.concatenation, optseq('[', $.range_expression, ']')),
seq($.multiple_concatenation, optseq('[', $.range_expression, ']')),
$.function_subroutine_call,
$.let_expression,
seq('(', $.mintypmax_expression, ')'),
$.cast,
$.assignment_pattern_expression,
$.streaming_concatenation,
$.sequence_method_call,
'this',
'$',
'null',
),
class_qualifier: $ => seq(
optseq('local', '::'),
choice( // TODO optional?
seq($.implicit_class_handle, '.'),
$.class_scope,
),
),
range_expression: $ => choice(
$.expression,
$._part_select_range,
),
//
primary_literal: $ => choice(
$._number,
$.time_literal,
$.unbased_unsized_literal,
$.string_literal,
$.simple_text_macro_usage,
),
time_literal: $ => choice(
seq($.unsigned_number, $.time_unit),
seq($.fixed_point_number, $.time_unit),
),
time_unit: $ => choice('s', 'ms', 'us', 'ns', 'ps', 'fs'),
string_literal: $ => seq(
'"',
repeat(choice(
token.immediate(/[^\\"]+/),
// EXTENDS Verilog spec with escape sequences
token.immediate(seq('\\', /./)),
token.immediate(seq('\\', '\n')),
)),
'"',
),
implicit_class_handle: $ => choice(
prec.left(seq('this', optseq('.', 'super'))),
'super',
),
bit_select1: $ => prec.left(PREC.PARENT, repeat1(seq( // reordered -> non empty
'[', $.expression, ']'),
)),
select1: $ => choice( // reordered -> non empty
prec.left(PREC.PARENT, seq( // 1xx
repseq('.', $.member_identifier, optional($.bit_select1)), '.', $.member_identifier,
optional($.bit_select1),
optseq('[', $._part_select_range, ']'),
)),
prec.left(PREC.PARENT, seq( // 01x
//
$.bit_select1,
optseq('[', $._part_select_range, ']'),
)),
prec.left(PREC.PARENT, seq( // 001
//
//
seq('[', $._part_select_range, ']'),
)),
),
nonrange_select1: $ => choice( // reordered -> non empty
prec.left(PREC.PARENT, seq( // 1x
repseq('.', $.member_identifier, optional($.bit_select1)), '.', $.member_identifier,
optional($.bit_select1),
)),
$.bit_select1,
),
constant_bit_select1: $ => repeat1(prec.left(PREC.PARENT, seq( // reordered -> non empty
'[', $.constant_expression, ']',
))),
constant_select1: $ => choice( // reordered -> non empty
seq(
'[',
repseq($.constant_expression, ']', '['),
choice($.constant_expression, $._constant_part_select_range),
']',
),
),
// constant_select1: $ => choice( // reordered -> non empty
// // seq(
// // repseq('.', $.member_identifier, optional($.constant_bit_select1))),
// // '.', $.member_identifier,
// // optional($.constant_bit_select1),
// // optseq('[', $._constant_part_select_range, ']')
// // ),
// seq(
// $.constant_bit_select1,
// optseq('[', $._constant_part_select_range, ']')
// ),
// seq('[', $._constant_part_select_range, ']'),
// ),
constant_cast: $ => seq($.casting_type, '\'', '(', $.constant_expression, ')'),
_constant_let_expression: $ => $.let_expression,
cast: $ => seq($.casting_type, '\'', '(', $.expression, ')'),
// A.8.5 Expression left-side values
net_lvalue: $ => choice(
seq(
$.ps_or_hierarchical_net_identifier,
optional($.constant_select1),
),
prec.left(PREC.CONCAT, seq('{', sep1(',', $.net_lvalue), '}')),
seq(
optional($._assignment_pattern_expression_type),
$.assignment_pattern_net_lvalue,
),
),
variable_lvalue: $ => choice(
prec.left(PREC.PARENT, seq(
optional(choice(
seq($.implicit_class_handle, '.'),
$.package_scope,
)),
$._hierarchical_variable_identifier,
optional($.select1),
)),
prec.left(PREC.CONCAT, seq('{', sep1(',', $.variable_lvalue), '}')),
prec.left(PREC.ASSIGN, seq(
optional($._assignment_pattern_expression_type),
$.assignment_pattern_variable_lvalue,
)),
$.streaming_concatenation,
),
nonrange_variable_lvalue: $ => prec.left(PREC.PARENT, seq(
optional(choice(
seq($.implicit_class_handle, '.'),
$.package_scope,
)),
$._hierarchical_variable_identifier,
optional($.nonrange_select1),
)),
// A.8.6 Operators
unary_operator: $ => choice(
'+', '-', '!', '~', '&', '~&', '|', '~|', '^', '~^', '^~',
),
inc_or_dec_operator: $ => choice('++', '--'),
// unary_module_path_operator = '~&' /
// '~|' /
// '~^' /
// '^~' /
// $('!'![ != ]) /
// $('~'!'=') /
// $('&'!'=') /
// $('|'!'=') /
// $('^'!'=')
//
// binary_module_path_operator = $('=='!'=') /
// $('!='!'=') /
// '&&' /
// '||' /
// $('&'!'=') /
// $('|'!'=') /
// $('^'!'=') /
// '^~' /
// '~^'
/* A.8.7 Numbers */
_number: $ => choice($.integral_number, $.real_number),
integral_number: $ => choice(
$.decimal_number,
$.octal_number,
$.binary_number,
$.hex_number,
),
decimal_number: $ => choice(
$.unsigned_number,
token(seq(
optseq(/[1-9][0-9_]*/, /\s*/),
/'[sS]?[dD]/,
/\s*/,
/[0-9][0-9_]*/,
)),
token(seq(
optseq(/[1-9][0-9_]*/, /\s*/),
/'[sS]?[dD]/,
/\s*/,
/[xXzZ?][_]*/,
)),
),
binary_number: $ => token(seq(
optseq(/[1-9][0-9_]*/, /\s*/),
/'[sS]?[bB]/,
/\s*/,
/[01xXzZ?][01xXzZ?_]*/,
)),
octal_number: $ => token(seq(
optseq(/[1-9][0-9_]*/, /\s*/),
/'[sS]?[oO]/,
/\s*/,
/[0-7xXzZ?][0-7xXzZ?_]*/,
)),
hex_number: $ => token(seq(
optseq(/[1-9][0-9_]*/, /\s*/),
/'[sS]?[hH]/,
/\s*/,
/[0-9a-fA-FxXzZ?][0-9a-fA-FxXzZ?_]*/,
)),
// NOTE: Embedded spaces are illegal.
non_zero_unsigned_number: $ => token(/[1-9][0-9_]*/),
real_number: $ => choice(
$.fixed_point_number,
token(/[0-9][0-9_]*(\.[0-9][0-9_]*)?[eE][+-]?[0-9][0-9_]*/),
),
fixed_point_number: $ => token(/[0-9][0-9_]*\.[0-9][0-9_]*/),
unsigned_number: $ => token(/[0-9][0-9_]*/),
// The apostrophe ( ' ) in unbased_unsized_literal shall not be followed by white_space.
unbased_unsized_literal: $ => choice('\'0', '\'1', /'[xXzZ]/),
/* A.9 General */
/* A.9.1 Attributes */
attribute_instance: $ => seq('(*', sep1(',', $.attr_spec), '*)'),
attr_spec: $ => seq($._attr_name, optseq('=', $.constant_expression)),
_attr_name: $ => $._identifier,
/* A.9.2 Comments */
// comment: $ => one_line_comment | block_comment
// one_line_comment: $ => // comment_text \n
// block_comment: $ => /* comment_text */
// comment_text: $ => { Any_ASCII_character }
// http://stackoverflow.com/questions/13014947/regex-to-match-a-c-style-multiline-comment/36328890#36328890
// from: https://github.com/tree-sitter/tree-sitter-c/blob/master/grammar.js
comment: $ => token(choice(
seq('//', /.*/),
seq(
'/*',
/[^*]*\*+([^/*][^*]*\*+)*/,
'/',
),
)),
/* A.9.3 Identifiers */
_array_identifier: $ => $._identifier,
_block_identifier: $ => $._identifier,
_bin_identifier: $ => $._identifier,
c_identifier: $ => /[a-zA-Z_][a-zA-Z0-9_]*/,
cell_identifier: $ => alias($._identifier, $.cell_identifier),
checker_identifier: $ => alias($._identifier, $.checker_identifier),
class_identifier: $ => alias($._identifier, $.class_identifier),
class_variable_identifier: $ => $._variable_identifier,
clocking_identifier: $ => alias($._identifier, $.clocking_identifier),
config_identifier: $ => alias($._identifier, $.config_identifier),
const_identifier: $ => alias($._identifier, $.const_identifier),
constraint_identifier: $ => alias($._identifier, $.constraint_identifier),
covergroup_identifier: $ => alias($._identifier, $.covergroup_identifier),
// covergroup_variable_identifier = _variable_identifier
cover_point_identifier: $ => alias($._identifier, $.cover_point_identifier),
cross_identifier: $ => alias($._identifier, $.cross_identifier),
dynamic_array_variable_identifier: $ => alias($._variable_identifier, $.dynamic_array_variable_identifier),
enum_identifier: $ => alias($._identifier, $.enum_identifier),
escaped_identifier: $ => seq('\\', /[^\s]*/),
formal_identifier: $ => alias($._identifier, $.formal_identifier),
formal_port_identifier: $ => alias($._identifier, $.formal_port_identifier),
function_identifier: $ => alias($._identifier, $.function_identifier),
generate_block_identifier: $ => alias($._identifier, $.generate_block_identifier),
genvar_identifier: $ => alias($._identifier, $.genvar_identifier),
_hierarchical_array_identifier: $ => $.hierarchical_identifier,
_hierarchical_block_identifier: $ => $.hierarchical_identifier,
_hierarchical_event_identifier: $ => $.hierarchical_identifier,
hierarchical_identifier: $ => prec.left(seq(
optseq('$root', '.'),
repseq($._identifier, optional($.constant_bit_select1), '.'),
$._identifier,
)),
_hierarchical_net_identifier: $ => $.hierarchical_identifier,
_hierarchical_parameter_identifier: $ => $.hierarchical_identifier,
_hierarchical_property_identifier: $ => $.hierarchical_identifier,
_hierarchical_sequence_identifier: $ => $.hierarchical_identifier,
_hierarchical_task_identifier: $ => $.hierarchical_identifier,
_hierarchical_tf_identifier: $ => $.hierarchical_identifier,
_hierarchical_variable_identifier: $ => $.hierarchical_identifier,
_identifier: $ => choice(
$.simple_identifier,
$.escaped_identifier,
),
index_variable_identifier: $ => alias($._identifier, $.index_variable_identifier),
interface_identifier: $ => alias($._identifier, $.interface_identifier),
interface_instance_identifier: $ => alias($._identifier, $.interface_instance_identifier),
inout_port_identifier: $ => alias($._identifier, $.inout_port_identifier),
input_port_identifier: $ => alias($._identifier, $.input_port_identifier),
instance_identifier: $ => alias($._identifier, $.instance_identifier),
library_identifier: $ => alias($._identifier, $.library_identifier),
member_identifier: $ => alias($._identifier, $.member_identifier),
method_identifier: $ => alias($._identifier, $.method_identifier),
modport_identifier: $ => alias($._identifier, $.modport_identifier),
_module_identifier: $ => $._identifier,
_net_identifier: $ => $._identifier,
_net_type_identifier: $ => $._identifier,
output_port_identifier: $ => alias($._identifier, $.output_port_identifier),
package_identifier: $ => alias($._identifier, $.package_identifier),
package_scope: $ => choice(
seq($.package_identifier, '::'),
seq('$unit', '::'),
),
parameter_identifier: $ => alias($._identifier, $.parameter_identifier),
port_identifier: $ => alias($._identifier, $.port_identifier),
production_identifier: $ => alias($._identifier, $.production_identifier),
program_identifier: $ => alias($._identifier, $.program_identifier),
property_identifier: $ => alias($._identifier, $.property_identifier),
ps_class_identifier: $ => seq(
optional($.package_scope), $.class_identifier,
),
ps_covergroup_identifier: $ => seq(
optional($.package_scope), $.covergroup_identifier,
),
ps_checker_identifier: $ => seq(
optional($.package_scope), $.checker_identifier,
),
ps_identifier: $ => seq(
optional($.package_scope), $._identifier,
),
ps_or_hierarchical_array_identifier: $ => seq(
optional(choice(
seq($.implicit_class_handle, '.'),
$.class_scope,
$.package_scope,
)),
$._hierarchical_array_identifier,
),
ps_or_hierarchical_net_identifier: $ => choice(
prec.left(PREC.PARENT, seq(optional($.package_scope), $._net_identifier)),
$._hierarchical_net_identifier,
),
ps_or_hierarchical_property_identifier: $ => choice(
seq(optional($.package_scope), $.property_identifier),
$._hierarchical_property_identifier,
),
ps_or_hierarchical_sequence_identifier: $ => choice(
seq(optional($.package_scope), $._sequence_identifier),
$._hierarchical_sequence_identifier,
),
ps_or_hierarchical_tf_identifier: $ => choice(
seq(optional($.package_scope), $.tf_identifier),
$._hierarchical_tf_identifier,
),
ps_parameter_identifier: $ => choice(
seq(
optional(choice(
$.package_scope,
$.class_scope,
)),
$.parameter_identifier,
),
seq(
repseq(
$.generate_block_identifier,
optseq('[', $.constant_expression, ']'),
'.',
),
$.parameter_identifier,
),
),
ps_type_identifier: $ => seq(
optional(choice(
seq('local', '::'),
$.package_scope,
$.class_scope,
)),
$._type_identifier,
),
_sequence_identifier: $ => $._identifier,
_signal_identifier: $ => $._identifier,
// A simple_identifier or c_identifier shall
// start with an alpha or underscore ( _ ) character,
// shall have at least one character, and shall not have any spaces.
simple_identifier: $ => /[a-zA-Z_][a-zA-Z0-9_$]*/,
specparam_identifier: $ => alias($._identifier, $.specparam_identifier),
// The $ character in a system_tf_identifier shall
// not be followed by white_space. A system_tf_identifier shall not be escaped.
system_tf_identifier: $ => /\$[a-zA-Z0-9_$]+/,
task_identifier: $ => alias($._identifier, $.task_identifier),
tf_identifier: $ => alias($._identifier, $.tf_identifier),
terminal_identifier: $ => alias($._identifier, $.terminal_identifier),
topmodule_identifier: $ => alias($._identifier, $.topmodule_identifier),
_type_identifier: $ => $._identifier,
_udp_identifier: $ => $._identifier,
_variable_identifier: $ => $._identifier,
/* A.9.4 White space */
// white_space: $ => space | tab | newline | eof};
},
});