EPFL - Swiss Federal Institute of Technology
Computer Science Department, Software Engineering Laboratory
basic_declaration:
abstract_subprogram_declaration.
type_declaratrion:
private_extension_declaration.
object_declaration:
single_task_declaration | single_protected_declaration.
derived_type_definition:
record_extension_part.
access_type_definition:
access_to_subprogram_definition.
proper_body:
protected_body.
name:
direct_name | type_conversion
| explicit_dereference | function_call.
aggregate:
record_aggregate | extension_aggregate | array_aggregate.
simple_statement:
requeue_statement.
renaming_declaration:
generic_renaming_declaration.
select_statement:
asynchronous_select.
generic_formal_parameter_declaration:
formal_object_declaration
| formal_type_declaration
| formal_subprogram_declaration
| formal_package_declaration.
new keywords:
abstract aliased protected requeue tagged until
Given these differences, we found that it is easier, to write the
syntax Ada95 from scratch, than to try to modify the syntax of Ada83.
In the following chapter, we present the difficulties in writing the
syntax of Ada95.
4.1:
name = direct_name | explicit_dereference
| indexed_component | slice
| selected_component | attribute_reference
| type_conversion | function_call
| CHARACTER_LITERAL.
explicit_dereference = name "." "ALL".
indexed_component = prefix "(" {+ expression $ "," +} ")".
= name indexed_component_body.
slice = prefix "(" discrete_range ")".
= name slice_body.
selected_component = prefix "." selector_name.
= name selected_component_body.
attribute_reference = prefix "'" attribute_designator.
= name attribute_designator_body
type_conversion = subtype_mark "(" expression ")".
= name type_conversion_body.
function_call = name | prefix actual_parameter_part.
= name [ actual_parameter_part ]
= name [ function_call_body ].
prefix = name.
subtype_mark = name.
Because all elements except direct_name and character_literal
start with name, we can rewrite name as following:
name = ( direct_name | CHARACTER_LITERAL )
{+ explicit_dereference_body
| indexed_component_body | slice_body
| selected_component_body | attribute_reference_body
| type_conversion_body | [ function_call_body ]
+}.
= ( direct_name | CHARACTER_LITERAL )
{ explicit_dereference_body
| indexed_component_body | slice_body
| selected_component_body | attribute_reference_body
| type_conversion_body | function_call_body
}.
indexed_component_body and type_converstion_body are a subset of
function_call_body, so we can eliminate these two. The problem is,
that slice_body and function_call_body are very similar, and the parser
needs a very long time to distinguish them. Here we write the rules
for slice_body and function_call_body:
slice_body = "(" discrete_range ")".
discrete_range = subtype_indication | range.
subtype_indication = subtype_mark [ constraint ].
= name [ subtype_indication_body ].
subtype_mark = name.
range = range_attribute_reference
| simple_expression ".." simple_expression.
range_attribute_reference = prefix "'" range_attribute_designator.
= name range_attribute_reference_body
range_attribute_designator = "RANGE" [ "(" expression ")" ].
function_call_body = actual_parameter_part.
actual_parameter_part = "(" {+ parameter_association $ "," +} ")".
parameter_association = [ selector_name "=>" ]
explicit_actual_parameter.
explicit_actual_parameter = expression.
slice_body = "(" ( name [ subtype_indication_body ]
| name range_attribute_reference_body
| simple_expression ".."
simple_expression
) ")".
function_call_body = "(" {+ [ selector_name "=>" ]
expression $ "," +} ")"
An example where slice_body and function_call_body are the same is:
(A(A(A))).
slice_body = "(" expression
( [ subtype_indication_body ]
| range_attribute_reference_body
| ".." simple_expression
) ")".
function_call_body = "(" ( expression
{ "," [ selector_name "=>" ] expression }
| selector_name "=>" expression
{ "," [ selector_name "=>" ] expression }
) ")"
Note, that slice_body without subtype_indication_body is included
in function_call_body.
The union of these two gives:
slice_body_or_function_call_body =
"(" ( expression ( subtype_indication_body
| range_attribute_reference_body
| ".." simple_expression
| { "," [ selector_name "=>" ] expression }
)
| selector_name "=>" expression
{ "," [ selector_name "=>" ] expression }
) ")".
There were some other easier ambiguities to resolve like:
parameter_specification = defining_identifier_list ":" mode subtype_mark [ ":=" default_expression ]. parameter_specification = defining_identifier_list ":" access_definition [ ":=" default_expression ].Which results to:
parameter_specification = defining_identifier_list ":" (mode subtype_mark | access_definition ) [ ":=" default_expression ].
sequence_of_statements = <+INCR+>
{+ <+SET+> statement +} <+DECR+>.
if_statement =
"IF" <+SPACE+> condition <+SPACE+> "THEN"
sequence_of_statements
{ <+SET+> "ELSIF" <+SPACE+> condition <+SPACE+> "THEN"
sequence_of_statements }
[ <+SET+> "ELSE" sequence_of_statements ]
<+SET+> "END" <+SPACE+> "IF" ";".