/* * Ada95 Grammar for ANTLR, target language C++ * * Copyright (C) 2003 Oliver M. Kellogg * Modifications (C) 2005 Daniel Zuberbuehler * * 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 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; } ;