summaryrefslogtreecommitdiffstats
path: root/languages/ada/ada.g
diff options
context:
space:
mode:
Diffstat (limited to 'languages/ada/ada.g')
-rw-r--r--languages/ada/ada.g1982
1 files changed, 1982 insertions, 0 deletions
diff --git a/languages/ada/ada.g b/languages/ada/ada.g
new file mode 100644
index 00000000..5f97952b
--- /dev/null
+++ b/languages/ada/ada.g
@@ -0,0 +1,1982 @@
+/*
+ * Ada95 Grammar for ANTLR, target language C++
+ *
+ * Copyright (C) 2003 Oliver M. Kellogg <okellogg@users.sourceforge.net>
+ * Modifications (C) 2005 Daniel Zuberbuehler <dzubi@users.sourceforge.net>
+ *
+ * Adapted from lexer9x.l/grammar9x.y,
+ *
+ ******* A YACC grammar for Ada 9X *********************************
+ * Copyright (C) Intermetrics, Inc. 1994 Cambridge, MA USA *
+ * Copying permitted if accompanied by this statement. *
+ * Derivative works are permitted if accompanied by this statement.*
+ * This grammar is thought to be correct as of May 1, 1994 *
+ * but as usual there is *no warranty* to that effect. *
+ *******************************************************************
+ *
+ * $Id$
+ *
+ * Not all rules from the Ada95 Reference Manual (RM) Annex P,
+ * Syntax Summary, are mirrored as rules here.
+ * The tree nodes follow the RM grammar as closely as sensible.
+ * This applies in particular to the terminals. OTOH, trivially
+ * reconstructable non-terminal rules are not reflected in the tree.
+ * FIXME: Document the exact rationale of the tree design.
+ *
+ */
+
+
+header "pre_include_hpp" {
+#include <antlr/SemanticException.hpp> // antlr wants this
+#include "AdaAST.hpp"
+#include "preambles.h"
+}
+
+options {
+ language="Cpp";
+}
+
+//-----------------------------------------------------------------------------
+// Define a Parser, calling it AdaParser
+//-----------------------------------------------------------------------------
+class AdaParser extends Parser;
+options {
+ k = 2; // token lookahead
+ exportVocab=Ada; // Call its vocabulary "Ada"
+ // codeGenMakeSwitchThreshold = 2; // Some optimizations
+ // codeGenBitsetTestThreshold = 3;
+ defaultErrorHandler = false; // Generate parser error handlers
+ buildAST = true;
+ ASTLabelType = "RefAdaAST";
+}
+
+{
+ ANTLR_PARSER_PREAMBLE
+
+public:
+ // Ada support stuff
+ void push_def_id (const RefAdaAST& defid);
+ const RefAdaAST& pop_def_id ();
+ bool end_id_matches_def_id (const RefAdaAST& endid);
+ bool definable_operator (const char *string); // operator_symbol sans "/="
+ bool is_operator_symbol (const char *string);
+}
+
+// Compilation Unit: This is the start rule for this parser.
+// The rules in this grammar are listed in the order in which
+// compilation_unit introduces them, depth first, with the
+// exception of the expression related rules which are listed
+// towards the end.
+compilation_unit
+ : context_items_opt ( library_item | subunit ) ( pragma )*
+ ;
+
+// The pragma related rules are pulled up here to get them out of the way.
+
+pragma : PRAGMA^ IDENTIFIER pragma_args_opt SEMI!
+ ;
+
+pragma_args_opt : ( LPAREN! pragma_arg ( COMMA! pragma_arg )* RPAREN! )?
+ ;
+
+pragma_arg : ( IDENTIFIER RIGHT_SHAFT^ )? expression
+ ;
+
+context_items_opt : ( pragma | with_clause | use_clause )*
+ { #context_items_opt =
+ #(#[CONTEXT_CLAUSE, "CONTEXT_CLAUSE"], #context_items_opt); }
+ // RM Annex P neglects pragmas; we include them.
+ // The node should really be named CONTEXT_ITEMS_OPT but we
+ // stick with the RM wording.
+ ;
+
+with_clause : w:WITH^ c_name_list SEMI!
+ { Set(#w, WITH_CLAUSE); }
+ ;
+
+c_name_list : compound_name ( COMMA! compound_name )*
+ ;
+
+compound_name : IDENTIFIER ( DOT^ IDENTIFIER )*
+ // Strangely, the RM never defines this rule, which however is
+ // required for tightening up the syntax of certain names
+ // (library unit names etc.)
+ ;
+
+use_clause : u:USE^
+ ( TYPE! subtype_mark ( COMMA! subtype_mark )*
+ { Set(#u, USE_TYPE_CLAUSE); }
+ | c_name_list { Set(#u, USE_CLAUSE); }
+ )
+ SEMI!
+ ;
+
+subtype_mark : compound_name ( TIC^ attribute_id )?
+ // { #subtype_mark = #(#[SUBTYPE_MARK, "SUBTYPE_MARK"], #subtype_mark); }
+ ;
+
+attribute_id : RANGE
+ | DIGITS
+ | DELTA
+ | ACCESS
+ | IDENTIFIER
+ ;
+
+library_item : private_opt
+ /* Slightly loose; PRIVATE can only precede
+ {generic|package|subprog}_decl.
+ Semantic check required to ensure it.*/
+ ( lib_pkg_spec_or_body
+ | subprog_decl_or_rename_or_inst_or_body[true]
+ | generic_decl[true]
+ )
+ { #library_item = #(#[LIBRARY_ITEM, "LIBRARY_ITEM"], #library_item); }
+ ;
+
+private_opt : ( PRIVATE )?
+ { #private_opt = #(#[MODIFIERS, "MODIFIERS"], #private_opt); }
+ ;
+
+lib_pkg_spec_or_body
+ : pkg:PACKAGE^
+ ( BODY! def_id[true] IS! pkg_body_part SEMI!
+ { Set(#pkg, PACKAGE_BODY); }
+ | def_id[true] spec_decl_part[#pkg]
+ )
+ ;
+
+subprog_decl [boolean lib_level]
+ { RefAdaAST t; }
+ : p:PROCEDURE^ def_id[lib_level]
+ ( generic_subp_inst
+ { Set(#p, GENERIC_PROCEDURE_INSTANTIATION); }
+ | formal_part_opt
+ ( renames { Set(#p, PROCEDURE_RENAMING_DECLARATION); }
+ | is_separate_or_abstract_or_decl[#p]
+ )
+ SEMI!
+ )
+ | f:FUNCTION^ def_designator[lib_level]
+ ( generic_subp_inst
+ { Set(#f, GENERIC_FUNCTION_INSTANTIATION); }
+ | function_tail
+ ( renames { Set(#f, FUNCTION_RENAMING_DECLARATION); }
+ | is_separate_or_abstract_or_decl[#f]
+ )
+ SEMI!
+ )
+ ;
+
+def_id [boolean lib_level]
+ : { lib_level }? cn:compound_name { push_def_id(#cn); }
+ | { !lib_level }? n:IDENTIFIER { push_def_id(#n); }
+ ;
+
+generic_subp_inst : IS! generic_inst SEMI!
+ ;
+
+generic_inst : NEW! compound_name ( LPAREN! value_s RPAREN! )?
+ { pop_def_id(); }
+ ;
+
+parenth_values : LPAREN! value ( COMMA! value )* RPAREN!
+ ;
+
+value : ( OTHERS^ RIGHT_SHAFT! expression
+ | ranged_expr_s ( RIGHT_SHAFT^ expression )?
+ )
+ // { #value = #(#[VALUE, "VALUE"], #value); }
+ ;
+
+ranged_expr_s : ranged_expr ( PIPE^ ranged_expr )*
+ // { #ranged_expr_s =
+ // #(#[RANGED_EXPRS, "RANGED_EXPRS"], #ranged_expr_s); }
+ ;
+
+ranged_expr : expression
+ ( DOT_DOT^ simple_expression
+ | RANGE^ range
+ )?
+ ;
+
+range_constraint : r:RANGE^ range
+ { Set(#r, RANGE_CONSTRAINT); }
+ ;
+
+range : ( (range_dots) => range_dots
+ | range_attrib_ref
+ )
+ // Current assumption is we don't need an extra node for range,
+ // otherwise uncomment the following line:
+ // { #range = #(#[RANGE_EXPR, "RANGE_EXPR"], #range); }
+ ;
+
+range_dots : simple_expression DOT_DOT^ simple_expression
+ ;
+
+range_attrib_ref : // "name TIC RANGE" is ambiguous; instead:
+ prefix TIC! r:RANGE^ ( LPAREN! expression RPAREN! )?
+ { Set(#r, RANGE_ATTRIBUTE_REFERENCE); }
+ ;
+
+// Here, the definition of `prefix' deviates from the RM.
+// This gives us some more strictness than `name' (which the RM uses to
+// define `prefix'.)
+prefix : IDENTIFIER
+ ( DOT^ ( ALL | IDENTIFIER )
+ | p:LPAREN^ value_s RPAREN!
+ { Set(#p, INDEXED_COMPONENT); }
+ )*
+ ;
+
+formal_part_opt : ( LPAREN! parameter_specification
+ ( SEMI! parameter_specification )*
+ RPAREN! )?
+ { #formal_part_opt = #([FORMAL_PART_OPT, "FORMAL_PART_OPT"],
+ #formal_part_opt); }
+ ;
+
+parameter_specification : def_ids_colon mode_opt subtype_mark init_opt
+ { #parameter_specification =
+ #(#[PARAMETER_SPECIFICATION,
+ "PARAMETER_SPECIFICATION"], #parameter_specification); }
+ ;
+
+def_ids_colon : defining_identifier_list COLON!
+ ;
+
+defining_identifier_list : IDENTIFIER ( COMMA! IDENTIFIER )*
+ { #defining_identifier_list =
+ #(#[DEFINING_IDENTIFIER_LIST,
+ "DEFINING_IDENTIFIER_LIST"], #defining_identifier_list); }
+ ;
+
+mode_opt : ( IN ( OUT )? | OUT | ACCESS )?
+ { #mode_opt = #(#[MODIFIERS, "MODIFIERS"], #mode_opt); }
+ ;
+
+renames { RefAdaAST dummy; }
+ : RENAMES! ( name
+ | dummy=definable_operator_symbol
+ )
+ { pop_def_id(); }
+ ;
+
+name { RefAdaAST dummy; }
+ : IDENTIFIER
+ ( DOT^ ( ALL
+ | IDENTIFIER
+ | CHARACTER_LITERAL
+ | dummy=is_operator
+ )
+ | p:LPAREN^ value_s RPAREN!
+ { Set(#p, INDEXED_COMPONENT); }
+ | TIC^ attribute_id // must be in here because of e.g.
+ // Character'Pos (x)
+ )*
+ // { #name = #(#[NAME, "NAME"], #name); }
+ ;
+
+is_operator returns [RefAdaAST d]
+ : { is_operator_symbol(LT(1)->getText().c_str()) }?
+ op:CHAR_STRING { #op->setType(OPERATOR_SYMBOL); d=#op; }
+ ;
+
+definable_operator_symbol returns [RefAdaAST d]
+ : { definable_operator(LT(1)->getText().c_str()) }?
+ op:CHAR_STRING { #op->setType(OPERATOR_SYMBOL); d=#op; }
+ ;
+
+parenthesized_primary : pp:LPAREN^
+ ( NuLL RECORD!
+ | value_s extension_opt
+ )
+ RPAREN!
+ { Set(#pp, PARENTHESIZED_PRIMARY); }
+ ;
+
+extension_opt : ( WITH! ( NuLL RECORD! | value_s ) )?
+ { #extension_opt =
+ #(#[EXTENSION_OPT, "EXTENSION_OPT"], #extension_opt); }
+ ;
+
+is_separate_or_abstract_or_decl! [RefAdaAST t]
+ : IS! separate_or_abstract[t]
+ | { pop_def_id();
+ if (t->getType() == AdaTokenTypes::PROCEDURE)
+ Set(t, PROCEDURE_DECLARATION);
+ else
+ Set(t, FUNCTION_DECLARATION);
+ }
+ ;
+
+separate_or_abstract! [RefAdaAST t]
+ : SEPARATE!
+ { pop_def_id();
+ if (t->getType() == AdaTokenTypes::PROCEDURE)
+ Set(t, PROCEDURE_BODY_STUB);
+ else
+ Set(t, FUNCTION_BODY_STUB);
+ }
+ | ABSTRACT!
+ { pop_def_id();
+ if (t->getType() == AdaTokenTypes::PROCEDURE)
+ Set(t, ABSTRACT_PROCEDURE_DECLARATION);
+ else
+ Set(t, ABSTRACT_FUNCTION_DECLARATION);
+ }
+ ;
+
+def_designator [boolean lib_level]
+ { RefAdaAST d; }
+ : { lib_level }? n:compound_name { push_def_id(#n); }
+ | { !lib_level }? d=designator { push_def_id(d); }
+ ;
+
+designator returns [RefAdaAST d]
+ { RefAdaAST op; }
+ : op=definable_operator_symbol { d = op; }
+ | n:IDENTIFIER { d = #n; }
+ ;
+
+function_tail : func_formal_part_opt RETURN! subtype_mark
+ ;
+
+// formal_part_opt is not strict enough for functions, i.e. it permits
+// "in out" and "out" as modes, thus we make an extra rule:
+func_formal_part_opt : ( LPAREN! func_param ( SEMI! func_param )* RPAREN! )?
+ { #func_formal_part_opt =
+ #([FORMAL_PART_OPT,
+ "FORMAL_PART_OPT"], #func_formal_part_opt); }
+ ;
+
+func_param : def_ids_colon in_access_opt subtype_mark init_opt
+ { #func_param =
+ #(#[PARAMETER_SPECIFICATION,
+ "PARAMETER_SPECIFICATION"], #func_param); }
+ ;
+
+in_access_opt : ( IN | ACCESS )?
+ { #in_access_opt = #(#[MODIFIERS, "MODIFIERS"], #in_access_opt); }
+ ;
+
+spec_decl_part [RefAdaAST pkg]
+ : ( IS! ( generic_inst { Set(pkg, GENERIC_PACKAGE_INSTANTIATION); }
+ | pkg_spec_part { Set(pkg, PACKAGE_SPECIFICATION); }
+ )
+ | renames { Set(pkg, PACKAGE_RENAMING_DECLARATION); }
+ )
+ SEMI!
+ ;
+
+pkg_spec_part : basic_declarative_items_opt
+ private_declarative_items_opt
+ end_id_opt
+ ;
+
+private_declarative_items_opt : ( PRIVATE! ( basic_decl_item | pragma )* )?
+ { #private_declarative_items_opt =
+ #(#[PRIVATE_DECLARATIVE_ITEMS_OPT,
+ "PRIVATE_DECLARATIVE_ITEMS_OPT"],
+ #private_declarative_items_opt); }
+ ;
+
+basic_declarative_items_opt : ( basic_decl_item | pragma )*
+ { #basic_declarative_items_opt =
+ #(#[BASIC_DECLARATIVE_ITEMS_OPT,
+ "BASIC_DECLARATIVE_ITEMS_OPT"],
+ #basic_declarative_items_opt); }
+ ;
+
+basic_declarative_items : ( basic_decl_item | pragma )+
+ { #basic_declarative_items =
+ #(#[BASIC_DECLARATIVE_ITEMS_OPT,
+ "BASIC_DECLARATIVE_ITEMS_OPT"],
+ #basic_declarative_items); }
+ ;
+
+basic_decl_item
+ : pkg:PACKAGE^ def_id[false] spec_decl_part[#pkg]
+ | tsk:TASK^ task_type_or_single_decl[#tsk]
+ | pro:PROTECTED^ prot_type_or_single_decl[#pro] SEMI!
+ | subprog_decl[false]
+ | decl_common
+ ;
+
+task_type_or_single_decl [RefAdaAST tsk]
+ : TYPE! def_id[false] discrim_part_opt task_definition_opt
+ { Set(tsk, TASK_TYPE_DECLARATION); }
+ | def_id[false] task_definition_opt
+ { Set(tsk, SINGLE_TASK_DECLARATION); }
+ ;
+
+task_definition_opt
+ : IS! task_items_opt private_task_items_opt end_id_opt SEMI!
+ | SEMI! { pop_def_id(); }
+ ;
+
+discrim_part_opt
+ : ( discrim_part_text )?
+ { #discrim_part_opt =
+ #(#[DISCRIM_PART_OPT,
+ "DISCRIM_PART_OPT"], #discrim_part_opt); }
+ ;
+
+discrim_part_text : LPAREN! (BOX | discriminant_specifications) RPAREN!
+ ;
+
+known_discrim_part
+ : LPAREN! discriminant_specifications RPAREN!
+ { #known_discrim_part =
+ #(#[DISCRIM_PART_OPT,
+ "DISCRIM_PART_OPT"], #known_discrim_part); }
+ ;
+
+empty_discrim_opt : /* empty */
+ { #empty_discrim_opt =
+ #(#[DISCRIM_PART_OPT,
+ "DISCRIM_PART_OPT"], #empty_discrim_opt); }
+ ;
+
+discrim_part
+ : discrim_part_text
+ { #discrim_part =
+ #(#[DISCRIM_PART_OPT,
+ "DISCRIM_PART_OPT"], #discrim_part); }
+ ;
+
+discriminant_specifications : discriminant_specification
+ ( SEMI! discriminant_specification )*
+ { #discriminant_specifications =
+ #(#[DISCRIMINANT_SPECIFICATIONS,
+ "DISCRIMINANT_SPECIFICATIONS"],
+ #discriminant_specifications); }
+ ;
+
+discriminant_specification : def_ids_colon access_opt subtype_mark init_opt
+ { #discriminant_specification =
+ #(#[DISCRIMINANT_SPECIFICATION,
+ "DISCRIMINANT_SPECIFICATION"],
+ #discriminant_specification); }
+ ;
+
+access_opt : ( ACCESS )?
+ { #access_opt = #(#[MODIFIERS, "MODIFIERS"], #access_opt); }
+ ;
+
+init_opt : ( ASSIGN! expression )?
+ { #init_opt = #(#[INIT_OPT, "INIT_OPT"], #init_opt); }
+ ; // `expression' is of course much too loose;
+ // semantic checks are required in the usage contexts.
+
+task_items_opt : ( pragma )* entrydecls_repspecs_opt
+ { #task_items_opt =
+ #(#[TASK_ITEMS_OPT, "TASK_ITEMS_OPT"], #task_items_opt); }
+ ;
+
+entrydecls_repspecs_opt : ( entry_declaration ( pragma | rep_spec )* )*
+ ;
+
+entry_declaration : e:ENTRY^ IDENTIFIER
+ discrete_subtype_def_opt formal_part_opt SEMI!
+ { Set (#e, ENTRY_DECLARATION); }
+ ;
+
+discrete_subtype_def_opt : ( (LPAREN discrete_subtype_definition RPAREN) =>
+ LPAREN! discrete_subtype_definition RPAREN!
+ | /* empty */
+ )
+ { #discrete_subtype_def_opt =
+ #(#[DISCRETE_SUBTYPE_DEF_OPT,
+ "DISCRETE_SUBTYPE_DEF_OPT"], #discrete_subtype_def_opt); }
+ ;
+
+discrete_subtype_definition : ( (range) => range
+ | subtype_ind
+ )
+ // Looks alot like discrete_range, but it's not
+ // (as soon as we start doing semantics.)
+ /* TBC: No need for extra node, just use the inner nodes?
+ { #discrete_subtype_definition =
+ #(#[DISCRETE_SUBTYPE_DEFINITION,
+ "DISCRETE_SUBTYPE_DEFINITION"],
+ #discrete_subtype_definition); }
+ */
+ ;
+
+rep_spec : r:FOR^ subtype_mark USE! rep_spec_part[#r] SEMI!
+ ;
+
+rep_spec_part [RefAdaAST t]
+ : RECORD! align_opt comp_loc_s END! RECORD! // record_type_spec
+ { Set(t, RECORD_REPRESENTATION_CLAUSE); }
+ | AT! expression // address_spec (Ada83)
+ { Set(t, AT_CLAUSE); }
+ | expression // attrib_def. Semantic check must ensure that the
+ // respective subtype_mark contains an attribute reference.
+ { Set(t, ATTRIBUTE_DEFINITION_CLAUSE); }
+ ;
+
+align_opt : ( AT! MOD! expression SEMI! )?
+ { #align_opt = #(#[MOD_CLAUSE_OPT, "MOD_CLAUSE_OPT"], #align_opt); }
+ ;
+
+comp_loc_s : ( pragma | subtype_mark AT! expression RANGE! range SEMI! )*
+ { #comp_loc_s = #(#[COMPONENT_CLAUSES_OPT, "COMPONENT_CLAUSES_OPT"],
+ #comp_loc_s); }
+ ;
+
+private_task_items_opt : ( PRIVATE! ( pragma )* entrydecls_repspecs_opt )?
+ { #private_task_items_opt =
+ #(#[PRIVATE_TASK_ITEMS_OPT,
+ "PRIVATE_TASK_ITEMS_OPT"], #private_task_items_opt); }
+ // Maybe we could just reuse TASK_ITEMS_OPT here instead of
+ // making a separate node type.
+ ;
+
+prot_type_or_single_decl [RefAdaAST pro]
+ : TYPE! def_id[false] discrim_part_opt protected_definition
+ { Set(pro, PROTECTED_TYPE_DECLARATION); }
+ | def_id[false] protected_definition
+ { Set(pro, SINGLE_PROTECTED_DECLARATION); }
+ ;
+
+prot_private_opt : ( PRIVATE! ( prot_op_decl | comp_decl )* )?
+ { #prot_private_opt =
+ #(#[PROT_PRIVATE_OPT,
+ "PROT_PRIVATE_OPT"], #prot_private_opt); }
+ ;
+
+protected_definition
+ : IS! prot_op_decl_s prot_private_opt end_id_opt
+ ;
+
+prot_op_decl_s : ( prot_op_decl )*
+ { #prot_op_decl_s = #(#[PROT_OP_DECLARATIONS,
+ "PROT_OP_DECLARATIONS"], #prot_op_decl_s); }
+ ;
+
+prot_op_decl : entry_declaration
+ | p:PROCEDURE^ def_id[false] formal_part_opt SEMI!
+ { pop_def_id(); Set(#p, PROCEDURE_DECLARATION); }
+ | f:FUNCTION^ def_designator[false] function_tail SEMI!
+ { pop_def_id(); Set(#f, FUNCTION_DECLARATION); }
+ | rep_spec
+ | pragma
+ ;
+
+prot_member_decl_s : ( prot_op_decl | comp_decl )*
+ { #prot_member_decl_s =
+ #(#[PROT_MEMBER_DECLARATIONS,
+ "PROT_MEMBER_DECLARATIONS"], #prot_member_decl_s); }
+ ;
+
+comp_decl : def_ids_colon component_subtype_def init_opt SEMI!
+ { #comp_decl =
+ #(#[COMPONENT_DECLARATION,
+ "COMPONENT_DECLARATION"], #comp_decl); }
+ ;
+
+// decl_common is shared between declarative_item and basic_decl_item.
+// decl_common only contains specifications.
+decl_common
+ : t:TYPE^ IDENTIFIER
+ ( IS! type_def[#t]
+ | ( discrim_part
+ ( IS! derived_or_private_or_record[#t, true]
+ | { Set(#t, INCOMPLETE_TYPE_DECLARATION); }
+ )
+ | empty_discrim_opt
+ { Set(#t, INCOMPLETE_TYPE_DECLARATION); }
+ // NB: In this case, the discrim_part_opt does not
+ // appear in the INCOMPLETE_TYPE_DECLARATION node.
+ )
+ /* The artificial derived_or_private_or_record rule
+ gives us some syntax-level control over where a
+ discrim_part may appear.
+ However, a semantic check is still necessary to make
+ sure the discrim_part is not given for a derived type
+ of an elementary type, or for the full view of a
+ private type that turns out to be such. */
+ )
+ SEMI!
+ | s:SUBTYPE^ IDENTIFIER IS! subtype_ind SEMI! // subtype_decl
+ { Set(#s, SUBTYPE_DECLARATION); }
+ | generic_decl[false]
+ | use_clause
+ | r:FOR^ ( (local_enum_name USE LPAREN) => local_enum_name USE!
+ enumeration_aggregate
+ { Set(#r, ENUMERATION_REPESENTATION_CLAUSE); }
+ | subtype_mark USE! rep_spec_part[#r]
+ )
+ SEMI!
+ | (IDENTIFIER COLON EXCEPTION RENAMES) =>
+ IDENTIFIER erd:COLON^ EXCEPTION! RENAMES! compound_name SEMI!
+ { Set(#erd, EXCEPTION_RENAMING_DECLARATION); }
+ | (IDENTIFIER COLON subtype_mark RENAMES) =>
+ IDENTIFIER ord:COLON^ subtype_mark RENAMES! name SEMI!
+ { Set(#ord, OBJECT_RENAMING_DECLARATION); }
+ | defining_identifier_list od:COLON^ // object_declaration
+ ( EXCEPTION!
+ { Set(#od, EXCEPTION_DECLARATION); }
+ | (CONSTANT ASSIGN) => CONSTANT! ASSIGN! expression
+ { Set(#od, NUMBER_DECLARATION); }
+ | aliased_constant_opt
+ ( array_type_definition[#od] init_opt
+ { Set(#od, ARRAY_OBJECT_DECLARATION); }
+ // Not an RM rule, but simplifies distinction
+ // from the non-array object_declaration.
+ | subtype_ind init_opt
+ { Set(#od, OBJECT_DECLARATION); }
+ )
+ )
+ SEMI!
+ ;
+
+type_def [RefAdaAST t]
+ : LPAREN! enum_id_s RPAREN!
+ { Set(t, ENUMERATION_TYPE_DECLARATION); }
+ | RANGE! range
+ { Set(t, SIGNED_INTEGER_TYPE_DECLARATION); }
+ | MOD! expression
+ { Set(t, MODULAR_TYPE_DECLARATION); }
+ | DIGITS! expression range_constraint_opt
+ { Set(t, FLOATING_POINT_DECLARATION); }
+ | DELTA! expression
+ ( RANGE! range
+ { Set(t, ORDINARY_FIXED_POINT_DECLARATION); }
+ | DIGITS! expression range_constraint_opt
+ { Set(t, DECIMAL_FIXED_POINT_DECLARATION); }
+ )
+ | array_type_definition[t]
+ | access_type_definition[t]
+ | empty_discrim_opt derived_or_private_or_record[t, false]
+ ;
+
+enum_id_s : enumeration_literal_specification
+ ( COMMA! enumeration_literal_specification )*
+ ;
+
+enumeration_literal_specification : IDENTIFIER | CHARACTER_LITERAL
+ ;
+
+range_constraint_opt : ( range_constraint )?
+ ;
+
+array_type_definition [RefAdaAST t]
+ : ARRAY! LPAREN! index_or_discrete_range_s RPAREN!
+ OF! component_subtype_def
+ { Set(t, ARRAY_TYPE_DECLARATION); }
+ ;
+
+index_or_discrete_range_s
+ : index_or_discrete_range ( COMMA^ index_or_discrete_range )*
+ ;
+
+index_or_discrete_range
+ : simple_expression
+ ( DOT_DOT^ simple_expression // constrained
+ | RANGE^ ( BOX // unconstrained
+ | range // constrained
+ )
+ )?
+ ;
+
+component_subtype_def : aliased_opt subtype_ind
+ ;
+
+aliased_opt : ( ALIASED )?
+ { #aliased_opt = #(#[MODIFIERS, "MODIFIERS"], #aliased_opt); }
+ ;
+
+subtype_ind : subtype_mark constraint_opt
+ { #subtype_ind = #(#[SUBTYPE_INDICATION, "SUBTYPE_INDICATION"],
+ #subtype_ind); }
+ ;
+
+constraint_opt : ( range_constraint
+ | digits_constraint
+ | delta_constraint
+ | (index_constraint) => index_constraint
+ | discriminant_constraint
+ )?
+ ;
+
+digits_constraint : d:DIGITS^ expression range_constraint_opt
+ { Set(#d, DIGITS_CONSTRAINT); }
+ ;
+
+delta_constraint : d:DELTA^ expression range_constraint_opt
+ { Set(#d, DELTA_CONSTRAINT); }
+ ;
+
+index_constraint : p:LPAREN^ discrete_range ( COMMA! discrete_range )* RPAREN!
+ { Set(#p, INDEX_CONSTRAINT); }
+ ;
+
+discrete_range
+ : (range) => range
+ | subtype_ind
+ ;
+
+discriminant_constraint : p:LPAREN^ discriminant_association
+ ( COMMA! discriminant_association )* RPAREN!
+ { Set(#p, DISCRIMINANT_CONSTRAINT); }
+ ;
+
+discriminant_association : selector_names_opt expression
+ { #discriminant_association =
+ #(#[DISCRIMINANT_ASSOCIATION,
+ "DISCRIMINANT_ASSOCIATION"], #discriminant_association); }
+ ;
+
+selector_names_opt : ( (association_head) => association_head
+ | /* empty */
+ )
+ { #selector_names_opt =
+ #(#[SELECTOR_NAMES_OPT,
+ "SELECTOR_NAMES_OPT"], #selector_names_opt); }
+ ;
+
+association_head : selector_name ( PIPE! selector_name )* RIGHT_SHAFT!
+ ;
+
+selector_name : IDENTIFIER // TBD: sem pred
+ ;
+
+access_type_definition [RefAdaAST t]
+ : ACCESS!
+ ( protected_opt
+ ( PROCEDURE! formal_part_opt
+ { Set(t, ACCESS_TO_PROCEDURE_DECLARATION); }
+ | FUNCTION! func_formal_part_opt RETURN! subtype_mark
+ { Set(t, ACCESS_TO_FUNCTION_DECLARATION); }
+ )
+ | constant_all_opt subtype_ind
+ { Set(t, ACCESS_TO_OBJECT_DECLARATION); }
+ )
+ ;
+
+protected_opt : ( PROTECTED )?
+ { #protected_opt = #(#[MODIFIERS, "MODIFIERS"], #protected_opt); }
+ ;
+
+constant_all_opt : ( CONSTANT | ALL )?
+ { #constant_all_opt =
+ #(#[MODIFIERS, "MODIFIERS"], #constant_all_opt); }
+ ;
+
+derived_or_private_or_record [RefAdaAST t, boolean has_discrim]
+ : ( ( ABSTRACT )? NEW subtype_ind WITH ) =>
+ abstract_opt NEW! subtype_ind WITH!
+ ( PRIVATE! { Set(t, PRIVATE_EXTENSION_DECLARATION); }
+ | record_definition[has_discrim]
+ { Set(t, DERIVED_RECORD_EXTENSION); }
+ )
+ | NEW! subtype_ind { Set(t, ORDINARY_DERIVED_TYPE_DECLARATION); }
+ | abstract_tagged_limited_opt
+ ( PRIVATE! { Set(t, PRIVATE_TYPE_DECLARATION); }
+ | record_definition[has_discrim]
+ { Set(t, RECORD_TYPE_DECLARATION); }
+ )
+ ;
+
+abstract_opt : ( ABSTRACT )?
+ { #abstract_opt = #(#[MODIFIERS, "MODIFIERS"], #abstract_opt); }
+ ;
+
+record_definition [boolean has_discrim]
+ : RECORD! component_list[has_discrim] END! RECORD!
+ | NuLL! RECORD! // Thus the component_list is optional in the tree.
+ ;
+
+component_list [boolean has_discrim]
+ : NuLL! SEMI! // Thus the component_list is optional in the tree.
+ | component_items ( variant_part { has_discrim }? )?
+ | empty_component_items variant_part { has_discrim }?
+ ;
+
+component_items : ( pragma | comp_decl )+
+ { #component_items =
+ #(#[COMPONENT_ITEMS,
+ "COMPONENT_ITEMS"], #component_items); }
+ ;
+
+empty_component_items :
+ { #empty_component_items =
+ #(#[COMPONENT_ITEMS,
+ "COMPONENT_ITEMS"], #empty_component_items); }
+ ;
+
+variant_part : c:CASE^ discriminant_direct_name IS! variant_s END! CASE! SEMI!
+ { Set (#c, VARIANT_PART); }
+ ;
+
+discriminant_direct_name : IDENTIFIER // TBD: symtab lookup.
+ ;
+
+variant_s : ( variant )+
+ { #variant_s = #(#[VARIANTS, "VARIANTS"], #variant_s); }
+ ;
+
+variant : w:WHEN^ choice_s RIGHT_SHAFT! component_list[true]
+ { Set (#w, VARIANT); }
+ ;
+
+choice_s : choice ( PIPE^ choice )*
+ ;
+
+choice : OTHERS
+ | (discrete_with_range) => discrete_with_range
+ | expression // ( DOT_DOT^ simple_expression )?
+ ; // No, that's already in discrete_with_range
+
+discrete_with_range : (mark_with_constraint) => mark_with_constraint
+ | range
+ ;
+
+mark_with_constraint : subtype_mark range_constraint
+ { #mark_with_constraint =
+ #(#[MARK_WITH_CONSTRAINT,
+ "MARK_WITH_CONSTRAINT"], #mark_with_constraint); }
+ ;
+
+abstract_tagged_limited_opt
+ : ( ABSTRACT TAGGED! | TAGGED )?
+ ( LIMITED )?
+ { #abstract_tagged_limited_opt =
+ #(#[MODIFIERS, "MODIFIERS"], #abstract_tagged_limited_opt); }
+ ;
+
+local_enum_name : IDENTIFIER // to be refined: do a symbol table lookup
+ ;
+
+enumeration_aggregate : parenth_values
+ ;
+
+aliased_constant_opt : ( ALIASED )? ( CONSTANT )?
+ { #aliased_constant_opt =
+ #(#[MODIFIERS, "MODIFIERS"], #aliased_constant_opt); }
+ ;
+
+generic_decl [boolean lib_level]
+ : g:GENERIC^ generic_formal_part_opt
+ ( PACKAGE! def_id[lib_level]
+ ( renames { Set(#g, GENERIC_PACKAGE_RENAMING); }
+ | IS! pkg_spec_part { Set(#g, GENERIC_PACKAGE_DECLARATION); }
+ )
+ | PROCEDURE! def_id[lib_level] formal_part_opt
+ ( renames { Set(#g, GENERIC_PROCEDURE_RENAMING); }
+ // ^^^ Semantic check must ensure that the (generic_formal)*
+ // after GENERIC is not given here.
+ | { Set(#g, GENERIC_PROCEDURE_DECLARATION); pop_def_id(); }
+ )
+ | FUNCTION! def_designator[lib_level] function_tail
+ ( renames { Set(#g, GENERIC_FUNCTION_RENAMING); }
+ // ^^^ Semantic check must ensure that the (generic_formal)*
+ // after GENERIC is not given here.
+ | { Set(#g, GENERIC_FUNCTION_DECLARATION); pop_def_id(); }
+ )
+ )
+ SEMI!
+ ;
+
+generic_formal_part_opt : ( use_clause | pragma | generic_formal_parameter )*
+ { #generic_formal_part_opt =
+ #(#[GENERIC_FORMAL_PART,
+ "GENERIC_FORMAL_PART"],
+ #generic_formal_part_opt); }
+ ;
+
+generic_formal_parameter :
+ ( t:TYPE^ def_id[false]
+ ( IS!
+ ( LPAREN! BOX! RPAREN!
+ { Set (#t, FORMAL_DISCRETE_TYPE_DECLARATION); }
+ | RANGE! BOX!
+ { Set (#t, FORMAL_SIGNED_INTEGER_TYPE_DECLARATION); }
+ | MOD! BOX!
+ { Set (#t, FORMAL_MODULAR_TYPE_DECLARATION); }
+ | DELTA! BOX!
+ ( DIGITS! BOX!
+ { Set (#t, FORMAL_DECIMAL_FIXED_POINT_DECLARATION); }
+ | { Set (#t, FORMAL_ORDINARY_FIXED_POINT_DECLARATION); }
+ )
+ | DIGITS! BOX!
+ { Set (#t, FORMAL_FLOATING_POINT_DECLARATION); }
+ | array_type_definition[#t]
+ | access_type_definition[#t]
+ | empty_discrim_opt discriminable_type_definition[#t]
+ )
+ | discrim_part IS! discriminable_type_definition[#t]
+ )
+ { pop_def_id(); }
+ | w:WITH^ ( PROCEDURE! def_id[false] formal_part_opt subprogram_default_opt
+ { Set(#w, FORMAL_PROCEDURE_DECLARATION); }
+ | FUNCTION! def_designator[false] function_tail subprogram_default_opt
+ { Set(#w, FORMAL_FUNCTION_DECLARATION); }
+ | PACKAGE! def_id[false] IS! NEW! compound_name formal_package_actual_part_opt
+ { Set(#w, FORMAL_PACKAGE_DECLARATION); }
+ )
+ { pop_def_id(); }
+ | parameter_specification
+ )
+ SEMI!
+ ;
+
+discriminable_type_definition [RefAdaAST t]
+ : ( ( ABSTRACT )? NEW subtype_ind WITH ) =>
+ abstract_opt NEW! subtype_ind WITH! PRIVATE!
+ { Set (t, FORMAL_PRIVATE_EXTENSION_DECLARATION); }
+ | NEW! subtype_ind
+ { Set (t, FORMAL_ORDINARY_DERIVED_TYPE_DECLARATION); }
+ | abstract_tagged_limited_opt PRIVATE!
+ { Set (t, FORMAL_PRIVATE_TYPE_DECLARATION); }
+ ;
+
+subprogram_default_opt : ( IS! ( BOX | name ) )?
+ ;
+
+formal_package_actual_part_opt
+ : ( LPAREN! ( BOX | defining_identifier_list ) RPAREN! )?
+ ;
+
+subprog_decl_or_rename_or_inst_or_body [boolean lib_level]
+ { RefAdaAST t; }
+ : p:PROCEDURE^ def_id[lib_level]
+ ( generic_subp_inst
+ { Set(#p, GENERIC_PROCEDURE_INSTANTIATION); }
+ | formal_part_opt
+ ( renames { Set(#p, PROCEDURE_RENAMING_DECLARATION); }
+ | IS! ( separate_or_abstract[#p]
+ | body_part { Set(#p, PROCEDURE_BODY); }
+ )
+ | { pop_def_id();
+ Set(#p, PROCEDURE_DECLARATION); }
+ )
+ SEMI!
+ )
+ | f:FUNCTION^ def_designator[lib_level]
+ ( generic_subp_inst
+ { Set(#f, GENERIC_FUNCTION_INSTANTIATION); }
+ | function_tail
+ ( renames { Set(#f, FUNCTION_RENAMING_DECLARATION); }
+ | IS! ( separate_or_abstract[#f]
+ | body_part { Set(#f, FUNCTION_BODY); }
+ )
+ | { pop_def_id();
+ Set(#f, FUNCTION_DECLARATION); }
+ )
+ SEMI!
+ )
+ ;
+
+body_part : declarative_part block_body end_id_opt
+ ;
+
+declarative_part : ( pragma | declarative_item )*
+ { #declarative_part =
+ #(#[DECLARATIVE_PART, "DECLARATIVE_PART"],
+ #declarative_part); }
+ ;
+
+// A declarative_item may appear in the declarative part of any body.
+declarative_item :
+ ( pkg:PACKAGE^ ( body_is
+ ( separate { Set(#pkg, PACKAGE_BODY_STUB); }
+ | pkg_body_part
+ { Set(#pkg, PACKAGE_BODY); }
+ )
+ SEMI!
+ | def_id[false] spec_decl_part[#pkg]
+ )
+ | tsk:TASK^ ( body_is
+ ( separate { Set(#tsk, TASK_BODY_STUB); }
+ | body_part { Set(#tsk, TASK_BODY); }
+ )
+ SEMI!
+ | task_type_or_single_decl[#tsk]
+ )
+ | pro:PROTECTED^
+ ( body_is
+ ( separate { Set(#pro, PROTECTED_BODY_STUB); }
+ | prot_op_bodies_opt end_id_opt
+ { Set(#pro, PROTECTED_BODY); }
+ )
+ | prot_type_or_single_decl[#pro]
+ )
+ SEMI!
+ | subprog_decl_or_rename_or_inst_or_body[false]
+ | decl_common
+ )
+ /* DECLARATIVE_ITEM is just a pass-thru node so we omit it.
+ Objections anybody?
+ { #declarative_item =
+ #(#[DECLARATIVE_ITEM,
+ "DECLARATIVE_ITEM"], #declarative_item); }
+ */
+ ;
+
+body_is : BODY! def_id[false] IS!
+ ;
+
+separate : SEPARATE! { pop_def_id(); }
+ ;
+
+pkg_body_part : declarative_part block_body_opt end_id_opt
+ ;
+
+block_body_opt : ( BEGIN! handled_stmt_s )?
+ { #block_body_opt =
+ #(#[BLOCK_BODY_OPT,
+ "BLOCK_BODY_OPT"], #block_body_opt); }
+ ;
+
+prot_op_bodies_opt : ( entry_body
+ | subprog_decl_or_body
+ | pragma
+ )*
+ { #prot_op_bodies_opt =
+ #(#[PROT_OP_BODIES_OPT,
+ "PROT_OP_BODIES_OPT"], #prot_op_bodies_opt); }
+ ;
+
+subprog_decl_or_body
+ : p:PROCEDURE^ def_id[false] formal_part_opt
+ ( IS! body_part { Set(#p, PROCEDURE_BODY); }
+ | { pop_def_id(); Set(#p, PROCEDURE_DECLARATION); }
+ )
+ SEMI!
+ | f:FUNCTION^ def_designator[false] function_tail
+ ( IS! body_part { Set(#f, FUNCTION_BODY); }
+ | { pop_def_id(); Set(#f, FUNCTION_DECLARATION); }
+ )
+ SEMI!
+ ;
+
+block_body : b:BEGIN^ handled_stmt_s
+ { Set(#b, BLOCK_BODY); }
+ ;
+
+handled_stmt_s : statements except_handler_part_opt
+ { #handled_stmt_s =
+ #(#[HANDLED_SEQUENCE_OF_STATEMENTS,
+ "HANDLED_SEQUENCE_OF_STATEMENTS"], #handled_stmt_s); }
+ ;
+
+handled_stmts_opt : ( statements except_handler_part_opt )?
+ { #handled_stmts_opt =
+ #(#[HANDLED_STMTS_OPT,
+ "HANDLED_STMTS_OPT"], #handled_stmts_opt); }
+ ;
+
+statements : ( pragma | statement )+
+ { #statements = #(#[SEQUENCE_OF_STATEMENTS,
+ "SEQUENCE_OF_STATEMENTS"], #statements); }
+ ;
+
+statement : def_label_opt
+ ( null_stmt
+ | exit_stmt
+ | return_stmt
+ | goto_stmt
+ | delay_stmt
+ | abort_stmt
+ | raise_stmt
+ | requeue_stmt
+ | accept_stmt
+ | select_stmt
+ | if_stmt
+ | case_stmt
+ | loop_stmt SEMI!
+ | block END! SEMI!
+ | statement_identifier
+ ( loop_stmt id_opt SEMI!
+ | block end_id_opt SEMI!
+ )
+ | call_or_assignment
+ // | code_stmt // TBD: resolve ambiguity
+ )
+ { #statement = #(#[STATEMENT, "STATEMENT"], #statement); }
+ ;
+
+def_label_opt : ( LT_LT! IDENTIFIER GT_GT! )?
+ { #def_label_opt = #(#[LABEL_OPT, "LABEL_OPT"], #def_label_opt); }
+ ;
+
+null_stmt : s:NuLL SEMI!
+ { Set(#s, NULL_STATEMENT); }
+ ;
+
+if_stmt : s:IF^ cond_clause elsifs_opt
+ else_opt
+ END! IF! SEMI!
+ { Set(#s, IF_STATEMENT); }
+ ;
+
+cond_clause : condition c:THEN^ statements
+ { Set(#c, COND_CLAUSE); }
+ ;
+
+condition : expression
+ // { #condition = #(#[CONDITION, "CONDITION"], #condition); }
+ ;
+
+elsifs_opt : ( ELSIF! cond_clause )*
+ { #elsifs_opt = #(#[ELSIFS_OPT, "ELSIFS_OPT"], #elsifs_opt); }
+ ;
+
+else_opt : ( ELSE! statements )?
+ { #else_opt = #(#[ELSE_OPT, "ELSE_OPT"], #else_opt); }
+ ;
+
+case_stmt : s:CASE^ expression IS! alternative_s END! CASE! SEMI!
+ { Set(#s, CASE_STATEMENT); }
+ ;
+
+alternative_s : ( case_statement_alternative )+
+ ;
+
+case_statement_alternative : s:WHEN^ choice_s RIGHT_SHAFT! statements
+ { Set(#s, CASE_STATEMENT_ALTERNATIVE); }
+ ;
+
+loop_stmt : iteration_scheme_opt
+ l:LOOP^ statements END! LOOP! // basic_loop
+ { Set(#l, LOOP_STATEMENT); }
+ ;
+
+iteration_scheme_opt : ( WHILE^ condition
+ | FOR^ IDENTIFIER IN! reverse_opt discrete_subtype_definition
+ )?
+ { #iteration_scheme_opt =
+ #(#[ITERATION_SCHEME_OPT,
+ "ITERATION_SCHEME_OPT"], #iteration_scheme_opt); }
+ ;
+
+reverse_opt : ( REVERSE )?
+ { #reverse_opt = #(#[MODIFIERS, "MODIFIERS"], #reverse_opt); }
+ ;
+
+id_opt_aux { RefAdaAST endid; } :
+ endid=definable_operator_symbol { end_id_matches_def_id (endid) }?
+ | n:compound_name { end_id_matches_def_id (#n) }?
+ /* Ordinarily we would need to be stricter here, i.e.
+ match compound_name only for the library-level case
+ (and IDENTIFIER otherwise), but end_id_matches_def_id
+ does the right thing for us. */
+ | { pop_def_id(); }
+ ;
+
+id_opt : id_opt_aux
+ { #id_opt = #(#[ID_OPT, "ID_OPT"], #id_opt); }
+ ;
+
+end_id_opt : e:END^ id_opt_aux
+ { Set(#e, END_ID_OPT); }
+ ;
+
+/* Note: This rule should really be `statement_identifier_opt'.
+ However, manual disambiguation of `loop_stmt' from `block'
+ in the presence of the statement_identifier in `statement'
+ results in this rule. The case of loop_stmt/block given
+ without the statement_identifier is directly coded in
+ `statement'. */
+statement_identifier! : n:IDENTIFIER COLON!
+ { push_def_id(#n); }
+ ;
+
+/*
+statement_identifier_opt : ( n:IDENTIFIER COLON! { push_def_id(#n); } )?
+ { #statement_identifier_opt =
+ #(#[STATEMENT_IDENTIFIER_OPT,
+ "STATEMENT_IDENTIFIER_OPT"], #statement_identifier_opt); }
+ ;
+ */
+
+block : declare_opt block_body
+ { #block = #(#[BLOCK_STATEMENT, "BLOCK_STATEMENT"], #block); }
+ ;
+
+declare_opt : ( DECLARE! declarative_part )?
+ { #declare_opt = #(#[DECLARE_OPT, "DECLARE_OPT"], #declare_opt); }
+ ;
+
+exit_stmt : s:EXIT^ ( label_name )? ( WHEN condition )? SEMI!
+ { Set(#s, EXIT_STATEMENT); }
+ ;
+
+label_name : IDENTIFIER
+ ;
+
+return_stmt : s:RETURN^ ( expression )? SEMI!
+ { Set(#s, RETURN_STATEMENT); }
+ ;
+
+goto_stmt : s:GOTO^ label_name SEMI!
+ { Set(#s, GOTO_STATEMENT); }
+ ;
+
+call_or_assignment : // procedure_call is in here.
+ name ( ASSIGN! expression
+ { #call_or_assignment =
+ #(#[ASSIGNMENT_STATEMENT,
+ "ASSIGNMENT_STATEMENT"], #call_or_assignment); }
+ | { #call_or_assignment =
+ #(#[CALL_STATEMENT,
+ "CALL_STATEMENT"], #call_or_assignment); }
+ /* Preliminary. Use semantic analysis to produce
+ {PROCEDURE|ENTRY}_CALL_STATEMENT. */
+ )
+ SEMI!
+ ;
+
+entry_body : e:ENTRY^ def_id[false] entry_body_formal_part entry_barrier IS!
+ body_part SEMI!
+ { Set (#e, ENTRY_BODY); }
+ ;
+
+entry_body_formal_part : entry_index_spec_opt formal_part_opt
+ ;
+
+entry_index_spec_opt :
+ ( (LPAREN FOR) =>
+ LPAREN! FOR! def_id[false] IN! discrete_subtype_definition RPAREN!
+ | /* empty */
+ )
+ { #entry_index_spec_opt =
+ #(#[ENTRY_INDEX_SPECIFICATION,
+ "ENTRY_INDEX_SPECIFICATION"], #entry_index_spec_opt); }
+ ;
+
+entry_barrier : WHEN! condition
+ ;
+
+entry_call_stmt : name SEMI! // Semantic analysis required, for example
+ // to ensure `name' is an entry.
+ { #entry_call_stmt =
+ #(#[ENTRY_CALL_STATEMENT,
+ "ENTRY_CALL_STATEMENT"], #entry_call_stmt); }
+ ;
+
+accept_stmt : a:ACCEPT^ def_id[false] entry_index_opt formal_part_opt
+ ( DO! handled_stmts_opt end_id_opt SEMI!
+ | SEMI! { pop_def_id(); }
+ )
+ { Set (#a, ACCEPT_STATEMENT); }
+ ;
+
+entry_index_opt : ( (LPAREN expression RPAREN) => LPAREN! expression RPAREN!
+ // Looks alot like parenthesized_expr_opt, but it's not.
+ // We need the syn pred for the usage context in accept_stmt.
+ // The formal_part_opt that follows the entry_index_opt there
+ // creates ambiguity (due to the opening LPAREN.)
+ | /* empty */
+ )
+ { #entry_index_opt =
+ #(#[ENTRY_INDEX_OPT,
+ "ENTRY_INDEX_OPT"], #entry_index_opt); }
+ ;
+
+delay_stmt : d:DELAY^ until_opt expression SEMI!
+ { Set (#d, DELAY_STATEMENT); }
+ ;
+
+until_opt : ( UNTIL )?
+ { #until_opt = #(#[MODIFIERS, "MODIFIERS"], #until_opt); }
+ ;
+
+// SELECT_STATEMENT itself is not modeled since it is trivially
+// reconstructed:
+// select_statement ::= selective_accept | timed_entry_call
+// | conditional_entry_call | asynchronous_select
+//
+select_stmt : s:SELECT^
+ ( (triggering_alternative THEN ABORT) =>
+ triggering_alternative THEN! ABORT! abortable_part
+ { Set (#s, ASYNCHRONOUS_SELECT); }
+ | selective_accept
+ { Set (#s, SELECTIVE_ACCEPT); }
+ | entry_call_alternative
+ ( OR! delay_alternative { Set (#s, TIMED_ENTRY_CALL); }
+ | ELSE! statements { Set (#s, CONDITIONAL_ENTRY_CALL); }
+ )
+ )
+ END! SELECT! SEMI!
+ // { Set (#s, SELECT_STATEMENT); }
+ ;
+
+triggering_alternative : ( delay_stmt | entry_call_stmt ) stmts_opt
+ { #triggering_alternative =
+ #(#[TRIGGERING_ALTERNATIVE,
+ "TRIGGERING_ALTERNATIVE"], #triggering_alternative); }
+ ;
+
+abortable_part : stmts_opt
+ { #abortable_part =
+ #(#[ABORTABLE_PART,
+ "ABORTABLE_PART"], #abortable_part); }
+ ;
+
+entry_call_alternative : entry_call_stmt stmts_opt
+ { #entry_call_alternative =
+ #(#[ENTRY_CALL_ALTERNATIVE,
+ "ENTRY_CALL_ALTERNATIVE"], #entry_call_alternative); }
+ ;
+
+selective_accept : guard_opt select_alternative or_select_opt else_opt
+ ;
+
+guard_opt : ( w:WHEN^ condition RIGHT_SHAFT! ( pragma )* )?
+ { Set(#w, GUARD_OPT); }
+ ;
+
+select_alternative // Not modeled since it's just a pass-through.
+ : accept_alternative
+ | delay_alternative
+ | t:TERMINATE SEMI! { Set(#t, TERMINATE_ALTERNATIVE); }
+ ;
+
+accept_alternative : accept_stmt stmts_opt
+ { #accept_alternative =
+ #(#[ACCEPT_ALTERNATIVE,
+ "ACCEPT_ALTERNATIVE"], #accept_alternative); }
+ ;
+
+delay_alternative : delay_stmt stmts_opt
+ { #delay_alternative =
+ #(#[DELAY_ALTERNATIVE,
+ "DELAY_ALTERNATIVE"], #delay_alternative); }
+ ;
+
+stmts_opt : ( pragma | statement )*
+ ;
+
+or_select_opt : ( OR! guard_opt select_alternative )*
+ { #or_select_opt =
+ #(#[OR_SELECT_OPT, "OR_SELECT_OPT"], #or_select_opt); }
+ ;
+
+abort_stmt : a:ABORT^ name ( COMMA! name )* SEMI!
+ { Set (#a, ABORT_STATEMENT); }
+ ;
+
+except_handler_part_opt : ( EXCEPTION! ( exception_handler )+ )?
+ { #except_handler_part_opt =
+ #(#[EXCEPT_HANDLER_PART_OPT,
+ "EXCEPT_HANDLER_PART_OPT"], #except_handler_part_opt); }
+ ;
+
+exception_handler : w:WHEN^ identifier_colon_opt except_choice_s RIGHT_SHAFT!
+ statements
+ { Set (#w, EXCEPTION_HANDLER); }
+ ;
+
+identifier_colon_opt : ( IDENTIFIER COLON! )?
+ { #identifier_colon_opt =
+ #(#[IDENTIFIER_COLON_OPT,
+ "IDENTIFIER_COLON_OPT"], #identifier_colon_opt); }
+ ;
+
+except_choice_s : exception_choice ( PIPE^ exception_choice )*
+ ;
+
+exception_choice : compound_name
+ | OTHERS
+ ;
+
+raise_stmt : r:RAISE^ ( compound_name )? SEMI!
+ { Set (#r, RAISE_STATEMENT); }
+ ;
+
+requeue_stmt : r:REQUEUE^ name ( WITH! ABORT )? SEMI!
+ { Set (#r, REQUEUE_STATEMENT); }
+ ;
+
+operator_call : cs:CHAR_STRING^ operator_call_tail[#cs]
+ ;
+
+operator_call_tail [RefAdaAST opstr]
+ : LPAREN! { is_operator_symbol(opstr->getText().c_str()) }?
+ value_s RPAREN! { opstr->setType(OPERATOR_SYMBOL); }
+ ;
+
+value_s : value ( COMMA! value )*
+ { #value_s = #(#[VALUES, "VALUES"], #value_s); }
+ ;
+
+/*
+literal : NUMERIC_LIT
+ | CHARACTER_LITERAL
+ | CHAR_STRING
+ | NuLL
+ ;
+ */
+
+expression : relation
+ ( a:AND^ ( THEN! { Set (#a, AND_THEN); } )? relation
+ | o:OR^ ( ELSE! { Set (#o, OR_ELSE); } )? relation
+ | XOR^ relation
+ )*
+ ;
+
+relation : simple_expression
+ ( IN^ range_or_mark
+ | n:NOT^ IN! range_or_mark { Set (#n, NOT_IN); }
+ | EQ^ simple_expression
+ | NE^ simple_expression
+ | LT_^ simple_expression
+ | LE^ simple_expression
+ | GT^ simple_expression
+ | GE^ simple_expression
+ )?
+ ;
+
+range_or_mark : (range) => range
+ | subtype_mark
+ ;
+
+simple_expression : signed_term
+ ( PLUS^ signed_term
+ | MINUS^ signed_term
+ | CONCAT^ signed_term
+ )*
+ ;
+
+signed_term
+ : p:PLUS^ term { Set(#p, UNARY_PLUS); }
+ | m:MINUS^ term { Set(#m, UNARY_MINUS); }
+ | term
+ ;
+
+term : factor ( STAR^ factor
+ | DIV^ factor
+ | MOD^ factor
+ | REM^ factor
+ )*
+ ;
+
+factor : ( NOT^ primary
+ | ABS^ primary
+ | primary ( EXPON^ primary )?
+ )
+ ;
+
+primary : ( name_or_qualified
+ | parenthesized_primary
+ | allocator
+ | NuLL
+ | NUMERIC_LIT
+ | CHARACTER_LITERAL
+ | cs:CHAR_STRING^ ( operator_call_tail[#cs] )?
+ )
+ ;
+
+// Temporary, to be turned into just `qualified'.
+// We get away with it because `qualified' is always mentioned
+// together with `name'.
+// Only exception: `code_stmt', which is not yet implemented.
+name_or_qualified { RefAdaAST dummy; }
+ : IDENTIFIER
+ ( DOT^ ( ALL
+ | IDENTIFIER
+ | CHARACTER_LITERAL
+ | dummy=is_operator
+ )
+ | p:LPAREN^ value_s RPAREN!
+ { Set(#p, INDEXED_COMPONENT); }
+ | TIC^ ( parenthesized_primary | attribute_id )
+ )*
+ ;
+
+allocator : n:NEW^ name_or_qualified
+ { Set(#n, ALLOCATOR); }
+ ;
+
+subunit : sep:SEPARATE^ LPAREN! compound_name RPAREN!
+ { Set(#sep, SUBUNIT); }
+ ( subprogram_body
+ | package_body
+ | task_body
+ | protected_body
+ )
+ ;
+
+subprogram_body
+ : p:PROCEDURE^ def_id[false] formal_part_opt IS! body_part SEMI!
+ { pop_def_id(); Set(#p, PROCEDURE_BODY); }
+ | f:FUNCTION^ def_designator[false] function_tail IS! body_part SEMI!
+ { pop_def_id(); Set(#f, FUNCTION_BODY); }
+ ;
+
+package_body : p:PACKAGE^ body_is pkg_body_part SEMI!
+ { Set(#p, PACKAGE_BODY); }
+ ;
+
+task_body : t:TASK^ body_is body_part SEMI!
+ { Set(#t, TASK_BODY); }
+ ;
+
+protected_body : p:PROTECTED^ body_is prot_op_bodies_opt end_id_opt SEMI!
+ { Set(#p, PROTECTED_BODY); }
+ ;
+
+// TBD
+// code_stmt : qualified SEMI!
+// ;
+
+//----------------------------------------------------------------------------
+// The Ada scanner
+//----------------------------------------------------------------------------
+{
+#include "preambles.h"
+}
+class AdaLexer extends Lexer;
+
+options {
+ charVocabulary = '\3'..'\377';
+ exportVocab = Ada; // call the vocabulary "Ada"
+ testLiterals = false; // don't automatically test for literals
+ k = 4; // number of characters of lookahead
+ caseSensitive = false;
+ caseSensitiveLiterals = false;
+ ///defaultErrorHandler = true;
+}
+
+tokens {
+ // part 1: keywords
+ ABORT = "abort" ;
+ ABS = "abs" ;
+ ABSTRACT = "abstract" ;
+ ACCEPT = "accept" ;
+ ACCESS = "access" ;
+ ALIASED = "aliased" ;
+ ALL = "all" ;
+ AND = "and" ;
+ ARRAY = "array" ;
+ AT = "at" ;
+ BEGIN = "begin" ;
+ BODY = "body" ;
+ CASE = "case" ;
+ CONSTANT = "constant" ;
+ DECLARE = "declare" ;
+ DELAY = "delay" ;
+ DELTA = "delta" ;
+ DIGITS = "digits" ;
+ DO = "do" ;
+ ELSE = "else" ;
+ ELSIF = "elsif" ;
+ END = "end" ;
+ ENTRY = "entry" ;
+ EXCEPTION = "exception" ;
+ EXIT = "exit" ;
+ FOR = "for" ;
+ FUNCTION = "function" ;
+ GENERIC = "generic" ;
+ GOTO = "goto" ;
+ IF = "if" ;
+ IN = "in" ;
+ IS = "is" ;
+ LIMITED = "limited" ;
+ LOOP = "loop" ;
+ MOD = "mod" ;
+ NEW = "new" ;
+ NOT = "not" ;
+ NuLL = "null" ;
+ OF = "of" ;
+ OR = "or" ;
+ OTHERS = "others" ;
+ OUT = "out" ;
+ PACKAGE = "package" ;
+ PRAGMA = "pragma" ;
+ PRIVATE = "private" ;
+ PROCEDURE = "procedure" ;
+ PROTECTED = "protected" ;
+ RAISE = "raise" ;
+ RANGE = "range" ;
+ RECORD = "record" ;
+ REM = "rem" ;
+ RENAMES = "renames" ;
+ REQUEUE = "requeue" ;
+ RETURN = "return" ;
+ REVERSE = "reverse" ;
+ SELECT = "select" ;
+ SEPARATE = "separate" ;
+ SUBTYPE = "subtype" ;
+ TAGGED = "tagged" ;
+ TASK = "task" ;
+ TERMINATE = "terminate" ;
+ THEN = "then" ;
+ TYPE = "type" ;
+ UNTIL = "until" ;
+ USE = "use" ;
+ WHEN = "when" ;
+ WHILE = "while" ;
+ WITH = "with" ;
+ XOR = "xor" ;
+
+ // part 2: RM tokens (synthetic)
+ ABORTABLE_PART;
+ ABORT_STATEMENT;
+ /*ABSTRACT_SUBPROGRAM_DECLARATION; =>
+ ABSTRACT_{FUNCTION|PROCEDURE}_DECLARATION */
+ ACCEPT_ALTERNATIVE;
+ ACCEPT_STATEMENT;
+ /* ACCESS_TO_FUNCTION_DEFINITION => ACCESS_TO_FUNCTION_DECLARATION */
+ /* ACCESS_TO_OBJECT_DEFINITION => ACCESS_TO_OBJECT_DECLARATION */
+ /* ACCESS_TO_PROCEDURE_DEFINITION => ACCESS_TO_PROCEDURE_DECLARATION */
+ /* ACCESS_TYPE_DEFINITION => ACCESS_TYPE_DECLARATION */
+ ALLOCATOR;
+ /* ARRAY_TYPE_DEFINITION => ARRAY_TYPE_DECLARATION */
+ ASSIGNMENT_STATEMENT;
+ ASYNCHRONOUS_SELECT;
+ ATTRIBUTE_DEFINITION_CLAUSE;
+ AT_CLAUSE;
+ BLOCK_STATEMENT;
+ CASE_STATEMENT;
+ CASE_STATEMENT_ALTERNATIVE;
+ CODE_STATEMENT;
+ COMPONENT_DECLARATION;
+ // COMPONENT_LIST; // not currently used as an explicit node
+ // CONDITION; // not currently used
+ CONDITIONAL_ENTRY_CALL;
+ CONTEXT_CLAUSE;
+ /* DECIMAL_FIXED_POINT_DEFINITION => DECIMAL_FIXED_POINT_DECLARATION */
+ // DECLARATIVE_ITEM; // not currently used
+ DECLARATIVE_PART;
+ DEFINING_IDENTIFIER_LIST;
+ DELAY_ALTERNATIVE;
+ DELAY_STATEMENT;
+ DELTA_CONSTRAINT;
+ /* DERIVED_TYPE_DEFINITION; =>
+ DERIVED_RECORD_EXTENSION, ORDINARY_DERIVED_TYPE_DECLARATION */
+ DIGITS_CONSTRAINT;
+ // DISCRETE_RANGE; // Not used; instead, directly use its RHS alternatives.
+ DISCRIMINANT_ASSOCIATION;
+ DISCRIMINANT_CONSTRAINT;
+ DISCRIMINANT_SPECIFICATION;
+ ENTRY_BODY;
+ ENTRY_CALL_ALTERNATIVE;
+ ENTRY_CALL_STATEMENT;
+ ENTRY_DECLARATION;
+ ENTRY_INDEX_SPECIFICATION;
+ ENUMERATION_REPESENTATION_CLAUSE;
+ /* ENUMERATION_TYPE_DEFINITION => ENUMERATION_TYPE_DECLARATION */
+ EXCEPTION_DECLARATION;
+ EXCEPTION_HANDLER;
+ EXCEPTION_RENAMING_DECLARATION;
+ EXIT_STATEMENT;
+ /* FLOATING_POINT_DEFINITION => FLOATING_POINT_DECLARATION */
+ /* FORMAL_ACCESS_TYPE_DEFINITION => FORMAL_ACCESS_TYPE_DECLARATION */
+ /* FORMAL_ARRAY_TYPE_DEFINITION => FORMAL_ARRAY_TYPE_DECLARATION */
+ /* FORMAL_DECIMAL_FIXED_POINT_DEFINITION =>
+ FORMAL_DECIMAL_FIXED_POINT_DECLARATION */
+ /* FORMAL_DERIVED_TYPE_DEFINITION =>
+ FORMAL_{ORDINARY_DERIVED_TYPE|PRIVATE_EXTENSION}_DECLARATION */
+ /* FORMAL_DISCRETE_TYPE_DEFINITION => FORMAL_DISCRETE_TYPE_DECLARATION */
+ /* FORMAL_FLOATING_POINT_DEFINITION =>
+ FORMAL_FLOATING_POINT_DECLARATION */
+ /* FORMAL_MODULAR_TYPE_DEFINITION => FORMAL_MODULAR_TYPE_DECLARATION */
+ /* FORMAL_ORDINARY_FIXED_POINT_DEFINITION =>
+ FORMAL_ORDINARY_FIXED_POINT_DECLARATION */
+ FORMAL_PACKAGE_DECLARATION;
+ /* FORMAL_PRIVATE_TYPE_DEFINITION => FORMAL_PRIVATE_TYPE_DECLARATION */
+ /* FORMAL_SIGNED_INTEGER_TYPE_DEFINITION =>
+ FORMAL_SIGNED_INTEGER_TYPE_DECLARATION */
+ /* FORMAL_SUBPROGRAM_DECLARATION; =>
+ FORMAL_{FUNCTION|PROCEDURE}_DECLARATION */
+ /* FORMAL_TYPE_DECLARATION; not used, replaced by the corresponding
+ finer grained declarations */
+ /* FORMAL_TYPE_DEFINITION; not used at all; we use declarations
+ not definitions */
+ /* FULL_TYPE_DECLARATION; not used, replaced by the corresponding
+ finer grained declarations */
+ GENERIC_FORMAL_PART;
+ /* GENERIC_INSTANTIATION; =>
+ GENERIC_{FUNCTION|PACKAGE|PROCEDURE}_INSTANTIATION */
+ GENERIC_PACKAGE_DECLARATION;
+ /* GENERIC_RENAMING_DECLARATION; =>
+ GENERIC_{FUNCTION|PACKAGE|PROCEDURE}_RENAMING */
+ /* GENERIC_SUBPROGRAM_DECLARATION; =>
+ GENERIC_{FUNCTION|PROCEDURE}_DECLARATION */
+ GOTO_STATEMENT;
+ HANDLED_SEQUENCE_OF_STATEMENTS;
+ HANDLED_STMTS_OPT;
+ IF_STATEMENT;
+ INCOMPLETE_TYPE_DECLARATION;
+ INDEXED_COMPONENT;
+ INDEX_CONSTRAINT;
+ LIBRARY_ITEM;
+ LOOP_STATEMENT;
+ /* MODULAR_TYPE_DEFINITION => MODULAR_TYPE_DECLARATION */
+ NAME;
+ NULL_STATEMENT;
+ NUMBER_DECLARATION;
+ OBJECT_DECLARATION;
+ OBJECT_RENAMING_DECLARATION;
+ OPERATOR_SYMBOL;
+ /* ORDINARY_FIXED_POINT_DEFINITION => ORDINARY_FIXED_POINT_DECLARATION */
+ PACKAGE_BODY;
+ PACKAGE_BODY_STUB;
+ PACKAGE_RENAMING_DECLARATION;
+ PACKAGE_SPECIFICATION;
+ PARAMETER_SPECIFICATION;
+ // PREFIX; // not used
+ // PRIMARY; // not used
+ PRIVATE_EXTENSION_DECLARATION;
+ PRIVATE_TYPE_DECLARATION;
+ // PROCEDURE_CALL_STATEMENT; // NYI, using CALL_STATEMENT for now.
+ PROTECTED_BODY;
+ PROTECTED_BODY_STUB;
+ PROTECTED_TYPE_DECLARATION;
+ RAISE_STATEMENT;
+ RANGE_ATTRIBUTE_REFERENCE;
+ RECORD_REPRESENTATION_CLAUSE;
+ /* RECORD_TYPE_DEFINITION => RECORD_TYPE_DECLARATION */
+ REQUEUE_STATEMENT;
+ RETURN_STATEMENT;
+ SELECTIVE_ACCEPT;
+ /* SELECT_ALTERNATIVE; Not used - instead, we use the finer grained rules
+ ACCEPT_ALTERNATIVE | DELAY_ALTERNATIVE
+ | TERMINATE_ALTERNATIVE */
+ /* SELECT_STATEMENT; Not used - instead, we use the finer grained rules
+ SELECTIVE_ACCEPT | TIMED_ENTRY_CALL
+ | CONDITIONAL_ENTRY_CALL | ASYNCHRONOUS_SELECT */
+ SEQUENCE_OF_STATEMENTS;
+ /* SIGNED_INTEGER_TYPE_DEFINITION => SIGNED_INTEGER_TYPE_DECLARATION */
+ SINGLE_PROTECTED_DECLARATION;
+ SINGLE_TASK_DECLARATION;
+ STATEMENT;
+ /* SUBPROGRAM_BODY; => {FUNCTION|PROCEDURE}_BODY */
+ /* SUBPROGRAM_BODY_STUB; => {FUNCTION|PROCEDURE}_BODY_STUB */
+ /* SUBPROGRAM_DECLARATION; => {FUNCTION|PROCEDURE}_DECLARATION */
+ /* SUBPROGRAM_RENAMING_DECLARATION; =>
+ {FUNCTION|PROCEDURE}_RENAMING_DECLARATION */
+ SUBTYPE_DECLARATION;
+ SUBTYPE_INDICATION;
+ SUBTYPE_MARK;
+ SUBUNIT;
+ TASK_BODY;
+ TASK_BODY_STUB;
+ TASK_TYPE_DECLARATION;
+ TERMINATE_ALTERNATIVE;
+ TIMED_ENTRY_CALL;
+ TRIGGERING_ALTERNATIVE;
+ /* TYPE_DECLARATION; not used, replaced by the corresponding
+ finer grained declarations */
+ USE_CLAUSE;
+ USE_TYPE_CLAUSE;
+ VARIANT;
+ VARIANT_PART;
+ WITH_CLAUSE;
+
+ // part 3: Non-RM synthetic tokens.
+ // They exist mainly to normalize the node structure with respect to
+ // optional items. (Without them, the presence or absence of an optional
+ // item would change the node layout, but we want a fixed layout.)
+ ABSTRACT_FUNCTION_DECLARATION;
+ ABSTRACT_PROCEDURE_DECLARATION;
+ ACCESS_TO_FUNCTION_DECLARATION;
+ ACCESS_TO_OBJECT_DECLARATION;
+ ACCESS_TO_PROCEDURE_DECLARATION;
+ /* ACCESS_TYPE_DECLARATION; not used, replaced by
+ ACCESS_TO_{FUNCTION|OBJECT|PROCEDURE}_DECLARATION
+ */
+ ARRAY_OBJECT_DECLARATION;
+ ARRAY_TYPE_DECLARATION;
+ AND_THEN;
+ BASIC_DECLARATIVE_ITEMS_OPT;
+ BLOCK_BODY;
+ BLOCK_BODY_OPT;
+ CALL_STATEMENT; // See {PROCEDURE|ENTRY}_CALL_STATEMENT
+ COMPONENT_CLAUSES_OPT;
+ COMPONENT_ITEMS;
+ COND_CLAUSE;
+ DECIMAL_FIXED_POINT_DECLARATION;
+ DECLARE_OPT;
+ DERIVED_RECORD_EXTENSION;
+ // DERIVED_TYPE_DECLARATION; // not used
+ DISCRETE_SUBTYPE_DEF_OPT;
+ DISCRIMINANT_SPECIFICATIONS;
+ DISCRIM_PART_OPT;
+ ELSE_OPT;
+ ELSIFS_OPT;
+ END_ID_OPT;
+ ENTRY_INDEX_OPT;
+ ENUMERATION_TYPE_DECLARATION;
+ EXCEPT_HANDLER_PART_OPT;
+ EXTENSION_OPT;
+ FLOATING_POINT_DECLARATION;
+ /* FORMAL_ACCESS_TYPE_DECLARATION => ACCESS_TYPE_DECLARATION */
+ /* FORMAL_ARRAY_TYPE_DECLARATION => ARRAY_TYPE_DECLARATION */
+ FORMAL_DECIMAL_FIXED_POINT_DECLARATION;
+ FORMAL_DISCRETE_TYPE_DECLARATION;
+ FORMAL_FLOATING_POINT_DECLARATION;
+ FORMAL_FUNCTION_DECLARATION;
+ FORMAL_MODULAR_TYPE_DECLARATION;
+ FORMAL_ORDINARY_DERIVED_TYPE_DECLARATION;
+ FORMAL_ORDINARY_FIXED_POINT_DECLARATION;
+ FORMAL_PART_OPT;
+ FORMAL_PRIVATE_EXTENSION_DECLARATION;
+ FORMAL_PRIVATE_TYPE_DECLARATION;
+ FORMAL_PROCEDURE_DECLARATION;
+ FORMAL_SIGNED_INTEGER_TYPE_DECLARATION;
+ FUNCTION_BODY;
+ FUNCTION_BODY_STUB;
+ FUNCTION_DECLARATION;
+ FUNCTION_RENAMING_DECLARATION;
+ GENERIC_FUNCTION_DECLARATION;
+ GENERIC_FUNCTION_INSTANTIATION;
+ GENERIC_FUNCTION_RENAMING;
+ GENERIC_PACKAGE_INSTANTIATION;
+ GENERIC_PACKAGE_RENAMING;
+ GENERIC_PROCEDURE_DECLARATION;
+ GENERIC_PROCEDURE_INSTANTIATION;
+ GENERIC_PROCEDURE_RENAMING;
+ GUARD_OPT;
+ IDENTIFIER_COLON_OPT;
+ ID_OPT;
+ INIT_OPT;
+ ITERATION_SCHEME_OPT;
+ LABEL_OPT;
+ MARK_WITH_CONSTRAINT;
+ MODIFIERS; /* Possible values: abstract access aliased all constant in
+ limited out private protected reverse tagged */
+ MODULAR_TYPE_DECLARATION;
+ MOD_CLAUSE_OPT;
+ // NAME_OR_QUALIFIED;
+ NOT_IN;
+ ORDINARY_DERIVED_TYPE_DECLARATION;
+ ORDINARY_FIXED_POINT_DECLARATION;
+ OR_ELSE;
+ OR_SELECT_OPT;
+ PARENTHESIZED_PRIMARY;
+ // PARENTHESIZED_VALUES;
+ // PARENTHESIZED_VALUES_OPT;
+ PRIVATE_DECLARATIVE_ITEMS_OPT;
+ PRIVATE_TASK_ITEMS_OPT;
+ PROCEDURE_BODY;
+ PROCEDURE_BODY_STUB;
+ PROCEDURE_DECLARATION;
+ PROCEDURE_RENAMING_DECLARATION;
+ PROT_MEMBER_DECLARATIONS;
+ PROT_OP_BODIES_OPT;
+ PROT_OP_DECLARATIONS;
+ PROT_PRIVATE_OPT;
+ RANGED_EXPRS; // ugh, what an ugly name
+ RANGE_CONSTRAINT;
+ RECORD_TYPE_DECLARATION;
+ SELECTOR_NAMES_OPT;
+ SIGNED_INTEGER_TYPE_DECLARATION;
+ TASK_ITEMS_OPT;
+ UNARY_MINUS;
+ UNARY_PLUS;
+ VALUE;
+ VALUES;
+ VARIANTS;
+}
+
+{
+ ANTLR_LEXER_PREAMBLE
+ private:
+ bool lastTokenWasTicCompatible;
+}
+
+//----------------------------------------------------------------------------
+// OPERATORS
+//----------------------------------------------------------------------------
+COMMENT_INTRO : "--" {lastTokenWasTicCompatible=false;};
+DOT_DOT : ".." {lastTokenWasTicCompatible=false;};
+LT_LT : "<<" {lastTokenWasTicCompatible=false;};
+OX : "<>" {lastTokenWasTicCompatible=false;};
+GT_GT : ">>" {lastTokenWasTicCompatible=false;};
+ASSIGN : ":=" {lastTokenWasTicCompatible=false;};
+RIGHT_SHAFT : "=>" {lastTokenWasTicCompatible=false;};
+NE : "/=" {lastTokenWasTicCompatible=false;};
+LE : "<=" {lastTokenWasTicCompatible=false;};
+GE : ">=" {lastTokenWasTicCompatible=false;};
+EXPON : "**" {lastTokenWasTicCompatible=false;};
+PIPE : '|' {lastTokenWasTicCompatible=false;};
+CONCAT : '&' {lastTokenWasTicCompatible=false;};
+DOT : '.' {lastTokenWasTicCompatible=false;};
+EQ : '=' {lastTokenWasTicCompatible=false;};
+LT_ : '<' {lastTokenWasTicCompatible=false;};
+GT : '>' {lastTokenWasTicCompatible=false;};
+PLUS : '+' {lastTokenWasTicCompatible=false;};
+MINUS : '-' {lastTokenWasTicCompatible=false;};
+STAR : '*' {lastTokenWasTicCompatible=false;};
+DIV : '/' {lastTokenWasTicCompatible=false;};
+LPAREN : '(' {lastTokenWasTicCompatible=false;};
+RPAREN : ')' {lastTokenWasTicCompatible=true;};
+COLON : ':' {lastTokenWasTicCompatible=false;};
+COMMA : ',' {lastTokenWasTicCompatible=false;};
+SEMI : ';' {lastTokenWasTicCompatible=false;};
+
+
+// Literals.
+
+// Rule for IDENTIFIER: testLiterals is set to true. This means that
+// after we match the rule, we look in the literals table to see if
+// it's a keyword or really an identifier.
+IDENTIFIER
+ options {testLiterals=true;}
+ : ( 'a'..'z' ) ( ('_')? ( 'a'..'z'|'0'..'9' ) )*
+ ;
+
+TIC_OR_CHARACTER_LITERAL :
+ "'"! { $setType(TIC); } (
+ { ! lastTokenWasTicCompatible }? . "'"!
+ { $setType(CHARACTER_LITERAL); }
+ )?
+ {lastTokenWasTicCompatible=false;};
+
+CHAR_STRING : '"'! ("\"\"" | ~('"'))* '"'!
+ {lastTokenWasTicCompatible=true;};
+
+NUMERIC_LIT : ( DIGIT )+
+ ( '#' BASED_INTEGER ( '.' BASED_INTEGER )? '#'
+ | ( '_' ( DIGIT )+ )+ // INTEGER
+ )?
+ ( { LA(2)!='.' }? //&& LA(3)!='.' }?
+ ( '.' ( DIGIT )+ ( '_' ( DIGIT )+ )* ( EXPONENT )?
+ | EXPONENT
+ )
+ )?
+ {lastTokenWasTicCompatible=false;};
+
+// a couple protected methods to assist in matching the various numbers
+
+protected
+DIGIT : ( '0'..'9' ) {lastTokenWasTicCompatible=false;};
+
+protected
+EXPONENT : ('e') ('+'|'-')? ( DIGIT )+ {lastTokenWasTicCompatible=false;};
+
+protected
+EXTENDED_DIGIT : ( DIGIT | 'a'..'f' ) {lastTokenWasTicCompatible=false;};
+
+protected
+BASED_INTEGER : ( EXTENDED_DIGIT ) ( ('_')? EXTENDED_DIGIT )* {lastTokenWasTicCompatible=false;};
+
+
+// Whitespace -- ignored
+WS_ : ( ' '
+ | '\t'
+ | '\f'
+ // handle newlines
+ | ( "\r\n" // Evil DOS
+ | '\r' // Macintosh
+ | '\n' // Unix (the right way)
+ )
+ { newline(); }
+ )
+ { $setType(antlr::Token::SKIP); }
+ ;
+
+// Single-line comments
+COMMENT : COMMENT_INTRO (~('\n'|'\r'))* ('\n'|'\r'('\n')?)
+ { $setType(antlr::Token::SKIP);
+ newline();
+ lastTokenWasTicCompatible=false; }
+ ;
+