tree-sitter-ada/grammar.js
Emmanuel Briot 51a69f0fb4 Additions to the grammar
This currently fails the testsuite because of ambiguities
2022-10-21 14:11:41 +02:00

1050 lines
29 KiB
JavaScript

function toCaseInsensitive(a) {
var ca = a.charCodeAt(0);
if (ca>=97 && ca<=122) return `[${a}${a.toUpperCase()}]`;
if (ca>=65 && ca<= 90) return `[${a.toLowerCase()}${a}]`;
return a;
}
function caseInsensitive(keyword) {
//return keyword; // Easier to read conflict messages
return new RegExp(keyword
.split('')
.map(toCaseInsensitive)
.join('')
)
}
/**
* A list of rules
*/
function list_of(separator, rule) {
return seq(
rule,
repeat(seq(
separator,
rule,
)),
);
}
/**
* Handles comma-separated lists of rules
*/
function comma_separated_list_of(rule) {
return list_of(',', rule)
}
module.exports = grammar({
name: 'ada',
extras: $ => [
/\s|\\\r?\n/,
$.comment,
],
// word: $ => $.keyword,
word: $ => $.identifier,
conflicts: $ => [
// "name" can be either a simple name, or a defining_identifier_list
// [$.direct_name, $.defining_identifier_list],
// "function_specification is" could be either an expression function
// specification, or a function specification
// ??? Maybe we can merge both in the grammar
[$.expression_function_declaration, $.subprogram_specification],
// ??? Maybe we can merge these
[$.null_procedure_declaration, $.subprogram_specification],
// "'for' direct_name * 'use'" could also be "'for' name * 'use'" as
// specified in at_clause.
[$.at_clause, $.name],
// "procedure name is" could be either a procedure specification, or
// a generic_instantiation.
[$.generic_instantiation, $.procedure_specification],
// Same for "package_specification ;"
[$.generic_package_declaration, $._package_declaration],
[$.attribute_definition_clause, $.attribute_reference],
[$.record_extension_part, $.derived_type_definition],
],
rules: {
compilation: $ => repeat(
$.compilation_unit,
),
keyword: $ => /[a-zA-Z]+/,
identifier: $ =>
/[a-zA-Z\u{80}-\u{10FFFF}][0-9a-zA-Z_\u{80}-\u{10FFFF}]*/u,
comment: $ => token(seq('--', /.*/)),
string_literal: $ => token(/"[^"]*"/),
character_literal: $ => token(/'.'/),
numeric_literal: $ => token(
choice(
/[0-9]/,
/[0-9_]+(\.[0-9]+)?([eE][0-9_-]+)?/,
/[0-9]+#[0-9a-fA-F._-]+#/
)
),
relational_operator: $ => choice('=', '/=', '<', '<=', '>', '>='),
binary_adding_operator: $ => choice('+', '-', '&'),
unary_adding_operator: $ => choice('+', '-'),
multiplying_operator: $ => choice('*', '/', 'mod', 'rem'),
tick: $ => choice(
'\'', // But is not the start of a character_literal
),
name_list: $ => comma_separated_list_of($.name),
name: $ => choice(
$.direct_name,
$.explicit_dereference,
$.selected_component,
$.attribute_reference,
$.function_call,
$.character_literal,
$.qualified_expression,
'@',
),
defining_identifier_list: $ => comma_separated_list_of($.identifier),
direct_name: $ => choice(
$.identifier,
$.string_literal,
),
explicit_dereference: $ => seq(
$.name,
'.',
caseInsensitive('all'),
),
selected_component: $ => seq(
$.name,
'.',
$.selector_name,
),
selector_name: $ => choice(
$.direct_name,
$.character_literal,
caseInsensitive('others'),
),
attribute_reference: $ => choice(
seq(
$.name,
$.tick,
$.attribute_designator,
),
// $.reduction_attribute_reference,
),
// reduction_attribute_reference: $ => seq(
// $.value_sequence,
// $.tick,
// $.reduction_attribute_designator,
// ),
reduction_attribute_designator: $ => seq(
$.identifier,
'(',
$.reduction_specification,
')',
),
reduction_specification: $ => seq(
$.name,
',',
$.expression,
),
// value_sequence: $ => seq(
// '[',
// optional(seq(
// field('is_parallel', caseInsensitive('parallel')),
// optional(seq(
// '(',
// $.chunk_specification,
// ')',
// )),
// )),
// $.iterated_element_association,
// ']',
// ),
chunk_specification: $ => choice(
$.simple_expression,
seq(
$.identifier,
caseInsensitive('in'),
$.discrete_subtype_definition,
),
),
iterated_element_association: $ => seq(
caseInsensitive('for'),
choice(
$.loop_parameter_specification,
$.iterator_specification,
),
optional(seq(
caseInsensitive('use'),
$.expression,
)),
$.assoc_expression,
),
discrete_subtype_definition: $ => choice(
$.subtype_indication,
$.range_g,
),
loop_parameter_specification: $ => seq(
$.identifier,
caseInsensitive('in'),
optional(caseInsensitive('reverse')),
$.discrete_subtype_definition,
optional($.iterator_filter),
),
loop_parameter_subtype_indication: $ => choice(
$.subtype_indication,
$.access_definition,
),
iterator_filter: $ => seq(
caseInsensitive('when'),
$.condition,
),
iterator_specification: $ => seq(
$.identifier,
optional(seq(
':',
$.loop_parameter_subtype_indication,
)),
choice(
caseInsensitive('in'),
caseInsensitive('of'),
),
optional(caseInsensitive('reverse')),
$.name,
optional($.iterator_filter),
),
attribute_designator: $ => choice(
$.identifier,
caseInsensitive('access'),
caseInsensitive('delta'),
caseInsensitive('digits'),
caseInsensitive('mod'),
),
function_call: $ => seq(
$.name,
$.actual_parameter_part,
),
qualified_expression: $ => seq(
$.name,
$.tick,
$.aggregate,
),
compilation_unit: $ => choice(
$.with_clause,
seq(
optional(caseInsensitive('private')),
$._declarative_item,
),
$.statement,
$.subunit,
$.entry_declaration,
),
_declarative_item: $ => choice(
$._basic_declarative_item,
$.proper_body,
$.body_stub,
),
_basic_declarative_item: $ => choice(
$._basic_declaration,
$.aspect_clause,
$.use_clause,
),
_basic_declaration: $ => choice(
$.type_declaration,
$.subtype_declaration,
$.object_declaration,
$.number_declaration,
$.subprogram_declaration,
$.abstract_subprogram_declaration,
$.null_procedure_declaration,
$.expression_function_declaration,
$._package_declaration,
$.renaming_declaration,
$.exception_declaration,
$.generic_declaration,
$.generic_instantiation,
),
_package_declaration: $ => seq(
$.package_specification,
';',
),
package_specification: $ => seq(
caseInsensitive('package'),
field('name', $.name), // $.defining_program_unit_name),
optional($.aspect_specification),
caseInsensitive('is'),
optional($._basic_declarative_item_list),
optional(seq(
caseInsensitive('private'),
optional($._basic_declarative_item_list),
)),
caseInsensitive('end'),
field('endname', optional($.name)),
),
with_clause: $ => seq(
field('is_limited', optional(caseInsensitive('limited'))),
field('is_private', optional(caseInsensitive('private'))),
caseInsensitive('with'),
field('names', $.name_list),
';',
),
use_clause: $ => seq(
caseInsensitive('use'),
optional(seq(
field('is_all', optional(caseInsensitive('all'))),
field('is_type', caseInsensitive('type')),
)),
$.name_list,
';',
),
subunit: $ => seq(
caseInsensitive('separate'),
'(',
$.name,
')',
$.proper_body,
),
proper_body: $ => choice(
// $.subprogram_body,
$.package_body,
// $.task_body,
// $.protected_body,
),
package_body: $ => seq(
caseInsensitive('package'),
caseInsensitive('body'),
$.name,
optional($.aspect_specification),
caseInsensitive('is'),
optional($.non_empty_declarative_part),
optional(seq(
caseInsensitive('begin'),
$.handled_sequence_of_statements,
)),
caseInsensitive('end'),
optional($.name),
';',
),
subtype_indication: $ => seq(
optional($.null_exclusion),
$.name,
optional($.constraint),
),
constraint: $ => choice(
$.scalar_constraint,
$.index_constraint,
),
scalar_constraint: $ => choice(
$.range_constraint,
$.digits_constraint,
$.delta_constraint,
),
range_g: $ => choice(
// $.range_attribute_reference,
seq(
$.simple_expression,
'..',
$.simple_expression,
),
),
range_constraint: $ => seq(
caseInsensitive('range'),
$.range_g,
),
condition: $ => seq(
$.expression,
';',
),
expression: $ => choice(
$.relation,
seq($.relation, $.AND_relation_list),
seq($.relation, $.AND_THEN_relation_list),
seq($.relation, $.OR_relation_list),
seq($.relation, $.OR_ELSE_relation_list),
seq($.relation, $.XOR_relation_list),
),
assoc_expression: $ => seq(
'=>',
choice(
$.expression,
'<>',
),
),
AND_relation_list: $ => repeat1(seq(
caseInsensitive('and'),
$.relation,
)),
AND_THEN_relation_list: $ => repeat1(seq(
caseInsensitive('and'),
caseInsensitive('then'),
$.relation,
)),
OR_relation_list: $ => repeat1(seq(
caseInsensitive('or'),
$.relation,
)),
OR_ELSE_relation_list: $ => repeat1(seq(
caseInsensitive('or'),
caseInsensitive('else'),
$.relation,
)),
XOR_relation_list: $ => repeat1(seq(
caseInsensitive('xor'),
$.relation,
)),
relation: $ => choice(
seq(
$.simple_expression,
optional(seq(
$.relational_operator,
$.simple_expression,
))
),
// seq(
// $.simple_expression,
// optional(caseInsensitive('not')),
// caseInsensitive('in'),
// $.membership_choice_list,
// ),
// $.raise_expression,
),
simple_expression: $ => seq(
optional($.unary_adding_operator),
$.term,
repeat(seq(
$.binary_adding_operator,
$.term,
)),
),
term: $ => seq(
$.factor,
repeat(seq(
$.multiplying_operator,
$.factor,
)),
),
factor: $ => choice(
seq(
$.primary,
optional(seq(
'**',
$.primary,
)),
),
seq(
caseInsensitive('abs'),
$.primary,
),
seq(
caseInsensitive('not'),
$.primary,
),
),
primary: $ => choice(
$.numeric_literal,
caseInsensitive('null'),
$.aggregate,
$.name,
// $.allocator,
),
access_definition: $ => seq(
optional($.null_exclusion),
caseInsensitive('access'),
choice(
seq(
optional(caseInsensitive('constant')),
$.name,
),
seq(
optional(caseInsensitive('protected')),
caseInsensitive('procedure'),
optional($.non_empty_parameter_profile),
),
seq(
optional(caseInsensitive('protected')),
caseInsensitive('function'),
$.parameter_and_result_profile,
),
),
),
actual_parameter_part: $ => seq(
'(',
choice(
comma_separated_list_of($.parameter_association),
// $.conditional_expression,
// $.quantified_expression,
// $.declare_expression,
),
')',
),
parameter_association: $ => choice(
seq(
$.component_choice_list,
$.assoc_expression,
),
$.expression,
'<>',
),
component_choice_list: $ => choice(
$.selector_name,
seq(
$.component_choice_list,
'|',
$.selector_name,
),
),
aggregate: $ => choice(
$.record_aggregate,
// $.extension_aggregate,
// $.array_aggregate,
// $.delta_aggregate,
// seq(
// '(',
// choice(
// $.conditional_expression,
// $.quantified_expression,
// $.declare_expression,
// ),
// ')',
// ),
),
record_aggregate: $ => seq(
'(',
$.record_component_association_list,
')',
),
record_component_association_list: $ => choice(
// comma_separated_list_of($.record_component_association),
seq(
caseInsensitive('null'),
caseInsensitive('record'),
),
),
null_exclusion: $ => seq(
caseInsensitive('not'),
caseInsensitive('null'),
),
index_constraint: $ => seq(
'(',
// comma_separated_list_of($.discrete_range),
')',
),
digits_constraint: $ => seq(
caseInsensitive('digits'),
$.simple_expression,
optional($.range_constraint),
),
delta_constraint: $ => seq(
caseInsensitive('delta'),
$.simple_expression,
optional($.range_constraint),
),
_basic_declarative_item_list: $ => repeat1(
$._basic_declarative_item_pragma,
),
_basic_declarative_item_pragma: $ => choice(
$._basic_declarative_item,
$.pragma_g,
),
type_declaration: $ => choice(
$.full_type_declaration,
// $.incomplete_type_declaration,
// $.private_type_declaration,
// $.private_extension_declaration,
),
full_type_declaration: $ => choice(
seq(
caseInsensitive('type'),
$.identifier,
// optional($.known_discriminant_part),
caseInsensitive('is'),
$.type_definition,
// optional($.aspect_specification),
';',
),
// $.task_type_declaration,
// $.protected_type_declaration,
),
type_definition: $ => choice(
// $.enumeration_type_definition,
$.integer_type_definition,
// $.real_type_definition,
// $.array_type_definition,
// $.record_type_definition,
// $.access_type_definition,
$.derived_type_definition,
// $.interface_type_definition,
),
integer_type_definition: $ => choice(
$.signed_integer_type_definition,
// $.modular_type_definition,
),
signed_integer_type_definition: $ => seq(
caseInsensitive('range'),
$.simple_expression,
'..',
$.simple_expression,
),
derived_type_definition: $ => seq(
optional(caseInsensitive('abstract')),
optional(caseInsensitive('limited')),
caseInsensitive('new'),
$.subtype_indication,
optional(seq(
// optional(seq(
// caseInsensitive('and'),
// $.interface_list,
// )),
$.record_extension_part,
)),
),
record_extension_part: $ => seq(
caseInsensitive('with'),
$.record_definition,
),
record_definition: $ => choice(
seq(
caseInsensitive('record'),
$.component_list,
caseInsensitive('end'),
caseInsensitive('record'),
optional($.identifier),
),
seq(
caseInsensitive('null'),
caseInsensitive('record'),
),
),
component_list: $ => choice(
repeat1($.component_item),
// seq(
// optional($.component_item),
// $.variant_part,
// ),
caseInsensitive('null'),
),
component_item: $ => seq(
$.component_declaration,
$.aspect_clause,
),
component_declaration: $ => seq(
$.defining_identifier_list,
':',
$.component_definition,
// optional($.assign_value),
optional($.aspect_specification),
';'
),
component_definition: $ => seq(
optional(caseInsensitive('aliased')),
choice(
$.subtype_indication,
// $.access_definition,
),
),
abstract_subprogram_declaration: $ => seq(
optional($.overriding_indicator),
$.subprogram_specification,
caseInsensitive('is'),
caseInsensitive('abstract'),
$.aspect_specification,
';',
),
array_aggregate: $ => choice(
// $.position_array_aggregate,
// $.null_array_aggregate,
// $.named_array_aggregate,
),
aspect_association: $ => seq(
$.aspect_mark,
optional(seq(
'=>',
$.aspect_definition,
)),
),
aspect_clause: $ => choice(
$.attribute_definition_clause,
$.enumeration_representation_clause,
$.record_representation_clause,
$.at_clause,
),
aspect_definition: $ => choice(
$.expression,
$.global_aspect_definition,
),
aspect_mark: $ => seq(
$.identifier,
optional(seq(
$.tick,
$.identifier,
)),
),
aspect_mark_list: $ => comma_separated_list_of($.aspect_association),
aspect_specification: $ => seq(
caseInsensitive('with'),
$.aspect_mark_list,
),
at_clause: $ => seq(
caseInsensitive('for'),
$.direct_name,
caseInsensitive('use'),
caseInsensitive('at'),
$.expression,
';',
),
attribute_definition_clause: $ => seq(
caseInsensitive('for'),
$.name,
$.tick,
$.attribute_designator,
caseInsensitive('use'),
$.expression,
';',
),
body_stub: $ => choice(
// $.subprogram_body_stub,
// $.package_body_stub,
// $.task_body_stub,
// $.protected_body_stub,
),
choice_parameter_specification: $ => $.identifier, // ??? inline
component_clause: $ => seq(
$.name,
caseInsensitive('at'),
field('position', $.expression),
caseInsensitive('range'),
field('first_bit', $.simple_expression),
'..',
field('last_bit', $.simple_expression),
';',
),
declarative_item_pragma: $ => choice(
$._declarative_item,
$.pragma_g,
),
non_empty_declarative_part: $ => repeat1(
$.declarative_item_pragma,
),
entry_declaration: $ => seq(
optional($.overriding_indicator),
caseInsensitive('entry'),
$.identifier,
optional(seq(
'(',
$.discrete_subtype_definition,
')',
)),
optional($.non_empty_parameter_profile),
optional($.aspect_specification),
';',
),
enumeration_aggregate: $ => $.array_aggregate, // ??? inline
enumeration_representation_clause: $ => seq(
caseInsensitive('for'),
$.name,
caseInsensitive('use'),
$.enumeration_aggregate,
';',
),
exception_choice_list: $ => list_of('|', $.exception_choice),
exception_choice: $ => choice(
$.name,
caseInsensitive('others'),
),
exception_declaration: $ => seq(
$.defining_identifier_list,
':',
caseInsensitive('exception'),
optional($.aspect_specification),
';',
),
exception_handler: $ => seq(
caseInsensitive('when'),
optional(seq(
$.choice_parameter_specification,
':',
)),
$.exception_choice_list,
'=>',
$.sequence_of_statements,
),
exception_handler_list: $ => repeat1(choice(
$.exception_handler,
$.pragma_g,
)),
expression_function_declaration: $ => seq(
optional($.overriding_indicator),
$.function_specification,
caseInsensitive('is'),
'(',
$.expression,
')',
optional($.aspect_specification),
';',
),
formal_part: $ => seq(
'(',
$.parameter_specification_list,
')',
),
function_specification: $ => seq(
caseInsensitive('function'),
$.name,
$.parameter_and_result_profile,
),
generic_declaration: $ => choice(
$.generic_subprogram_declaration,
$.generic_package_declaration,
),
generic_formal_part: $ => seq(
caseInsensitive('generic'),
repeat($.generic_formal_parameter_declaration),
),
generic_formal_parameter_declaration: $ => choice(
// $.formal_objet_declaration,
// $.formal_type_declaration,
// $.formal_subprogram_declaration,
// $.formal_package_declaration,
$.use_clause,
$.pragma_g,
),
generic_subprogram_declaration: $ => seq(
$.generic_formal_part,
$.subprogram_specification,
optional($.aspect_specification),
';',
),
generic_package_declaration: $ => seq(
$.generic_formal_part,
$.package_specification,
';',
),
generic_instantiation: $ => seq(
choice(
caseInsensitive('package'),
seq(
optional($.overriding_indicator),
choice(
caseInsensitive('procedure'),
caseInsensitive('function'),
),
),
),
$.name,
caseInsensitive('is'),
caseInsensitive('new'),
$.name, // includes the generic_actual_part
optional($.aspect_specification),
';',
),
global_aspect_definition: $ => choice(
seq(
$.global_mode,
// $.global_designator,
),
// $.extended_global_aspect_definition,
seq(
'(',
comma_separated_list_of($.global_aspect_element),
')',
),
),
global_aspect_element: $ => choice(
seq(
$.global_mode,
$.global_set,
),
// $.extended_global_aspect_definition,
),
global_mode: $ => choice(
$.non_empty_mode,
caseInsensitive('overriding'),
),
global_set: $ => prec.left(
comma_separated_list_of($.name), // ??? name_list
),
handled_sequence_of_statements: $ => seq(
$.sequence_of_statements,
optional(seq(
caseInsensitive('exception'),
$.exception_handler_list,
)),
),
label: $ => seq(
'<<',
field('statement_identifier', $.direct_name),
'>>',
),
mod_clause: $ => seq(
caseInsensitive('at'),
caseInsensitive('mod'),
$.expression,
';',
),
non_empty_mode: $ => choice(
caseInsensitive('in'),
seq(
caseInsensitive('in'),
caseInsensitive('out'),
),
caseInsensitive('out'),
),
null_procedure_declaration: $ => seq(
optional($.overriding_indicator),
$.procedure_specification,
caseInsensitive('is'),
caseInsensitive('null'),
// optional($.aspect_specification),
),
null_statement: $ => seq(
caseInsensitive('null'),
';',
),
number_declaration: $ => seq(
$.defining_identifier_list,
';',
caseInsensitive('constant'),
// $.assign_value,
';',
),
object_declaration: $ => choice(
seq(
$.defining_identifier_list,
':',
caseInsensitive('aliased'),
caseInsensitive('constant'),
choice(
$.subtype_indication,
$.access_definition,
// $.array_type_definition,
),
// optional($.assign_value),
optional($.aspect_specification),
';',
),
// $.single_task_declaration,
// $.single_protected_declaration,
),
overriding_indicator: $ => seq(
optional(caseInsensitive('not')),
caseInsensitive('overriding'),
),
non_empty_parameter_profile: $ => // ??? inline
$.formal_part,
parameter_and_result_profile: $ => seq(
optional($.formal_part),
$.result_profile,
),
parameter_specification: $ => seq(
$.defining_identifier_list,
':',
optional(caseInsensitive('aliased')),
optional($.non_empty_mode),
optional($.null_exclusion),
$.name,
// optional($.assign_value),
),
parameter_specification_list: $ => list_of(
';',
$.parameter_specification,
),
pragma_g: $ => seq(
caseInsensitive('pragma'),
$.identifier,
optional(seq(
'(',
choice(
// $.pragma_argument_association_list,
// $.conditional_quantified_expression,
),
')',
)),
';'
),
procedure_specification: $ => seq(
caseInsensitive('procedure'),
$.name,
optional($.non_empty_parameter_profile),
),
record_representation_clause: $ => prec.left(seq(
caseInsensitive('for'),
$.name,
caseInsensitive('use'),
caseInsensitive('record'),
optional($.mod_clause),
repeat($.component_clause),
caseInsensitive('end'),
caseInsensitive('record'),
optional($.name),
)),
renaming_declaration: $ => choice(
// $.object_renaming_declaration,
// $.exception_renaming_declaration,
// $.package_renaming_declaration,
// $.subprogram_renaming_declaration,
// $.generic_renaming_declaration,
),
result_profile: $ => seq(
caseInsensitive('return'),
choice(
seq(
optional($.null_exclusion),
$.name,
),
$.access_definition,
),
),
sequence_of_statements: $ => prec.left(seq(
repeat1($.statement),
repeat($.label),
)),
simple_statement: $ => choice(
$.null_statement,
// $.assignment_statement,
// $.exit_statement,
// $.goto_statement,
// $.procedure_call_statement,
// $.simple_return_statement,
// $.requeue_statement,
// $.delay_statement,
// $.abort_statement,
// $.raise_statement,
$.pragma_g,
),
statement: $ => seq(
repeat($.label),
choice(
$.simple_statement,
// $.compound_statement,
),
),
subprogram_declaration: $ => seq(
optional($.overriding_indicator),
$.subprogram_specification,
optional($.aspect_specification),
';',
),
subprogram_specification: $ => choice(
$.procedure_specification,
$.function_specification,
),
subtype_declaration: $ => seq(
caseInsensitive('subtype'),
$.identifier,
caseInsensitive('is'),
$.subtype_indication,
optional($.aspect_specification),
';',
),
}
});