difftastic/vendored_parsers/tree-sitter-vhdl/grammar.js

3794 lines
91 KiB
JavaScript

const PREC = {
CONSTANT_INTERFACE: 3,
VARIABLE_INTERFACE: 2,
SIGNAL_INTERFACE: 1,
ILLEGAL_INTERFACE: -3,
};
// 15.2 Character set
const RANGE_ATTRIBUTE_DESIGNATOR = [
'range',
'reverse_range'
];
const PREDEFINED_ATTRIBUTE_DESIGNATOR = [
'base',
'left',
'right',
'high',
'low',
'image',
'pos',
'val',
'succ',
'pred',
'leftof',
'rightof',
'subtype',
'length',
'ascending',
'descending',
'element',
'delayed',
'stable',
'quiet',
'transaction',
'event',
'active',
'last_event',
'last_active',
'last_value',
'driving',
'driving_value',
'simple_name',
'instance_name',
'path_name',
];
const PREDEFINED_ATTRIBUTE_DESIGNATOR_WITH_EXPRESSION = [
'image',
'value',
'pos',
'val',
'succ',
'pred',
'leftof',
'rightof',
'left',
'right',
'high',
'low',
'length',
'ascending',
'delayed',
'stable',
'quiet'
];
const EXPONENT = seq(
choice('e','E'),
optional(choice('+','-')),
repeat(/[0-9_]/),
);
module.exports = grammar({
name: 'vhdl',
word: $ => $.basic_identifier,
extras: $ => [ // {{{
$.comment,
$.tool_directive,
/\s/,
], // }}}
inline: $ => [ // {{{
$._entity_name, // 3.2
$._generate_specification, // 3.4
$._configuration_item, // 3.4.2
$._block_specification, // 3.4.2
$._designator, // 4.2.1
$._subprogram_declaration, // 4.2.1
$._subprogram_kind, // 4.3
$._subprogram_body, // 4.3
$._subprogram_instantiation_declaration, // 4.4
$._uninstantiated_name, // 4.4
$._package_name, // 4.8
$._scalar_type_definition, // 5.2.1
$._range, // 5.2.1
$._range_attribute_name, // 5.2.1
$._numeric_type_definition, // 5.2.1
$._unit, // 5.2.4
$._discrete_range, // 5.3.2
$._object_declaration, // 6
$._constraint, // 6.3
$._element_constraint, // 6.3
$._resolution_indication, // 6.3
$._generic_interface_declaration, // 6.5
$._port_interface_declaration, // 6.5
$._procedure_interface_declaration, // 6.5
$._function_interface_declaration, // 6.5
$._alias_denotator, // 6.6
$._illegal_interface_declaration, // 6.5.2
$._subprogram_interface_declaration, // 6.5.4
$._formal_part, // 6.5.7
$._actual_part, // 6.5.7
$._generic_interface_list, // 6.5.6.1
$._port_interface_list, // 6.5.6.1
$._procedure_parameter_list, // 6.5.6.1
$._function_parameter_list, // 6.5.6.1
$._clause, // HEADER
$._group_template, // 6.10
$._group_constituent, // 6.10
$._component_name, // 7.3
$._name, // 8
$._range_attribute_designator, // 8.6
$._external_object_name, // 8.7
$._name_or_label, // 8.7
$._external_pathname, // 8.7
$._expression, // 9.1
$._condition, // 9.1
$._simple_expression, // 9.1
$._string_expression, // 9.1
$._severity_expression, // 9.1
$._file_open_kind, // 9.1
$._time_expression, // 9.1
$._literal, // 9.3.2
$._numeric_literal, // 9.3.2
$._element_association, // 9.3.3
$._value, // 9.3.3
$._choice, // 9.3.3
$._function_name, // 9.3.4
$._signal_name, // 10.2
$._sensitivity_clause, // 10.2
$._condition_clause, // 10.2
$._timeout_clause, // 10.2
$._signal_assignment_statement, // 10.5
$._simple_signal_assignment, // 10.5.2
$._conditional_signal_assignment, // 10.5.3
$._selected_signal_assignment, // 10.5.4
$._variable_assignment_statement, // 10.6
$._iteration_scheme, // 10.10
$._concurrent_signal_assignment, // 11.6
$._generate_statement, // 11.8
$._library_unit, // 13.1
$._digit, // 15.5.2
$._digit_immed, // 15.5.2
$._identifier, // 14.4
$._abstract_literal, // 15.5
// PSL
$._PSL_Identifier, // PSL
$._PSL_Boolean, // PSL 5
$._PSL_Any_Type, // PSL 5
$._PSL_Clock_Expression, // PSL 5.3
$._PSL_Value, // PSL 5
$._PSL_FL_Property, // PSL 6.2
$._PSL_Property, // PSL 6.2
$._PSL_HDL_Module_NAME, // PSL 7.2
], // }}}
conflicts: $ => [ // {{{
// 'procedure' _identifier • 'is' …
//
// procedure_declaration:
// procedure foo is begin end procedure;
// procedure_declaration:
// procedure foo is new bar;
[$._procedure_specification, $.procedure_instantiation_declaration],
[$._function_specification , $.function_instantiation_declaration ],
// NOTE: This conflict can be solved inlining the rules, but there
// is a large penalty on the generated parser size (that is already
// quite large)
// function_call (positional_association_element)
// ambiguous_name (expression_list)
//
// _name '(' _expression ')'
//
// `foo ('+')` -> function_call (see _actual_part)
// `foo ("str")` -> function_call (see _actual_part)
[$.positional_association_element, $.expression_list],
[$.positional_association_element, $.group_constituent_list, $._primary],
// `(id (discrete_range))`
// slice name:
// `assert (arr (id'range))`
// subtype indication
// `assert new rec (elem (id'range));`
[$.index_constraint, $.slice_name],
// '(' _simple_name '(' _simple_name • ')' …
// resolution_function:
// assert new subtype_st (resolve_fun type_t);
// ^^^^^^^^^^^
// type_mark:
// assert new subtype_st (type_t object'range);
// ^^^^^^
// Unsure when _expression is used
[$.resolution_function, $.type_mark, $._primary],
// type_mark is ambiguos with simple_name in many contexts
[$.type_mark, $._primary],
[$.type_mark, $._primary, $.entity_instantiation],
[$.type_mark, $._primary, $.PSL_Hierarchical_HDL_Name],
[$.type_mark, $.function_call],
[$.type_mark, $.ambiguous_name, $.function_call],
[$.type_mark, $.ambiguous_name, $.function_call, $.slice_name],
[$.type_mark, $.ambiguous_name, $.function_call, $.slice_name, $.record_element_resolution, $.type_mark],
// _simple_name • ''' …
//
// attribute_name:
// `assert foo'bar;`
// qualified_expression:
// `assert foo'(bar);`
[$.attribute_name, $.type_mark],
[$.attribute_name, $._primary],
[$._predefined_designator, $._predefined_designator_with_expression],
// '(' _simple_name • ''' …
//
// type_mark:
// assert (foo'(bar), ...);
// attribute_name:
// assert (foo'bar, ...);
// range_attribute_name
// assert (foo'range, ...);
[$.attribute_name, $.range_attribute_name, $.type_mark],
// '(' _name '(' open • ')' ...
//
// function call:
// `assert (fun (fun (open)))`
// subtype indication
// `assert new rec (elem (open));`
//
[$.positional_association_element, $.index_constraint],
[$.positional_association_element, $._primary],
[$.named_association_element, $._primary],
// 6.2
// map clauses and map aspects shall or shall not be
// followed by semicolon depending on the context
[$.generic_clause],
[$.port_clause],
[$.procedure_parameter_clause],
[$.function_parameter_clause],
[$.generic_map_aspect],
[$.port_map_aspect],
// interfaces declarations defaults depends on context
// see corpus/interface_lists/
[$.constant_interface_declaration,
$.signal_interface_declaration,
$.variable_interface_declaration ],
[$._constant_mode, $._signal_mode, $._variable_mode],
// Generate statement body
// see corpus/declarations/generate.txt
// If generate - Generate body - If
[$.if_generate],
[$.else_generate],
[$.elsif_generate],
[$.elsif_generate],
[$.generate_statement_body],
[$.case_generate_alternative],
// `assert id
// `restrict id;`
[$.PSL_Instance, $._simple_name],
[$._PSL_Property_Instance, $._PSL_Sequence_Instance, $._PSL_Ambiguous_Instance],
[$._PSL_Property_Instance, $._PSL_Sequence_Instance],
[$.PSL_Property_Replicator],
[$.PSL_Property_Declaration],
// assert '{' ... '}'
[$._PSL_Compound_SERE, $._PSL_Sequence],
[$.configuration_specification],
], // }}}
precedences: () => [ // {{{
// Top level precedence
// Used when declarations and/or statements are outside of sequential
// statements, library unit or context clause.
// Use case: snippets of code on web (eg. declarative part w/o body)
[ 'declaration' , 'primary_unit' ],
[ 'declaration' , 'secondary_unit' ],
[ 'declaration' , 'context_item' ],
[ 'concurrent_statement' , 'sequential_statement'],
[ 'concurrent_statement' , 'declaration' ],
// Component declarations vs component instantiation
[ 'component_declaration', 'simple_name' ],
// This following relation is ambiguos. Usually procedure_call_statement,
// but component_instantiation is also legal.
[ 'procedure_call', 'component_instantiation' ],
// Expanded name
// Subtype indication
[ 'record_element_constraint' , 'type_mark' ],
[ 'record_element_resolution' , 'resolution_function' ],
[ 'type_mark' , 'resolution_function' ],
[ 'primary' , 'resolution_function' ],
// Physical literal
[ 'primary' , 'physical_literal' ],
[ 'attribute_name' , 'physical_literal' ],
// Group constituent
[ 'group_constituent_list' , 'primary' ],
[ 'group_constituent_list' , 'type_mark' ],
// Generate statatement element
[ 'generate_statement_element', 'primary' ],
// Incomplete selected assignment
// Assertion
// NOTE
// VHDL LRM states that ambiguos VHDL/PSL assertions shall
// be parsed as VHDL assertion
[ 'vhdl_assertion', 'psl_assertion' ],
// VHDL operands precedence
[
'range',
'exponentiation',
'factor',
'term',
'sign',
'simple_expression',
'shift_expression',
'relation',
'logical_expression',
'reduction',
'condition',
],
// PSL operands precedence
[
'union',
'clocked',
'SERE_repetition',
'sequence_within',
'sequence_and',
'sequence_or',
'sequence_fusion',
'sequence_concatenation',
'termination_property',
'occurrence_property',
'bounding_property',
'sequence_implication',
'property_implication',
'invariant_property',
],
[
// "next" "(" ... ")" is psl function
'psl_function_call',
'parenthesized_boolean',
'parenthesized_expression',
'occurrence_property',
'parenthesized_property',
],
// Conflicts between VHDL expression and PSL expression
[ 'logical_expression', 'logical_property' ],
[ 'factor' , 'property_factor' ],
// PSL Expression implication has the same precedence as
// VHDL expressions, therefore property_implication shall
// have lower precedence than implication.
[ 'implication', 'property_implication' ],
], // }}}
rules: {
design_file: $ => repeat(choice(
$._declaration,
$._sequential_statement,
$._concurrent_statement,
$.design_unit
)),
// 3.2 Entity declarations {{{
entity_declaration: $ => seq(
reservedWord('entity'),
field('name',$._identifier),
reservedWord('is'),
optional(alias($._header,$.entity_header)),
optional($.declarative_part),
optional(seq(
reservedWord('begin'),
optional($.concurrent_statement_part)
)),
reservedWord('end'),
optional(reservedWord('entity')),
optional($._end_simple_name),
';'
),
_entity_name: $ => field('entity', choice(
$._simple_name,
$.selected_name
)),
// }}}
// 3.3 Architecture bodies {{{
architecture_body: $ => seq(
reservedWord('architecture'),
field('name',$._identifier),
reservedWord('of'),
$._entity_name,
reservedWord('is'),
optional($.declarative_part),
reservedWord('begin'),
optional($.concurrent_statement_part),
reservedWord('end'),
optional(reservedWord('architecture')),
optional($._end_simple_name),
';'
),
// }}}
// 3.4 Configuration declarations {{{
configuration_declaration: $ => seq(
reservedWord('configuration'),
field('name',$._identifier),
reservedWord('of'),
$._entity_name,
reservedWord('is'),
// TODO
// Allow any sequence of declarative_item,
// verification_unit_binding_indication and block_configuration
// and use highlight query to highlight the errors
optional($.declarative_part),
repeat($.verification_unit_binding_indication),
optional($.block_configuration),
reservedWord('end'),
optional(reservedWord('configuration')),
optional($._end_simple_name),
';'
),
// }}}
// 3.4.2 Block configuration {{{
block_configuration: $ => seq(
reservedWord('for'),
$._block_specification,
repeat($.use_clause),
repeat($._configuration_item),
reservedWord('end'),
reservedWord('for'),
';'
),
_block_specification: $ => alias(
$.pathname_element,
$.block_specification
),
generate_statement_element: $ => prec('generate_statement_element',seq(
field('label', $._simple_name),
'(',
$._generate_specification,
')'
)),
_generate_specification: $ => field(
'specification',
choice(
$._expression,
$._range,
$._name_or_label
)
),
_configuration_item: $ => choice(
$.block_configuration,
$.component_configuration
),
// }}}
// 3.4.3 Component configuration {{{
component_configuration: $ => seq(
reservedWord('for'),
$._component_specification,
optional($.binding_indication),
repeat($.verification_unit_binding_indication),
optional($.block_configuration),
reservedWord('end'),
reservedWord('for'),
';'
),
// }}}
// 4.2.1 Subprogram declarations {{{
_subprogram_declaration: $ => choice(
$.procedure_declaration,
$.function_declaration,
),
procedure_declaration: $ => seq(
$._procedure_specification,
';'
),
function_declaration: $ => seq(
$._function_specification,
';'
),
_procedure_specification: $ => seq(
optional(choice(
reservedWord('pure'),
reservedWord('impure')
)),
reservedWord('procedure'),
$._designator,
optional(alias($._header,$.subprogram_header)),
optional($.procedure_parameter_clause),
optional($.return)
),
_function_specification: $ => seq(
optional(choice(
reservedWord('pure'),
reservedWord('impure')
)),
reservedWord('function'),
$._designator,
optional(alias($._header,$.subprogram_header)),
optional($.function_parameter_clause),
optional($.return)
),
return: $ => seq(
optional(','), // LINT: unexpected comma
reservedWord('return'),
$.type_mark,
),
_end_designator: $ => field(
'at_end',
choice(
$._end_simple_name,
$._operator_symbol
)
),
_designator: $ => field('designator',choice(
$._identifier,
$._operator_symbol,
)),
// }}}
// 4.2.2.1 Formal parameter list {{{
// ref formal_parameter_list
procedure_parameter_clause: $ => seq(
optional(reservedWord('parameter')),
'(',
optional($._procedure_parameter_list),
')',
),
function_parameter_clause: $ => seq(
optional(reservedWord('parameter')),
'(',
optional($._function_parameter_list),
')',
),
// }}}
// 4.3 Subprogram bodies {{{
_subprogram_body: $ => choice(
$.procedure_body,
$.function_body
),
procedure_body: $ => seq(
$._procedure_specification,
reservedWord('is'),
optional($.declarative_part),
reservedWord('begin'),
optional($.sequence_of_statements),
reservedWord('end'),
optional($._subprogram_kind),
optional($._end_designator),
';'
),
function_body: $ => seq(
$._function_specification,
reservedWord('is'),
optional($.declarative_part),
reservedWord('begin'),
optional($.sequence_of_statements),
reservedWord('end'),
optional($._subprogram_kind),
optional($._end_designator),
';'
),
_subprogram_kind: $ => field('at_end',seq(
optional(choice(
reservedWord('pure'),
reservedWord('impure')
)),
choice(
reservedWord('procedure'),
reservedWord('function')
),
)),
// }}}
// 4.4 Subprogram instantiation declarations {{{
_subprogram_instantiation_declaration: $ => choice(
$.procedure_instantiation_declaration,
$.function_instantiation_declaration
),
// LINT
// Procedure shall not have purity
procedure_instantiation_declaration: $ => seq(
optional(choice(
reservedWord('pure'),
reservedWord('impure')
)),
reservedWord('procedure'),
$._designator,
reservedWord('is'),
reservedWord('new'),
$._uninstantiated_name,
optional($.signature),
optional(alias($._header,$.subprogram_map_aspect)),
';'
),
function_instantiation_declaration: $ => seq(
optional(choice(
reservedWord('pure'),
reservedWord('impure')
)),
reservedWord('function'),
$._designator,
reservedWord('is'),
reservedWord('new'),
$._uninstantiated_name,
optional($.signature),
optional(alias($._header,$.subprogram_map_aspect)),
';'
),
_uninstantiated_name: $ => field('uninstantiated', choice(
$.selected_name,
$._simple_name
)),
// }}}
// 4.5.3 Signatures {{{
signature: $ => seq(
'[',
sepBy(',', $.type_mark),
optional($.return),
']'
),
// }}}
// 4.7 Package declarations {{{
package_declaration: $ => seq(
reservedWord('package'),
field('name',$._identifier),
reservedWord('is'),
optional(alias($._header,$.package_header)),
optional($.declarative_part),
reservedWord('end'),
optional(reservedWord('package')),
optional($._end_simple_name),
';'
),
// }}}
// 4.8 Package bodies {{{
package_body: $ => seq(
reservedWord('package'),
reservedWord('body'),
$._package_name,
reservedWord('is'),
optional($.declarative_part),
reservedWord('end'),
optional(seq(
reservedWord('package'),
reservedWord('body'),
)),
optional($._end_simple_name),
';'
),
_package_name: $ => field('package', $._simple_name),
// }}}
// 4.9 Package instantiation declarations {{{
package_instantiation_declaration: $ => seq(
reservedWord('package'),
field('name',$._identifier),
reservedWord('is'),
reservedWord('new'),
$._uninstantiated_name,
optional(alias($._header,$.package_map_aspect)),
';'
),
// }}}
// 5.2.1 Scalar types {{{
_scalar_type_definition: $ => choice(
$.enumeration_type_definition,
$._numeric_type_definition,
$.physical_type_definition
),
_numeric_type_definition: $ => alias(
$.range_constraint,
$.numeric_type_definition
),
range_constraint: $ => seq(
reservedWord('range'),
$._range
),
_range: $ => choice(
$.ascending_range,
$.descending_range,
$._range_attribute_name,
),
_range_attribute_name: $ => alias(
$.range_attribute_name,
$.attribute_name
),
range_attribute_name: $ => seq(
field('prefix', choice(
$._simple_name,
$.selected_name,
$.ambiguous_name,
$.attribute_name,
$._external_object_name,
)),
$._range_attribute_designator,
),
ascending_range: $ => prec('range',seq(
field('low', $._simple_expression),
reservedWord('to'),
field('high', $._simple_expression),
)),
descending_range: $ => prec('range',seq(
field('high', $._simple_expression),
reservedWord('downto'),
field('low', $._simple_expression),
)),
// }}}
// 5.2.2 Enumeration types {{{
enumeration_type_definition: $ => seq(
'(',
sepBy1(',', $._enumeration_literal),
')'
),
_enumeration_literal: $ => field('literal',choice(
$.character_literal,
$._identifier
)),
// }}}
// 5.2.4 Physical types {{{
physical_type_definition: $ => seq(
$.range_constraint,
reservedWord('units'),
optional(seq(
$.primary_unit_declaration,
repeat($.secondary_unit_declaration),
)),
reservedWord('end'),
reservedWord('units'),
optional($._end_simple_name)
),
primary_unit_declaration: $ => seq(
field('name',$._identifier),
';'
),
secondary_unit_declaration: $ => seq(
field('name',$._identifier),
'=',
choice(
$.physical_literal,
alias(
$._physical_literal,
$.physical_literal
),
),
';'
),
_physical_literal: $ => seq(
$._unit
),
physical_literal: $ => prec('physical_literal', seq(
$._abstract_literal,
$._unit,
)),
_unit: $ => field('unit', prec('physical_literal',choice(
$._simple_name,
$.selected_name
))),
// }}}
// 5.3 Composite types {{{
_composite_type_definition: $ => choice(
$._array_type_definition,
$.record_type_definition
),
// }}}
// 5.3.2 Array types {{{
_array_type_definition: $ => choice(
$.unbounded_array_definition,
$.constrained_array_definition
),
unbounded_array_definition: $ => seq(
reservedWord('array'),
'(',
sepBy1(',', $.index_subtype_definition),
')',
reservedWord('of'),
field('element',$.subtype_indication)
),
constrained_array_definition: $ => seq(
reservedWord('array'),
$.index_constraint,
reservedWord('of'),
field('element',$.subtype_indication)
),
index_subtype_definition: $ => seq(
$.type_mark,
reservedWord('range'),
$._any
),
array_constraint: $ => seq(
$.index_constraint,
optional($._array_element_constraint)
),
_array_element_constraint: $ => alias(
$._element_constraint,
$.array_element_constraint
),
index_constraint: $ => seq(
'(',
choice(
sepBy1(',', $._discrete_range),
prec.dynamic(99, $.open)
),
')',
),
_discrete_range: $ => choice(
$.subtype_indication,
$._range,
),
open: $ => reservedWord('open'),
// }}}
// 5.3.3 Record types {{{
record_type_definition: $ => seq(
reservedWord('record'),
repeat($.element_declaration),
reservedWord('end'),
reservedWord('record'),
optional($._end_simple_name)
),
element_declaration: $ => seq(
$.identifier_list,
':',
$.subtype_indication,
';'
),
record_constraint: $ => seq(
'(',
sepBy1(',', $.record_element_constraint),
')'
),
record_element_constraint: $ => prec('record_element_constraint', seq(
field('element', $._simple_name),
$._element_constraint
)),
identifier_list: $ => sepBy1(',', $._identifier),
// }}}
// 5.4 Access types {{{
access_type_definition: $ => seq(
reservedWord('access'),
$.subtype_indication
),
// }}}
// 5.4.2 Incomplete type declaration {{{
incomplete_type_declaration: $ => seq(
reservedWord('type'),
field('name',$._identifier),
';'
),
// }}}
// 5.5 File types {{{
file_type_definition: $ => seq(
reservedWord('file'),
reservedWord('of'),
$.type_mark
),
// }}}
// 5.6.2 Protected type declarations {{{
protected_type_declaration: $ => seq(
reservedWord('protected'),
optional($.declarative_part),
reservedWord('end'),
reservedWord('protected'),
optional($._end_simple_name),
),
// }}}
// 5.6.2 Protected type bodies {{{
protected_type_body: $ => seq(
reservedWord('protected'),
reservedWord('body'),
optional($.declarative_part),
reservedWord('end'),
reservedWord('protected'),
reservedWord('body'),
optional($._end_simple_name),
),
// }}}
// 6. Declarations {{{
declarative_part: $ => prec.left(repeat1(
$._declaration
)),
_declaration: $ => prec('declaration',choice(
$._subprogram_declaration,
$._subprogram_body,
$._subprogram_instantiation_declaration,
$.package_declaration,
$.package_body,
$.package_instantiation_declaration,
$._type_declaration,
$.subtype_declaration,
$._object_declaration,
$.alias_declaration,
$.component_declaration,
$.attribute_declaration,
$.attribute_specification,
$.configuration_specification,
$.disconnection_specification,
$.use_clause,
$.group_template_declaration,
$.group_declaration,
$._PSL_Directive,
$._PSL_Declaration
)),
// }}}
// 6.2 Type declarations {{{
_type_declaration: $ => choice(
$.full_type_declaration,
$.incomplete_type_declaration,
),
full_type_declaration: $ => seq(
reservedWord('type'),
field('name',$._identifier),
reservedWord('is'),
$._type_definition,
';'
),
_type_definition: $ => choice(
$._scalar_type_definition,
$._composite_type_definition,
$.access_type_definition,
$.file_type_definition,
$.protected_type_declaration,
$.protected_type_body
),
// }}}
// 6.3 Subtype declaration {{{
subtype_declaration: $ => seq(
reservedWord('subtype'),
field('name',$._identifier),
reservedWord('is'),
$.subtype_indication,
';'
),
subtype_indication: $ => seq(
optional($._resolution_indication),
$.type_mark,
optional($._constraint)
),
_resolution_indication: $ => choice(
$.resolution_function,
$.record_resolution,
$.parenthesized_resolution,
),
resolution_function: $ => prec('resolution_function', choice(
$._simple_name,
$.selected_name
)),
parenthesized_resolution: $ => seq(
'(',
$._resolution_indication,
')'
),
record_resolution: $ => seq(
'(',
sepBy1(',', $.record_element_resolution),
')'
),
record_element_resolution: $ => prec('record_element_resolution', seq(
field('element', $._simple_name),
$._resolution_indication
)),
type_mark: $ => prec('type_mark',choice(
$._simple_name,
$.selected_name,
$.attribute_name
)),
_constraint: $ => choice(
$.range_constraint,
$.array_constraint,
$.record_constraint
),
_element_constraint: $ => choice(
$.array_constraint,
$.record_constraint
),
// }}}
// 6.4.2 Object declarations {{{
_object_declaration: $ => choice(
$.constant_declaration,
$.signal_declaration,
$.variable_declaration,
$.shared_variable_declaration,
$.file_declaration,
),
// }}}
// 6.4.2 Constant declarations {{{
constant_declaration: $ => seq(
reservedWord('constant'),
$.identifier_list,
':',
$.subtype_indication,
optional($.default_expression),
';'
),
// }}}
// 6.4.2.3 Signal declarations {{{
signal_declaration: $ => seq(
reservedWord('signal'),
$.identifier_list,
':',
$.subtype_indication,
optional($.signal_kind),
optional($.default_expression),
';'
),
signal_kind: $ => choice(
reservedWord('register'),
reservedWord('bus')
),
// }}}
// 6.4.2.4 Variable declarations {{{
variable_declaration: $ => seq(
reservedWord('variable'),
$.identifier_list,
':',
$.subtype_indication,
optional($.default_expression),
';'
),
shared_variable_declaration: $ => seq(
reservedWord('shared'),
reservedWord('variable'),
$.identifier_list,
':',
$.subtype_indication,
optional($.default_expression),
';'
),
// }}}
// 6.4.2.5 File declarations {{{
file_declaration: $ => seq(
reservedWord('file'),
$.identifier_list,
':',
$.subtype_indication,
optional($.file_open_information),
';'
),
file_open_information: $ => seq(
optional(seq(
reservedWord('open'),
$._file_open_kind
)),
reservedWord('is'),
$._file_logical_name
),
_file_logical_name: $ => $._string_expression,
// }}}
// 6.5 Interface declarations {{{
_generic_interface_declaration: $ => choice(
$.constant_interface_declaration,
$.type_interface_declaration,
$._subprogram_interface_declaration,
$.package_interface_declaration,
$._illegal_interface_declaration
),
_port_interface_declaration: $ => choice(
$.signal_interface_declaration,
$._illegal_interface_declaration
),
// See 6.5.2 and 4.2.2.1
_procedure_interface_declaration: $ => choice(
$.constant_interface_declaration,
$.signal_interface_declaration,
$.variable_interface_declaration,
$.file_interface_declaration,
$._illegal_interface_declaration
),
_function_interface_declaration: $ => choice(
$.constant_interface_declaration,
$.signal_interface_declaration,
$.file_interface_declaration,
$._illegal_interface_declaration
),
// }}}
// 6.5.2 Interface object declarations {{{
constant_interface_declaration: $ => prec.dynamic(
PREC.CONSTANT_INTERFACE,
seq(
optional(reservedWord('constant')),
$.identifier_list,
':',
optional(alias($._constant_mode, $.mode)),
$.subtype_indication,
optional($.default_expression)
)
),
signal_interface_declaration: $ => prec.dynamic(
PREC.SIGNAL_INTERFACE,
seq(
optional(reservedWord('signal')),
$.identifier_list,
':',
optional(alias($._signal_mode, $.mode)),
$.subtype_indication,
optional($.signal_kind),
optional($.default_expression)
)
),
variable_interface_declaration: $ => prec.dynamic(
PREC.VARIABLE_INTERFACE,
seq(
optional(reservedWord('variable')),
$.identifier_list,
':',
optional(alias($._variable_mode, $.mode)),
$.subtype_indication,
optional($.default_expression)
)
),
file_interface_declaration: $ => seq(
reservedWord('file'),
$.identifier_list,
':',
optional(alias($._signal_mode, $.mode)), // ILLEGAL, LINT
$.subtype_indication,
optional($.default_expression) // ILLEGAL, LINT
),
// DO NOT LINE
_in: $ => reservedWord('in'),
_out: $ => reservedWord('out'),
_inout: $ => reservedWord('inout'),
_buffer: $ => reservedWord('buffer'),
_linkage: $ => reservedWord('linkage'),
// DO NOT INLINE
_constant_mode: $ => choice(
prec.dynamic( 1, $._in),
prec.dynamic(-3, $._out),
prec.dynamic(-3, $._inout),
prec.dynamic(-3, $._buffer),
prec.dynamic(-3, $._linkage),
),
// DO NOT INLINE
_variable_mode: $ => choice(
prec.dynamic( 1, $._in),
prec.dynamic( 1, $._out),
prec.dynamic( 1, $._inout),
prec.dynamic(-2, $._buffer),
prec.dynamic(-2, $._linkage),
),
// DO NOT INLINE
_signal_mode: $ => choice(
prec.dynamic(1, $._in),
prec.dynamic(1, $._out),
prec.dynamic(1, $._inout),
prec.dynamic(1, $._buffer),
prec.dynamic(1, $._linkage),
),
_illegal_interface_declaration: $ => prec.dynamic(
PREC.ILLEGAL_INTERFACE,
choice(
$.constant_interface_declaration,
$.signal_interface_declaration,
$.variable_interface_declaration,
$.file_interface_declaration,
$.type_interface_declaration,
$._subprogram_interface_declaration,
$.package_interface_declaration
)
),
// }}}
// 6.5.3 Interface type declarations {{{
type_interface_declaration: $ => seq(
reservedWord('type'),
field('name',$._identifier),
),
// }}}
// 6.5.4 Interface subprogram declarations {{{
_subprogram_interface_declaration: $ => choice(
$.procedure_interface_declaration,
$.function_interface_declaration
),
procedure_interface_declaration: $ => seq(
$._procedure_specification,
optional(seq(
reservedWord('is'),
$.interface_subprogram_default
))
),
function_interface_declaration: $ => seq(
$._function_specification,
optional(seq(
reservedWord('is'),
$.interface_subprogram_default
))
),
interface_subprogram_default: $ => choice(
$._simple_name,
$.selected_name,
$._operator_symbol,
alias('<>', $.same),
),
// }}}
// 6.5.5 Interface package declarations {{{
package_interface_declaration: $ => seq(
reservedWord('package'),
field('name',$._identifier),
reservedWord('is'),
reservedWord('new'),
$._uninstantiated_name,
optional(alias($._header,$.package_map_aspect)),
),
// }}}
// 6.5.6.1 Interface lists {{{
// LINT: Semicolon after last declaration
_generic_interface_list: $ => seq(
sepBy1(';', $._generic_interface_declaration),
),
_port_interface_list: $ => seq(
sepBy1(';', $._port_interface_declaration),
),
_procedure_parameter_list: $ => seq(
sepBy1(';', $._procedure_interface_declaration),
),
_function_parameter_list: $ => seq(
sepBy1(';', $._function_interface_declaration),
),
// }}}
// 6.5.6.2 Generic clauses {{{
generic_clause: $ => seq(
reservedWord('generic'),
'(',
optional($._generic_interface_list),
')',
optional($._semicolon)
),
_semicolon: $ => alias(';', $.semicolon),
// }}}
// 6.5.6.3 Port clauses {{{
port_clause: $ => seq(
reservedWord('port'),
'(',
optional($._port_interface_list),
')',
optional($._semicolon)
),
// }}}
// 6.5.7 Association lists {{{
// LINT: NAMED association element shall NOT be followed by
// POSITIONAL association element.
// NOTE: The correct ordering is deliberatedly not enforced
// by the parser. Tree-sitter does not support custom
// error recovery yet.
// the query.
// NOTE: Having different rules for positional and named
// association simplifies writing queries.
association_list: $ => sepBy1(',', $._association_element),
_association_element: $ => choice(
$.positional_association_element,
$.named_association_element
),
positional_association_element: $ => seq(
$._actual_part
),
named_association_element: $ => seq(
$._formal_part,
delimiter('=>'),
$._actual_part
),
_formal_part: $ => field(
'formal_part',
choice(
$._name,
$.others
),
),
_actual_part: $ => field(
'actual_part',
choice(
$._expression,
$.inertial_expression,
prec.dynamic(-1, $.subtype_indication),
prec.dynamic(99, $.open),
// used to resolve conflicts
// between ambiguous_name and function_call:
// _name '(' character_literal ')'
// _name '(' string_literal ')'
prec.dynamic(2, $.character_literal),
prec.dynamic(2, $.string_literal),
),
),
// }}}
// 6.5.7.2 Generic map aspects {{{
generic_map_aspect: $ => seq(
reservedWord('generic'),
reservedWord('map'),
'(',
optional(choice(
$.association_list,
$.default,
$._any
)),
')',
optional($._semicolon),
),
default: $ => reservedWord('default'),
_any: $ => alias('<>', $.any),
// }}}
// 6.5.7.3 Port map aspects {{{
port_map_aspect: $ => seq(
reservedWord('port'),
reservedWord('map'),
'(',
optional($.association_list),
')',
optional($._semicolon)
),
// }}}
// HEADER and MAP_ASPECTS {{{
_header: $ => seq(
$._clause,
optional($._clause),
optional($._clause),
optional($._clause),
),
_clause: $ => choice(
$.generic_clause,
$.generic_map_aspect,
$.port_clause,
$.port_map_aspect,
),
// }}}
// 6.6 Alias declarations {{{
alias_declaration: $ => seq(
reservedWord('alias'),
$._alias_designator,
optional(seq(
':',
$.subtype_indication
)),
reservedWord('is'),
$._alias_denotator,
optional($.signature),
';'
),
_alias_designator: $ => field(
'designator',
choice(
$._identifier,
$.character_literal,
$._operator_symbol
)
),
_alias_denotator: $ => field(
'denotator',
choice(
$._simple_name,
$.character_literal,
$.selected_name,
$.ambiguous_name,
$.slice_name,
$.attribute_name,
$._external_object_name,
)
),
_operator_symbol: $ => alias(
$.string_literal,
$.operator_symbol
),
// }}}
// 6.7 Attribute declarations {{{
attribute_declaration: $ => seq(
reservedWord('attribute'),
field('name',$._identifier),
':',
$.type_mark,
';'
),
// }}}
// 6.8 Component declarations {{{
component_declaration: $ => prec('component_declaration',seq(
reservedWord('component'),
field('name',$._identifier),
optional(reservedWord('is')),
optional(alias($._header,$.component_header)),
reservedWord('end'),
reservedWord('component'),
optional($._end_simple_name),
';'
)),
// }}}
// 6.9 Group template declarations {{{
group_template_declaration: $ => seq(
reservedWord('group'),
field('name',$._identifier),
reservedWord('is'),
'(',
$.entity_class_entry_list,
')',
';'
),
entity_class_entry_list: $ => sepBy1(',', $.entity_class_entry),
entity_class_entry: $ => seq(
$.entity_class,
optional($._any)
),
// }}}
// 6.10 Group declarations {{{
group_declaration: $ => seq(
reservedWord('group'),
field('name',$._identifier),
':',
$._group_template,
'(',
$.group_constituent_list,
')',
';'
),
group_constituent_list: $ => prec(
'group_constituent_list',
sepBy1(',', $._group_constituent),
),
_group_constituent: $ => choice(
$._simple_name,
$.selected_name,
$.character_literal
),
_group_template: $ => field(
'template',
choice(
$._simple_name,
$.selected_name
)
),
// }}}
// 7.2 Specifications {{{
attribute_specification: $ => seq(
reservedWord('attribute'),
field('name',$._simple_name),
reservedWord('of'),
$.entity_specification,
reservedWord('is'),
$._expression,
';'
),
entity_name_list: $ => choice(
sepBy1(',', $.entity_designator),
$.others,
$.all
),
entity_specification: $ => seq(
$.entity_name_list,
':',
$.entity_class
),
entity_class: $ => choice(
reservedWord('entity'),
reservedWord('architecture'),
reservedWord('configuration'),
reservedWord('procedure'),
reservedWord('function'),
reservedWord('package'),
reservedWord('type'),
reservedWord('subtype'),
reservedWord('constant'),
reservedWord('signal'),
reservedWord('variable'),
reservedWord('component'),
reservedWord('label'),
reservedWord('literal'),
reservedWord('units'),
reservedWord('group'),
reservedWord('file'),
reservedWord('property'),
reservedWord('sequence'),
),
entity_designator: $ => seq(
$._entity_tag,
optional($.signature)
),
_entity_tag: $ => choice(
$._simple_name,
$.character_literal,
$._operator_symbol
),
// }}}
// 7.3 Configuration specification {{{
configuration_specification: $ => prec.right(seq(
reservedWord('for'),
// not-optional, used to improve error recovery
optional(seq(
$._component_specification,
$.binding_indication,
optional(seq(
repeat($.verification_unit_binding_indication),
reservedWord('end'),
reservedWord('for'),
';'
))
))
)),
_component_specification: $ => seq(
$.instantiation_list,
':',
$._component_name
),
instantiation_list: $ => choice(
sepBy1(',', $._simple_name),
$.others,
$.all
),
all: $ => reservedWord('all'),
// TODO: Does it allow expanded name?
_component_name: $ => field(
'component',
$._simple_name
),
// }}}
// 7.3.2 Binding indication {{{
binding_indication: $ => seq(
optional(seq(
reservedWord('use'),
$._entity_aspect,
)),
optional($._header),
';'
),
// LINT: component_instantiation shall not be present in
// binding indication
_entity_aspect: $ => choice(
$.entity_instantiation,
$.configuration_instantiation,
$.component_instantiation,
$.open
),
// }}}
// 7.3.4 Verification unit binding indication {{{
verification_unit_binding_indication: $ => seq(
reservedWord('use'),
reservedWord('vunit'),
$.verification_unit_list,
';'
),
verification_unit_list: $ => sepBy1(
',',
choice(
$._simple_name,
$.selected_name,
)
),
// }}}
// 7.4 Disconnection specification {{{
disconnection_specification: $ => seq(
reservedWord('disconnect'),
$.guarded_signal_specification,
$._after,
';'
),
guarded_signal_specification: $ => seq(
$.signal_list,
':',
$.type_mark,
),
signal_list: $ => choice(
sepBy1(',', $._signal_name),
$.others,
$.all
),
// }}}
// 8 Names {{{
_name: $ => choice(
$._simple_name,
$.character_literal,
$.selected_name,
$.ambiguous_name,
$.slice_name,
$.attribute_name,
$._external_object_name,
),
_simple_name: $ => prec('simple_name',choice(
alias($.basic_identifier, $.simple_name),
alias($.extended_identifier, $.extended_simple_name)
)),
_end_simple_name: $ => field(
'at_end',
$._simple_name
),
// }}}
// 8.3 Selected names {{{
// LINT
// Only expanded names shall have character_literal and operator_symbol
// as suffix
selected_name: $ => seq(
field('prefix', choice(
$._simple_name,
$.selected_name,
$.ambiguous_name,
$.slice_name,
$._external_object_name,
)),
token.immediate('.'),
field('suffix', choice(
$._simple_name,
$.character_literal,
$._operator_symbol,
$.all // allowed on access value
)),
),
// }}}
// 8.4 Indexed name (Ambiguos name) {{{
// foo (bar)
// - function call
// - type conversion
// - slice name
// - indexed name
// foo (bar, baz)
// - function call
// - indexed name
// prefix (foo)
// - slice name
// - indexed name
ambiguous_name: $ => seq(
field('prefix', choice(
$._simple_name,
$.selected_name,
$.ambiguous_name,
$.function_call
)),
'(',
$.expression_list,
')'
),
expression_list: $ => sepBy1(',', $._expression),
// }}}
// 8.5 Slice name {{{
slice_name: $ => seq(
field('prefix', choice(
$._simple_name,
$.ambiguous_name,
$.selected_name,
$.slice_name,
$.function_call,
)),
'(',
$._range,
')'
),
// }}}
// 8.6 Attribute names {{{
attribute_name: $ => prec('attribute_name',seq(
field('prefix', choice(
$._simple_name,
$.selected_name,
$.ambiguous_name, // indexed_name allowed
$.attribute_name,
$.function_call,
$._external_object_name,
)),
optional($.signature),
choice(
$._attribute_designator,
$._predefined_attribute_designator,
$._predefined_attribute_designator_with_expression,
),
)),
_attribute_designator: $ => seq(
token('\''),
field('designator', $._simple_name),
),
_predefined_attribute_designator: $ => prec.dynamic(1, seq(
token('\''),
field('designator', alias($._predefined_designator, $.predefined_designator)),
)),
// Only predefined attributes shall have expression
_predefined_attribute_designator_with_expression: $ => prec.dynamic(2, prec.right(seq(
token('\''),
field('designator', alias($._predefined_designator_with_expression, $.predefined_designator)),
'(',
$._expression,
')'
))),
_range_attribute_designator: $ => seq(
token('\''),
field('designator', alias($._range_designator, $.predefined_designator)),
optional(seq(
'(',
$._expression,
')',
))
),
// DO NOT INLINE
_predefined_designator: $ => choice(
...PREDEFINED_ATTRIBUTE_DESIGNATOR.map(attr => reservedWord(attr))
),
// DO NOT INLINE
_predefined_designator_with_expression: $ => choice(
...PREDEFINED_ATTRIBUTE_DESIGNATOR_WITH_EXPRESSION.map(attr => reservedWord(attr))
),
// DO NOT INLINE
_range_designator: $ => choice(
...RANGE_ATTRIBUTE_DESIGNATOR.map(attr => reservedWord(attr))
),
// }}}
// 8.7 External names {{{
_external_object_name: $ => choice(
$.external_constant_name,
$.external_signal_name,
$.external_variable_name
),
external_constant_name: $ => seq(
delimiter('<<'),
reservedWord('constant'),
$._external_pathname,
':',
$.subtype_indication,
delimiter('>>')
),
external_signal_name: $ => seq(
delimiter('<<'),
reservedWord('signal'),
$._external_pathname,
':',
$.subtype_indication,
delimiter('>>')
),
external_variable_name: $ => seq(
delimiter('<<'),
reservedWord('variable'),
$._external_pathname,
':',
$.subtype_indication,
delimiter('>>')
),
_external_pathname: $ => choice(
$.package_pathname,
$.absolute_pathname,
$.relative_pathname
),
package_pathname: $ => seq(
'@',
field('library', $._simple_name),
'.',
sepBy1('.', field('package',$._simple_name)),
'.',
field('object', $._simple_name),
),
absolute_pathname: $ => seq(
'.', $._partial_pathname
),
relative_pathname: $ => seq(
repeat('^.'),
$._partial_pathname
),
_partial_pathname: $ => seq(
repeat(seq(
$.pathname_element, '.'
)),
field('object', $._simple_name),
),
pathname_element: $ => choice(
$._name_or_label,
$.generate_statement_element,
),
_name_or_label: $ => field(
'name_or_label',
$._simple_name
),
// }}}
// 9. Expressions {{{
_expr: $ => choice(
$._unary_expression,
$._binary_expression,
$._primary
),
_unary_expression: $ => choice(
$.condition,
$.reduction,
$.sign,
$.factor
),
_binary_expression: $ => choice(
$.logical_expression,
$.relation,
$.shift_expression,
$.simple_expression,
$.concatenation,
$.term,
$.exponentiation,
),
_primary: $ => prec('primary',choice(
$._name,
$._literal,
$.aggregate,
$.qualified_expression,
$.allocator,
$.parenthesized_expression,
$.function_call,
)),
// Named expressions
_expression: $ => alias(
$._expr,
$.expression
),
_condition: $ => alias(
$._expr,
$.conditional_expression
),
_simple_expression: $ => alias(
$._expr,
$.simple_expression
),
_time_expression: $ => alias(
$._expr,
$.time_expression
),
_string_expression: $ => alias(
$._expr,
$.string_expression
),
_severity_expression: $ => alias(
$._primary,
$.severity_expression
),
_file_open_kind: $ => alias(
$._primary,
$.file_open_kind
),
// Special expressions
default_expression: $ => seq(
':=',
$._expr,
),
inertial_expression: $ => seq(
reservedWord('inertial'),
$._expr
),
parenthesized_expression: $ => prec('parenthesized_expression',seq(
'(',
$._expr,
')'
)),
// Unary expressions
// LINT: condition shall not have expression as parent
condition: $ => prec('condition', seq(
field('operator', delimiter('??')),
$._expr
)),
// LINT: reduction shall not have expression as parent
reduction: $ => prec('reduction', seq(
field('operator', choice(...['and', 'or', 'xor', 'nand', 'nor', 'xnor'].map(op => reservedWord(op)))),
$._expr
)),
// LINT: factor shall not have SOME expression as parent
factor: $ => prec.right('factor', seq(
field('operator', choice(...['not', 'abs'].map(op => reservedWord(op)))),
$._expr
)),
// LINT: sign shall not have SOME expression as parent
sign: $ => prec('sign', seq(
field('operator', choice(...['+', '-'].map(op => delimiter(op)))),
$._expr
)),
// Binary expressions
// LINT: nor and nand are non associative
// LINT: other operators are only associative with themselves
logical_expression: $ => prec.right('logical_expression',seq(
$._expr,
choice(
// associative operators
repeat1(prec.left('logical_expression',seq(field('operator', reservedWord('and' )), $._expr))),
repeat1(prec.left('logical_expression',seq(field('operator', reservedWord('or' )), $._expr))),
repeat1(prec.left('logical_expression',seq(field('operator', reservedWord('xor' )), $._expr))),
repeat1(prec.left('logical_expression',seq(field('operator', reservedWord('xnor')), $._expr))),
// non associative operators
seq(prec.left('logical_expression',seq(field('operator', reservedWord('nand')), $._expr))),
seq(prec.left('logical_expression',seq(field('operator', reservedWord('nor' )), $._expr))),
),
)),
// LINT: relations are not associative
relation: $ => prec.right('relation', seq(
$._expr,
field('operator', choice(...['<', '>', '=', '<=', '>=', '/=', '?<', '?>', '?=', '?<=', '?>=', '?/='].map(op => delimiter(op)))),
$._expr
)),
// LINT: shift expressions are not associative
shift_expression: $ => prec.right('shift_expression', seq(
$._expr,
field('operator', choice(...['sll', 'srl', 'sla', 'sra', 'rol', 'ror'].map(op => reservedWord(op)))),
$._expr,
)),
// LINT: operand shall not be sign
simple_expression: $ => prec.right('simple_expression', seq(
$._expr,
repeat1(prec.left('simple_expression',seq(
field('operator', choice(
...['+', '-'].map(op => delimiter(op))
)),
$._expr
))),
)),
concatenation: $ => prec.right('simple_expression', seq(
$._expr,
repeat1(prec.left('simple_expression',seq(
field('operator', delimiter('&')),
$._expr
))),
)),
term: $ => prec.right('term', seq(
$._expr,
choice(
repeat1(prec.left('term',seq(
field('operator', choice(
...['*', '/'].map(op => delimiter(op)),
...['rem', 'mod'].map(op => reservedWord(op)),
)),
$._expr
))),
)
)),
// LINT: exponentiation are not associative
exponentiation: $ => prec.left('exponentiation', seq(
$._expr,
field('operator', choice(...['**'].map(op => delimiter(op)))),
$._expr
)),
// }}}
// 9.3.2 Literals {{{
_literal: $ => choice(
$._numeric_literal,
$.string_literal,
$.bit_string_literal,
$.null,
$.character_literal,
),
_numeric_literal: $ => choice(
$._abstract_literal,
$.physical_literal
),
null: $ => reservedWord('null'),
// }}}
// 9.3.3 Aggregates {{{
aggregate: $ => prec(-1, seq(
'(',
$._element_association_list,
')'
)),
_element_association_list: $ => choice(
$.named_element_association,
seq(
$._element_association,
',',
sepBy1(',', $._element_association),
),
),
_element_association: $ => choice(
$.positional_element_association,
$.named_element_association,
),
positional_element_association: $ => seq(
$._value
),
named_element_association: $ => prec(-1, seq(
$.choices,
delimiter('=>'),
$._value
)),
_value: $ => $._expression,
choices: $ => sepBy1('|', $._choice),
_choice: $ => choice(
$._simple_expression,
$._range,
$.others
),
others: $ => reservedWord('others'),
// }}}
// 9.3.4 Function call {{{
function_call: $ => seq(
$._function_name,
'(',
$.association_list,
')'
),
_function_name: $ => field(
'function',
choice(
$._simple_name,
$._operator_symbol,
$.selected_name,
$.attribute_name,
)
),
// }}}
// 9.3.5 Qualified expressions {{{
qualified_expression: $ => seq(
$.type_mark,
token('\''),
choice(
$.aggregate,
alias($.parenthesized_expression,$.expression),
),
),
// }}}
// 9.3.7 Allocators {{{
allocator: $ => seq(
reservedWord('new'),
choice(
$.subtype_indication,
$.qualified_expression
)
),
// }}}
// 10.1 Sequential statements {{{
sequence_of_statements: $ => repeat1(
$._sequential_statement
),
_sequential_statement: $ => prec('sequential_statement',choice(
$.process_statement,
$.wait_statement,
$.assertion_statement,
$.report_statement,
$._signal_assignment_statement,
$._variable_assignment_statement,
$.procedure_call_statement,
$.if_statement,
$.case_statement,
$.loop_statement,
$.next_statement,
$.exit_statement,
$.return_statement,
$.null_statement,
$._PSL_Directive,
$._PSL_Declaration,
)),
// }}}
// 10.2 Wait statement {{{
wait_statement: $ => seq(
optional($.label),
reservedWord('wait'),
optional($._sensitivity_clause),
optional($._condition_clause),
optional($._timeout_clause),
';'
),
_sensitivity_clause: $ => seq(
reservedWord('on'),
$.sensitivity_list
),
_condition_clause: $ => seq(
reservedWord('until'),
$._condition
),
_timeout_clause: $ => seq(
reservedWord('for'),
$._time_expression
),
// LINT
// all is not allowed on sensitivy clause
sensitivity_list: $ => choice(
$.all,
sepBy1(',', $._signal_name),
),
_signal_name: $ => $._name,
// }}}
// 10.3 Assertion statement {{{
assertion_statement: $ => prec('vhdl_assertion',seq(
optional($.label),
optional(reservedWord('postponed')),
reservedWord('assert'),
$._condition,
optional($._report),
optional($._severity),
';'
)),
// }}}
// 10.4 Report statement {{{
report_statement: $ => seq(
optional($.label),
$._report,
optional($._severity),
';'
),
_report: $ => seq(
reservedWord('report'),
$._string_expression
),
_severity: $ => seq(
reservedWord('severity'),
$._severity_expression
),
// }}}
// 10.5 Signal assignments {{{
_signal_assignment_statement: $ => choice(
$._simple_signal_assignment,
$._conditional_signal_assignment,
$._selected_signal_assignment,
),
// }}}
// 10.5.2 Simple signal assignments {{{
_simple_signal_assignment: $ => choice(
$.simple_waveform_assignment,
$.simple_force_assignment,
$.simple_release_assignment
),
simple_waveform_assignment: $ => seq(
optional($.label),
$._target,
'<=',
optional(reservedWord('guarded')),
optional($.delay_mechanism),
$.waveforms,
';'
),
simple_force_assignment: $ => seq(
optional($.label),
$._target,
'<=',
optional(reservedWord('guarded')),
reservedWord('force'),
optional($.force_mode),
optional($._value),
';'
),
simple_release_assignment: $ => seq(
optional($.label),
$._target,
'<=',
optional(reservedWord('guarded')),
reservedWord('release'),
optional($.force_mode),
';'
),
force_mode: $ => choice(
$._in,
$._out
),
delay_mechanism: $ => choice(
$.transport,
$.inertial,
),
transport: $ => reservedWord('transport'),
inertial: $ => seq(
optional($._reject),
reservedWord('inertial')
),
_reject: $ => seq(
reservedWord('reject'),
field('reject', $._time_expression),
),
_target: $ => field(
'target',
choice(
$._name,
$.aggregate
),
),
waveforms: $ => choice(
$.unaffected,
sepBy1(',', $.waveform_element)
),
unaffected: $ => reservedWord('unaffected'),
waveform_element: $ => seq(
$._value,
optional($._after)
),
_after: $ => seq(
reservedWord('after'),
$._time_expression
),
// }}}
// 10.5.3 Conditional signal assignments {{{
_conditional_signal_assignment: $ => choice(
$.conditional_waveform_assignment,
$.conditional_force_assignment
),
conditional_waveform_assignment: $ => prec(1,seq(
optional($.label),
$._target,
'<=',
optional(reservedWord('guarded')),
optional($.delay_mechanism),
$.conditional_waveforms,
';'
)),
_when_clause: $ => seq(
reservedWord('when'),
$._condition
),
conditional_waveforms: $ => seq(
$.waveforms,
$._when_clause,
repeat($.alternative_conditional_waveforms),
),
alternative_conditional_waveforms: $ => seq(
reservedWord('else'),
$.waveforms,
optional($._when_clause)
),
conditional_force_assignment: $ => seq(
$._target,
'<=',
reservedWord('force'),
optional($.force_mode),
$.conditional_expressions,
';'
),
conditional_expressions: $ => seq(
$._value,
$._when_clause,
repeat($.alternative_conditional_expressions),
),
alternative_conditional_expressions: $ => seq(
reservedWord('else'),
$._value,
optional($._when_clause)
),
// }}}
// 10.5.4 Selected signal assignments {{{
_selected_signal_assignment: $ => choice(
$.selected_waveform_assignment,
$.selected_force_assignment
),
selected_waveform_assignment: $ => seq(
optional($.label),
reservedWord('with'),
$._expression,
reservedWord('select'),
optional(delimiter('?')),
$._target,
'<=',
optional(reservedWord('guarded')),
optional($.delay_mechanism),
$.selected_waveforms,
';'
),
selected_force_assignment: $ => seq(
optional($.label),
reservedWord('with'),
$._expression,
reservedWord('select'),
optional(delimiter('?')),
$._target,
'<=',
reservedWord('force'),
optional($.force_mode),
$.selected_expressions,
';'
),
selected_waveforms: $ => seq(
$.waveforms,
reservedWord('when'),
$.choices,
repeat($.alternative_selected_waveforms)
),
alternative_selected_waveforms: $ => seq(
',',
$.waveforms,
reservedWord('when'),
$.choices,
),
selected_expressions: $ => seq(
$._value,
reservedWord('when'),
$.choices,
repeat($.alternative_selected_expressions)
),
alternative_selected_expressions: $ => seq(
',',
$._value,
reservedWord('when'),
$.choices,
),
// }}}
// 10.6 Variable assignments {{{
_variable_assignment_statement: $ => choice(
$.simple_variable_assignment,
$.conditional_variable_assignment,
$.selected_variable_assignment,
),
// }}}
// 10.6.2 Simple variable assignments {{{
simple_variable_assignment: $ => prec(1,seq(
optional($.label),
$._target,
':=',
$._value,
';'
)),
// }}}
// 10.6.3 Conditional variable assignments {{{
conditional_variable_assignment: $ => seq(
optional($.label),
$._target,
':=',
$.conditional_expressions,
';'
),
// }}}
// 10.6.4 Selected variable assignments {{{
selected_variable_assignment: $ => seq(
optional($.label),
reservedWord('with'),
$._expression,
reservedWord('select'),
optional(delimiter('?')),
$._target,
':=',
$.selected_expressions,
';'
),
// }}}
// 10.7 Procedure call statement {{{
procedure_call_statement: $ => prec('procedure_call', seq(
optional($.label),
optional(reservedWord('postponed')),
field('procedure', choice(
$._simple_name,
$.selected_name
)),
optional(seq(
'(',
$.association_list,
')',
)),
';'
)),
// }}}
// 10.8 If statement {{{
if_statement: $ => seq(
optional($.label),
$.if,
repeat($.elsif),
optional($.else),
reservedWord('end'),
reservedWord('if'),
optional($._end_simple_name),
';'
),
if: $ => seq(
reservedWord('if'),
$._condition,
reservedWord('then'),
optional($.sequence_of_statements),
),
elsif: $ => seq(
reservedWord('elsif'),
$._condition,
reservedWord('then'),
optional($.sequence_of_statements)
),
else: $ => seq(
reservedWord('else'),
optional($.sequence_of_statements)
),
// }}}
// 10.9 Case statement {{{
case_statement: $ => seq(
optional($.label),
reservedWord('case'),
optional(delimiter('?')),
$._expression,
reservedWord('is'),
repeat($.case_statement_alternative),
reservedWord('end'),
reservedWord('case'),
optional(delimiter('?')),
optional($._end_simple_name),
';'
),
case_statement_alternative: $ => seq(
reservedWord('when'),
$.choices,
delimiter('=>'),
optional($.sequence_of_statements)
),
// }}}
// 10.10 Loop statement {{{
loop_statement: $ => seq(
optional($.label),
optional($._iteration_scheme),
reservedWord('loop'),
optional($.sequence_of_statements),
reservedWord('end'),
reservedWord('loop'),
optional($._end_simple_name),
';'
),
_iteration_scheme: $ => choice(
$.while_loop,
$.for_loop
),
while_loop: $ => seq(
reservedWord('while'),
$._condition,
),
for_loop: $ => seq(
reservedWord('for'),
$.parameter_specification
),
parameter_specification: $ => seq(
field('name',$._identifier),
reservedWord('in'),
$._discrete_range
),
// }}}
// 10.11 Next statement {{{
next_statement: $ => seq(
optional($.label),
reservedWord('next'),
optional($._loop_label),
optional($._when_clause),
';'
),
_loop_label: $ => field(
'loop_label',
$._simple_name
),
// }}}
// 10.12 Exit statement {{{
exit_statement: $ => seq(
optional($.label),
reservedWord('exit'),
optional($._loop_label),
optional($._when_clause),
';'
),
// }}}
// 10.13 Return statement {{{
return_statement: $ => seq(
optional($.label),
reservedWord('return'),
optional($._expression),
';'
),
// }}}
// 10.14 Null statement {{{
null_statement: $ => seq(
optional($.label),
reservedWord('null'),
';'
),
// }}}
// 11 Concurrent statements {{{
concurrent_statement_part: $ => repeat1(
$._concurrent_statement
),
_concurrent_statement: $ => prec('concurrent_statement', choice(
$.block_statement,
$.process_statement,
$.component_instantiation_statement,
$.procedure_call_statement,
$.assertion_statement,
$._concurrent_signal_assignment,
$._generate_statement,
$._PSL_Directive,
$._PSL_Declaration
)),
// }}}
// 11.2 Block statement {{{
block_statement: $ => seq(
optional($.label),
reservedWord('block'),
optional(seq(
'(',
$._guard,
')'
)),
optional(reservedWord('is')),
optional(alias($._header,$.block_header)),
optional($.declarative_part),
reservedWord('begin'),
optional($.concurrent_statement_part),
reservedWord('end'),
reservedWord('block'),
optional($._end_simple_name),
';'
),
_guard: $ => field(
'guard',
$._condition
),
// }}}
// 11.3 Process statement {{{
process_statement: $ => seq(
optional($.label),
optional(reservedWord('postponed')),
reservedWord('process'),
optional(seq(
'(',
$.sensitivity_list,
')'
)),
optional(reservedWord('is')),
optional($.declarative_part),
reservedWord('begin'),
optional($.sequence_of_statements),
reservedWord('end'),
optional(reservedWord('postponed')),
reservedWord('process'),
optional($._end_simple_name),
';'
),
// }}}
// 11.6 Concurrent signal assignments {{{
_concurrent_signal_assignment: $ => choice(
alias(
$.simple_waveform_assignment,
$.simple_concurrent_signal_assignment
),
alias(
$.conditional_waveform_assignment,
$.conditional_concurrent_signal_assignment
),
alias(
$.selected_waveform_assignment,
$.selected_concurrent_signal_assignment
)
),
// }}}
// 11.7 Component instantiation statements {{{
// LINT entity aspect shall not be open
component_instantiation_statement: $ => seq(
optional($.label),
$._entity_aspect,
optional(alias($._header,$.component_map_aspect)),
';'
),
entity_instantiation: $ => seq(
reservedWord('entity'),
field('entity', choice(
$._simple_name,
$.selected_name,
)),
optional(seq(
'(',
field('architecture',$._simple_name),
')'
))
),
configuration_instantiation: $ => seq(
reservedWord('configuration'),
field('configuration', choice(
$._simple_name,
$.selected_name,
))
),
component_instantiation: $ => prec('component_instantiation',seq(
optional(reservedWord('component')),
field('component', choice(
$._simple_name,
$.selected_name,
)),
)),
// }}}
// 11.8 Generate statements {{{
_generate_statement: $ => choice(
$.for_generate_statement,
$.if_generate_statement,
$.case_generate_statement,
),
for_generate_statement: $ => seq(
optional($.label),
reservedWord('for'),
$.parameter_specification,
reservedWord('generate'),
optional($.generate_statement_body),
reservedWord('end'),
reservedWord('generate'),
optional($._end_simple_name),
';'
),
if_generate_statement: $ => seq(
optional($.label),
$.if_generate,
repeat($.elsif_generate),
optional($.else_generate),
reservedWord('end'),
reservedWord('generate'),
optional($._end_simple_name),
';'
),
if_generate: $ => seq(
reservedWord('if'),
optional($.label),
$._condition,
reservedWord('generate'),
optional($.generate_statement_body),
),
elsif_generate: $ => seq(
reservedWord('elsif'),
optional($.label),
$._condition,
reservedWord('generate'),
optional($.generate_statement_body)
),
else_generate: $ => seq(
reservedWord('else'),
optional($.label),
reservedWord('generate'),
optional($.generate_statement_body)
),
case_generate_statement: $ => seq(
optional($.label),
reservedWord('case'),
$._expression,
reservedWord('generate'),
repeat($.case_generate_alternative),
reservedWord('end'),
reservedWord('generate'),
optional($._end_simple_name),
';'
),
case_generate_alternative: $ => seq(
reservedWord('when'),
optional($.label),
$.choices,
delimiter('=>'),
optional($.generate_statement_body)
),
generate_statement_body: $ => choice(
// with begin
seq(
optional($.declarative_part),
reservedWord('begin'),
repeat($._concurrent_statement),
optional(seq(
reservedWord('end'),
optional($._end_simple_name),
';'
)),
),
// with end
seq(
optional(seq(
optional($.declarative_part),
reservedWord('begin'),
)),
repeat($._concurrent_statement),
reservedWord('end'),
optional($._end_simple_name),
';'
),
// without both
repeat1($._concurrent_statement),
),
label: $ => seq(
$._identifier,
':'
),
// }}}
// 12.4 Use clauses {{{
use_clause: $ => seq(
reservedWord('use'),
sepBy1(',', $.selected_name),
';'
),
// }}}
// 13.1 Design units {{{
design_unit: $ => prec.right(choice(
$.context_clause,
seq(
optional($.context_clause),
$._library_unit
),
)),
_library_unit: $ => choice(
$._primary_unit,
$._secondary_unit
),
_primary_unit: $ => prec('primary_unit',choice(
$.entity_declaration,
$.configuration_declaration,
$.package_declaration,
$.package_instantiation_declaration,
$.context_declaration,
$._PSL_Verification_Unit,
)),
_secondary_unit: $ => prec('secondary_unit',choice(
$.architecture_body,
$.package_body
)),
// }}}
// 13.2 Design libraries {{{
library_clause: $ => seq(
reservedWord('library'),
$.logical_name_list,
';'
),
logical_name_list: $ => sepBy1(',', field('library',$._simple_name)),
// }}}
// 13.3 Context declarations {{{
context_declaration: $ => seq(
reservedWord('context'),
field('name',$._identifier),
reservedWord('is'),
optional($.context_clause),
reservedWord('end'),
optional(reservedWord('context')),
optional($._end_simple_name),
';'
),
// }}}
// 13.4 Context clauses {{{
context_clause: $ => prec.right(repeat1(
$._context_item
)),
_context_item: $ => prec('context_item',choice(
$.library_clause,
$.use_clause,
$.context_reference
)),
context_reference: $ => seq(
reservedWord('context'),
$.context_list,
';'
),
context_list: $ => sepBy1(',', $.selected_name),
// }}}
// 15.3 Separators {{{
// }}}
// 15.4 Identifiers {{{
_identifier: $ => choice(
alias($.basic_identifier, $.identifier),
$.extended_identifier
),
basic_identifier: $ => token(seq(
/[a-zA-Z]/,
repeat(seq(
optional('_'),
/[a-zA-Z0-9]/
))
)),
extended_identifier: $ => token(seq(
'\\',
/(\\\\|[^\r\n\\])*/,
'\\',
)),
// }}}
// 15.5 Abstract literals
_abstract_literal: $ => choice(
$.integer_decimal,
$.real_decimal,
$.based_integer,
$.based_real
),
// 15.5.2 Decimal literals
integer_decimal: $ => token(seq(
repeat1(/[0-9_]/),
optional(EXPONENT)
)),
real_decimal: $ => token(seq(
repeat1(/[0-9_]/),
'.',
// not optional.
// optional used here to highlight incomplete code
optional(seq(
repeat1(/[0-9_]/),
optional(EXPONENT)
))
)),
// 15.5.3 Based literals
// TODO: Write another grammar to parse the values
based_integer: $ => token(seq(
repeat('0'),
choice(/[0-9]/,/1[0-6]/),
'#',
/[0-9a-fA-F_]*/,
'#',
optional(EXPONENT)
)),
based_real: $ => token(seq(
repeat('0'),
choice(/[0-9]/,/1[0-6]/),
'#',
/[0-9a-fA-F_]*/,
'.',
/[0-9a-fA-F_]*/,
'#',
optional(EXPONENT)
)),
// 15.6 Character literal
character_literal: $ => choice(
// Longest token has higher precedence
// the second alternative can't be matched.
// But, when the code is incomplete, tree-sitter will know
// there is only a "'" missing and will recovery from the
// error.
seq(/'.'/),
seq(/'[^;,)\r\n]/,"'"), // error recovery
),
// 15.7 String literal
string_literal: $ => choice(
// same trick used on character_literal
seq(/"(""|[^"\r\n])*"/),
seq(/"(""|[^";,)\r\n])*/,'"'),
),
// 15.8 Bit string literals
bit_string_literal: $ => choice(
seq(/[0-9]*[uUsS]?[bBoOxX]"[^" \r\n]*"/),
seq(/[0-9]*[uUsS]?[bBoOxX]"[^" ;,)\r\n]*/,'"'),
seq(/[0-9]*[dD]"[^" \r\n]*"/),
seq(/[0-9]*[dD]"[^" ;,)\r\n]*/,'"'),
),
// 15.9 Comments
comment: $ => token(choice(
prec(2,/--.*/),
prec(2,seq( // from tree-sitter-c
'/*',
/[^*]*\*+([^/*][^*]*\*+)*/,
'/'
))
)),
// 15.11 Tool directives
tool_directive: $ => token(/`.*/),
// PSL
// PSL 5. Boolean layer {{{
_PSL_Identifier: $ => alias(
$._identifier,
$.PSL_Identifier
),
_PSL_Any_Type: $ => prec(1,choice(
alias($._expr, $.PSL_Any_Type),
$.PSL_Expression,
$.PSL_Built_In_Function_Call,
$.PSL_Union_Expression,
)),
_PSL_Boolean: $ => choice(
alias($._expr, $.PSL_Boolean),
$.PSL_Expression,
$.PSL_Built_In_Function_Call
),
PSL_Parenthesized_Boolean: $ => seq(
'(',
$._PSL_Boolean,
')'
),
_PSL_Number: $ => choice(
alias($._expr, $.PSL_Number),
$.PSL_Built_In_Function_Call
),
_PSL_Value: $ => $._PSL_Any_Type,
PSL_Expression: $ => prec.right('implication', seq(
$._PSL_Boolean,
field('operator', choice(...['->', '<->'].map(op => delimiter(op)))),
$._PSL_Boolean,
)),
// }}}
// PSL 5.2.3 Built-in functions {{{
PSL_Built_In_Function_Call: $ => prec('psl_function_call', choice(
seq(
choice(
reservedWord('prev'),
reservedWord('next'),
reservedWord('stable'),
reservedWord('rose'),
reservedWord('fell'),
reservedWord('isunknown'),
reservedWord('countones'),
reservedWord('onehot'),
reservedWord('onehot0'),
reservedWord('nondet'),
reservedWord('nondet_vector'),
),
'(',
sepBy1(',', choice($._PSL_Any_Type, $.PSL_Value_Set)),
')',
),
seq(
reservedWord('ended'),
'(',
$._PSL_Sequence,
')',
)
)),
// }}}
// PSL 5.3 Clock expressions {{{
_PSL_Clock_Expression: $ => choice(
$._condition,
$.PSL_Built_In_Function_Call
),
// }}}
// PSL 5.3 Union expressions {{{
PSL_Union_Expression: $ => prec.left('union', seq(
$._PSL_Any_Type,
field('operator', reservedWord('union')),
$._PSL_Any_Type,
)),
// }}}
// PSL 5.4 Default clock declaration {{{
_PSL_Declaration: $ => choice(
$.PSL_Property_Declaration,
$.PSL_Sequence_Declaration,
$.PSL_Clock_Declaration
),
PSL_Clock_Declaration: $ => seq(
reservedWord('default'),
reservedWord('clock'),
reservedWord('is'),
$._PSL_Clock_Expression,
';'
),
// }}}
// PSL 6.1.1 Sequential Extended Regular Expressions (SEREs) {{{
_PSL_SERE: $ => choice(
$._PSL_Boolean,
$._PSL_Sequence,
$.PSL_Simple_SERE,
$._PSL_Compound_SERE,
),
PSL_Simple_SERE: $ => choice(
$._PSL_Fusion_SERE,
$._PSL_Concat_SERE,
),
_PSL_Fusion_SERE: $ => prec.right('sequence_fusion', seq(
$._PSL_SERE,
repeat1(prec.left(seq(
field('operator', delimiter(':')),
$._PSL_SERE,
))),
)),
_PSL_Concat_SERE: $ => prec.right('sequence_concatenation', seq(
$._PSL_SERE,
repeat1(prec.left(seq(
field('operator', delimiter(';')),
$._PSL_SERE,
))),
)),
// }}}
// PSL 6.1.1.2 Compound SEREs {{{
_PSL_Compound_SERE: $ => prec.dynamic(1, choice(
$.PSL_Repeated_SERE,
$.PSL_Braced_SERE,
$.PSL_Clocked_SERE,
alias(
choice(
$.PSL_Compound_SERE_And,
$.PSL_Compound_SERE_Within
),
$.PSL_Compound_SERE,
),
$.PSL_Parameterized_SERE,
)),
PSL_Compound_SERE_Or: $ => prec.right('sequence_or', seq(
$._PSL_Compound_SERE,
repeat1(prec.left(seq(
field('operator', delimiter('|')),
$._PSL_Compound_SERE,
)))
)),
PSL_Compound_SERE_And: $ => prec.right('sequence_and', seq(
$._PSL_Compound_SERE,
repeat1(prec.left(seq(
field('operator', choice(...['&', '&&'].map(op => delimiter(op)))),
$._PSL_Compound_SERE,
)))
)),
PSL_Compound_SERE_Within: $ => prec.right('sequence_within', seq(
$._PSL_Compound_SERE,
repeat1(prec.left(seq(
field('operator', reservedWord('within')),
$._PSL_Compound_SERE,
)))
)),
PSL_Parameterized_SERE: $ => seq(
reservedWord('for'),
$.PSL_Parameters_Definition,
':',
field('operator', choice(...['|', '&', '&&'].map(op => delimiter(op)))),
'{',
field('SERE', $._PSL_SERE),
'}'
),
PSL_Parameters_Definition: $ => sepBy1(',', $.PSL_Parameter_Specification),
PSL_Parameter_Specification: $ => seq(
$._PSL_Identifier,
optional($.PSL_Index_Range),
reservedWord('in'),
$.PSL_Value_Set
),
// }}}
// PSL 6.1.2 Sequences {{{
_PSL_Sequence: $ => choice(
$._PSL_Sequence_Instance,
$.PSL_Repeated_SERE,
$.PSL_Braced_SERE,
$.PSL_Clocked_SERE
),
PSL_Repeated_SERE: $ => prec.left(
'SERE_repetition',
seq(
optional(choice(
$._PSL_Boolean,
$._PSL_Sequence,
)),
$.PSL_Count,
),
),
PSL_Count: $ => seq(
'[',
optional(field('operator',
choice(...['+', '*', '=', '->'].map(op => token.immediate(prec(3, (op)))))
)),
optional(choice(
$._PSL_Number,
$._PSL_Range
)),
']',
),
_PSL_Range: $ => $._range,
PSL_Braced_SERE: $ => prec.right(seq(
'{',
$._PSL_SERE,
'}'
)),
PSL_Clocked_SERE: $ => prec.left(
'clocked',
seq(
'{',
$._PSL_SERE,
'}',
'@',
$._PSL_Clock_Expression,
)
),
// }}}
// PSL 6.2 Properties {{{
_PSL_Property: $ => choice(
$.PSL_Property_Replicator,
$._PSL_FL_Property,
$._PSL_Ambiguous_Instance,
),
_PSL_FL_Property: $ => choice(
$._PSL_Property_Instance,
$.PSL_Parenthesized_FL_Property,
$.PSL_Sequential_FL_Property,
$.PSL_Clocked_FL_Property,
$.PSL_Invariant_FL_Property,
$.PSL_Ocurrence_FL_Property,
$.PSL_Extended_Ocurrence_FL_Property,
$.PSL_Termination_FL_Property,
$.PSL_Bounding_FL_Property,
$.PSL_Suffix_Implication_FL_Property,
$.PSL_Parameterized_Property,
$.PSL_Implication_FL_Property,
$.PSL_Logical_FL_Property,
$.PSL_Factor_FL_Property,
$._PSL_Boolean
),
PSL_Parenthesized_FL_Property: $ => prec('parenthesized_property',seq(
'(',
$._PSL_FL_Property,
')',
)),
PSL_Sequential_FL_Property: $ => prec.left(-1, seq(
$._PSL_Sequence,
optional('!')
)),
PSL_Clocked_FL_Property: $ => prec.right('clocked', seq(
$._PSL_FL_Property,
repeat1(prec.left('clocked',seq(
field('operator', delimiter('@')),
$._PSL_Clock_Expression
))),
)),
PSL_Invariant_FL_Property: $ => prec.right('invariant_property', seq(
field('operator', choice(...['always', 'never'].map(op => reservedWord(op)))),
$._PSL_FL_Property
)),
PSL_Ocurrence_FL_Property: $ => prec.right('occurrence_property', seq(
field('operator', seq(
choice(...['next', 'eventually'].map(op => reservedWord(op))),
optional(token.immediate('!'))
)),
$._PSL_FL_Property
)),
PSL_Implication_FL_Property: $ => prec.right('property_implication', seq(
$._PSL_FL_Property,
repeat1(prec.left('property_implication',seq(
field('operator', choice(...['->', '<->'].map(op => delimiter(op)))),
$._PSL_FL_Property,
))),
)),
PSL_Logical_FL_Property: $ => prec.right('logical_property', seq(
$._PSL_FL_Property,
repeat1(prec.left('logical_property',seq(
field('operator', choice(...['and', 'or'].map(op => reservedWord(op)))),
$._PSL_FL_Property,
))),
)),
PSL_Factor_FL_Property: $ => prec.left('property_factor', seq(
field('operator', reservedWord('not')),
$._PSL_FL_Property,
)),
PSL_Extended_Ocurrence_FL_Property: $ => prec.right('occurrence_property', seq(
field('operator', seq(
choice(...[
'eventually',
'next',
'next_a',
'next_e',
'next_event',
'next_event_a',
'next_event_e'
].map(op => reservedWord(op))),
optional(token.immediate('!'))
)),
$._PSL_Extended_Ocurrence_argument,
)),
_PSL_Extended_Ocurrence_argument: $ => seq(
choice(
$._PSL_Extended_Ocurrence_FL_Property_Count_Specification,
$._PSL_Extended_Ocurrence_FL_Property_Until_Specification,
),
'(',
field('Property', $._PSL_FL_Property),
')',
),
_PSL_Extended_Ocurrence_FL_Property_Count_Specification: $ => seq(
$.PSL_Count,
),
_PSL_Extended_Ocurrence_FL_Property_Until_Specification: $ => prec('parenthesized_boolean',seq(
'(',
field('Boolean', $._PSL_Boolean),
')',
optional($.PSL_Count),
)),
PSL_Termination_FL_Property: $ => prec.left('termination_property', seq(
$._PSL_FL_Property,
field('operator', choice(...['async_abort', 'sync_abort', 'abort'].map(op => reservedWord(op)))),
$._PSL_Boolean
)),
PSL_Bounding_FL_Property: $ => prec.right('bounding_property', seq(
$._PSL_FL_Property,
field('operator', seq(
choice(...['until', 'before'].map(op => reservedWord(op))),
optional(token.immediate('!')),
optional(token.immediate('_'))
)),
$._PSL_FL_Property,
)),
PSL_Suffix_Implication_FL_Property: $ => choice(
prec.right(seq(
'{',
field('SERE', $._PSL_SERE),
'}',
'(',
field('Property', $._PSL_FL_Property),
')',
)),
prec.right('sequence_implication', choice(
...['|=>', '|->'].map(op => {
return seq(
field('Sequence', $._PSL_Sequence),
field('operator', delimiter(op)),
field('Property', $._PSL_FL_Property),
)
})
)),
),
PSL_Parameterized_Property: $ => seq(
reservedWord('for'),
$.PSL_Parameters_Definition,
':',
field('operator', choice(...['and', 'or'].map(op => reservedWord(op)))),
'(',
$._PSL_FL_Property,
')',
),
// }}}
// PSL 6.2.3 Replicated properties {{{
PSL_Property_Replicator: $ => seq(
reservedWord('forall'),
$.PSL_Parameter_Specification,
':',
field('Property',
choice(
prec.dynamic(3,$._PSL_Property_Instance),
$._PSL_Property
)
)
),
PSL_Index_Range: $ => seq(
'(',
$._PSL_Range,
')'
),
PSL_Value_Set: $ => choice(
$.boolean,
seq(
'{',
$._PSL_Value_Range,
repeat(seq(
',', $._PSL_Value_Range
)),
'}',
),
),
boolean: $ => reservedWord('boolean'),
_PSL_Value_Range: $ => choice(
$._PSL_Value,
$._PSL_Range
),
// }}}
// PSL 6.3 Property and sequence declarations {{{
PSL_Property_Declaration: $ => seq(
reservedWord('property'),
$._PSL_Identifier,
optional(seq(
'(',
$.PSL_Formal_Parameter_List,
')',
)),
reservedWord('is'),
choice(
prec.dynamic(3, $._PSL_Property_Instance),
$._PSL_Property,
),
';'
),
PSL_Sequence_Declaration: $ => seq(
reservedWord('sequence'),
$._PSL_Identifier,
optional(seq(
'(',
$.PSL_Formal_Parameter_List,
')',
)),
reservedWord('is'),
$._PSL_Sequence,
';'
),
PSL_Formal_Parameter_List: $ => sepBy1(';', $.PSL_Formal_Parameter),
PSL_Formal_Parameter: $ => seq(
$._PSL_Parameter_Specification,
sepBy1(',', $._PSL_Identifier)
),
_PSL_Parameter_Specification: $ => choice(
$.PSL_Constant_Parameter_Specification,
$.PSL_Temporal_Parameter_Specification,
),
PSL_Constant_Parameter_Specification: $ => choice(
reservedWord('const'),
seq(
optional(reservedWord('const')),
choice(
$.PSL_HDL_Type,
$.PSL_Type_Class
)
),
),
PSL_Temporal_Parameter_Specification: $ => choice(
reservedWord('sequence'),
reservedWord('property'),
),
PSL_HDL_Type: $ => seq(
reservedWord('hdltype'),
$.subtype_indication
),
PSL_Type_Class: $ => choice(
reservedWord('boolean'),
reservedWord('bit'),
reservedWord('bit_vector'),
reservedWord('numeric'),
reservedWord('string'),
),
// }}}
// PSL 6.3.3 Instantiation {{{
PSL_Instance: $ => seq(
$._PSL_Identifier,
optional(seq(
'(',
$.PSL_Actual_Parameter_List,
')'
))
),
_PSL_Ambiguous_Instance: $ => prec.dynamic(-1,seq(
alias($.PSL_Instance, $.PSL_Ambiguous_Instance)
)),
_PSL_Sequence_Instance: $ => prec.dynamic(-2,
alias($.PSL_Instance, $.PSL_Sequence_Instance)
),
_PSL_Property_Instance: $ => prec.dynamic(-2,
alias($.PSL_Instance, $.PSL_Property_Instance)
),
PSL_Actual_Parameter_List: $ => sepBy1(',', $.PSL_Actual_Parameter),
PSL_Actual_Parameter: $ => choice(
$._PSL_Any_Type,
$._PSL_Sequence,
$._PSL_Property
),
// }}}
// PSL 7.1 Verification directives {{{
_PSL_Directive: $ => choice(
$.PSL_Assert_Directive,
$.PSL_Assume_Directive,
$.PSL_Assume_Guarantee_Directive,
$.PSL_Restrict_Directive,
$.PSL_Restrict_Guarantee_Directive,
$.PSL_Cover_Directive,
$.PSL_Fairness_Directive,
$.PSL_Strong_Fairness_Directive,
),
PSL_Assert_Directive: $ => prec('psl_assertion',seq(
optional($.label),
reservedWord('assert'),
$._PSL_Property,
optional($._report),
';'
)),
PSL_Assume_Directive: $ => seq(
optional($.label),
reservedWord('assume'),
$._PSL_Property,
';'
),
PSL_Assume_Guarantee_Directive: $ => seq(
optional($.label),
reservedWord('assume_guarantee'),
$._PSL_Property,
optional($._report),
';'
),
PSL_Restrict_Directive: $ => seq(
optional($.label),
reservedWord('restrict'),
$._PSL_Sequence,
';'
),
PSL_Restrict_Guarantee_Directive: $ => seq(
optional($.label),
reservedWord('restrict_guarantee'),
$._PSL_Sequence,
optional($._report),
';'
),
PSL_Cover_Directive: $ => seq(
optional($.label),
reservedWord('cover'),
$._PSL_Sequence,
optional($._report),
';'
),
PSL_Fairness_Directive: $ => seq(
optional($.label),
reservedWord('fairness'),
$._PSL_Boolean,
';'
),
PSL_Strong_Fairness_Directive: $ => seq(
optional($.label),
reservedWord('strong'),
reservedWord('fairness'),
$._PSL_Boolean,
',',
$._PSL_Boolean,
';'
),
// }}}
// PSL 7.2 Verification units {{{
_PSL_Verification_Unit: $ => choice(
$.PSL_VUnit,
$.PSL_VProp,
$.PSL_VMode
),
PSL_VUnit: $ => seq(
reservedWord('vunit'),
$._PSL_Identifier,
$.PSL_Verification_Unit_Body
),
PSL_VProp: $ => seq(
reservedWord('vprop'),
$._PSL_Identifier,
$.PSL_Verification_Unit_Body
),
PSL_VMode: $ => seq(
reservedWord('vmode'),
$._PSL_Identifier,
$.PSL_Verification_Unit_Body
),
PSL_Verification_Unit_Body: $ => seq(
optional(seq(
'(',
$.PSL_Hierarchical_HDL_Name,
')'
)),
'{',
repeat($.PSL_Inherit_Spec),
repeat($._PSL_VUnit_Item),
'}'
),
PSL_Hierarchical_HDL_Name: $ => seq(
$._PSL_HDL_Module_NAME,
repeat(seq(
choice(
token.immediate('.'),
token.immediate('/'),
),
field('instance', $._simple_name)
))
),
_PSL_HDL_Module_NAME: $ => seq(
field('entity', $._simple_name),
optional(seq(
'(',
field('architecture', $._simple_name),
')'
))
),
PSL_Inherit_Spec: $ => seq(
reservedWord('inherit'),
sepBy1(',', $._name),
';'
),
_PSL_VUnit_Item: $ => choice(
$._declaration,
$._concurrent_statement
),
// }}}
},
supertype: $ => [
$._primary_unit,
$._secondary_unit,
$._context_item,
$._sequential_statement,
$._concurrent_statement,
$._PSL_Verification_Unit,
$._PSL_Declaration,
$._PSL_Directive
]
})
// Helper functions {{{
function binary_expression(prec, operands, optable) {
return choice(...optable.map(([operator, precedence, tokenize]) => {
return prec(precedence, seq(
field('left', operands),
field('operator', tokenize(operator)),
field('right', operands)
))
}))
}
function unary_expression(prec, operand, optable) {
return choice(...optable.map(([operator, precedence, tokenize]) => {
return prec(precedence, seq(
field('operator', tokenize(operator)),
field('argument', operand)
))
}))
}
function delimiter(delim, precedence = 2) {
return token(prec(precedence, delim))
}
function reservedWord(word) {
//return word
return alias(reserved(caseInsensitive(word)), word)
}
function reserved(regex) {
return token(prec(2, new RegExp(regex)))
}
function caseInsensitive(word) {
return word.split('')
.map(letter => `[${letter}${letter.toUpperCase()}]`)
.join('')
}
function sepBy1(sep, rule) {
return seq(rule, repeat(seq(sep, rule)))
}
function sepBy(sep, rule) {
return optional(sepBy1(sep, rule))
}
// }}}