/******************************************************************************
 *
 * Copyright (C) 2014 by M. Kreis
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation under the terms of the GNU General Public License is hereby
 * granted. No representations are made about the suitability of this software
 * for any purpose. It is provided "as is" without express or implied warranty.
 * See the GNU General Public License for more details.
 *
 */
options {
  JAVA_UNICODE_ESCAPE = true;
  OUTPUT_LANGUAGE = "c++";
  NAMESPACE = "vhdl::parser";
  STATIC=false;
  PARSER_INCLUDE="vhdljjparser.h";
  TOKEN_MANAGER_INCLUDE="vhdlstring.h";
 // TOKEN_MANAGER_USES_PARSER = true;
  TOKEN_MANAGER_SUPER_CLASS = "TokenParser";
 // DEBUG_PARSER  = true;
 //OUTPUT_DIRECTORY = ".";
 //DEBUG_PARSER=true;
 //DEBUG_LOOKAHEAD=true;

  }

PARSER_BEGIN(VhdlParser)


struct SharedState
{
  std::shared_ptr<Entry> current_root;
  std::shared_ptr<Entry> tempEntry;
  std::shared_ptr<Entry> lastEntity;
  std::shared_ptr<Entry> lastCompound;
  std::shared_ptr<Entry> current;
  QCString compSpec;
  QCString currName;
  int levelCounter = 0;
  QCString confName;
  QCString genLabels;
  QCString lab;
  VhdlSection param_sec = VhdlSection::UNKNOWN;
  VhdlSection parse_sec = VhdlSection::UNKNOWN;
  VhdlSpecifier currP = VhdlSpecifier::UNKNOWN;
  bool interf_sec;
  bool generic_sec;
};

VHDLOutlineParser *m_outlineParser;
SharedState *m_sharedState;

void setOutlineParser(VHDLOutlineParser* p) { m_outlineParser=p; }
VHDLOutlineParser *outlineParser() const { return m_outlineParser; }
void setSharedState(SharedState *s) { m_sharedState=s; }
void clearError() { hasError = false; }

bool checkListTok()
{
    return  (getToken(1)->kind==SEMI_T) && (getToken(2)->kind==RPAREN_T);
}

bool checkNextTok(int kind)
{
    return  getToken(1)->kind==kind;
}

Token* _getPrevTok()
{
    return getToken(0);
}

PARSER_END(VhdlParser)

SKIP :
{
  " "
| "\t"
| "\n" {parser->outlineParser()->lineCount();}
| "\r"
}

SKIP:
{
  // VHDL comment -- ......
  // VHDL doxygen line comment --! ....
  <#DOXYGEN_VHDL_COMMENT: (" "|"\t")*"--!"(~["\n", "\r"])* ("\n" | "\r" | "\r\n")?>
  | <MULT_DOXYGEN_COMMENT: (<DOXYGEN_VHDL_COMMENT>)+ >
  {
    {
    QCString doc = image;
     int count=doc.contains("--!");
     parser->outlineParser()->setMultCommentLine();
    parser->outlineParser()->lineCount(image);
    if (count == 1)
      parser->outlineParser()->oneLineComment(doc);
    else
      parser->outlineParser()->handleCommentBlock(QCString(image),FALSE); ;
    }

  }
  |<VHDL_FLOWCHART_COMMENT: "--#" (~["\n", "\r"])* ("\n" | "\r" | "\r\n")?>  { parser->outlineParser()->handleFlowComment(image);}
  |<VHDL_COMMENT: "--" (~["\n", "\r"])* ("\n" | "\r" | "\r\n")?>
  {
    parser->outlineParser()->lineCount(image);}
  }

// VHDL 2008  comment /* .... */
// VHDL 2008 doxygen comment /*! .... */
SKIP :
{
  <MULT_DOXYGEN_VHDL_COMMENT_2008 : "/*!" (~["*"])* "*" ("*" | ~["*","/"] (~["*"])* "*")* "/">
  {
   {
     QCString q = filter2008VhdlComment(image);
     parser->outlineParser()->lineCount(image);
     parser->outlineParser()->handleCommentBlock(QCString(q),TRUE);image.clear();
   }
  }
  | <MULT_VHDL_2008_COMMENT : "/*" (~["*"])* "*" ("*" | ~["*","/"] (~["*"])* "*")* "/">
    {
      parser->outlineParser()->lineCount(image);image.clear();}
    }

/* KEYWORDS */

TOKEN [IGNORE_CASE] :
{
 <ABS_T: "abs">
| <ACCESS_T: "access">
| <AFTER_T: "after">
| <ALIAS_T: "alias"> {parser->outlineParser()->setLineParsed(ALIAS_T);}
| <ALL_T: "all">
| <AND_T: "and">
| <ARCHITECTURE_T: "architecture"> {parser->outlineParser()->setLineParsed(ARCHITECTURE_T);}
| <ARRAY_T: "array"> {parser->outlineParser()->setLineParsed(ARRAY_T);}
| <ASSERT_T: "assert">
| <ASSUME_T: "assume">
| <ASSUME_GUARANTEE_T: "assume_guarantee">
| <ATTRIBUTE_T: "attribute"> {parser->outlineParser()->setLineParsed(ATTRIBUTE_T);}
| <BEGIN_T: "begin">
| <BLOCK_T: "block">
| <BODY_T: "body"> {parser->outlineParser()->setLineParsed(BODY_T);}
| <BUFFER_T: "buffer">
| <BUS_T: "bus">
| <COMPONENT_T: "component"> {parser->outlineParser()->setLineParsed(COMPONENT_T);}
| <CASE_T: "case">
| <CONFIGURATION_T: "configuration"> {parser->outlineParser()->setLineParsed(CONFIGURATION_T);}
| <CONSTANT_T: "constant">  {parser->outlineParser()->setLineParsed(CONSTANT_T);}
| <CONTEXT_T: "context"> {parser->outlineParser()->setLineParsed(CONTEXT_T);}
| <COVER_T: "cover">
| <DEFAULT_T: "default">
| <DISCONNECT_T: "disconnect">
| <DOWNTO_T: "downto">
| <ELSE_T: "else">
| <ELSIF_T: "elsif">
| <END_T: "end"> {parser->outlineParser()->setLineParsed(END_T);}
| <ENTITY_T: "entity"> {parser->outlineParser()->setLineParsed(ENTITY_T);}
| <EXIT_T: "exit">
| <FAIRNESS_T: "fairness">
| <FILE_T: "file"> {parser->outlineParser()->setLineParsed(FILE_T);}
| <FOR_T: "for">
| <FORCE_T: "force">
| <FUNCTION_T: "function">  {parser->outlineParser()->setLineParsed(FUNCTION_T);}
| <GENERATE_T: "generate">
| <GENERIC_T: "generic">
| <GROUP_T: "group"> {parser->outlineParser()->setLineParsed(GROUP_T);}
| <GUARDED_T: "guarded">
| <IF_T: "if">
| <IMPURE_T: "impure">
| <IN_T: "in">
| <INERTIAL_T: "inertial">
| <INOUT_T: "inout">
| <IS_T: "is">
| <LABEL_T: "label">
| <LIBRARY_T: "library"> {parser->outlineParser()->setLineParsed(LIBRARY_T);}
| <LINKAGE_T: "linkage">
| <LITERAL_T: "literal">
| <LOOP_T: "loop">
| <MAP_T: "map">
| <MOD_T: "mod">
//| <MODE_T: "mode">
| <NAND_T: "nand">
| <NEW_T: "new">
| <NEXT_T: "next">
| <NOR_T: "nor">
| <NOT_T: "not">
| <NULL_T: "null">
| <OF_T: "of">
| <ON_T: "on">
| <OPEN_T: "open">
| <OR_T: "or">
| <OTHER_T: "others">
| <OUT_T: "out">
| <PACKAGE_T: "package"> {parser->outlineParser()->setLineParsed(PACKAGE_T);}
| <PARAMETER_T: "parameter">
| <PORT_T: "port"> {parser->outlineParser()->setLineParsed(PORT_T);}
| <POSTPONED_T: "postponed">
| <PRIVATE_T: "private">
| <PROCEDURE_T: "procedure"> {parser->outlineParser()->setLineParsed(PROCEDURE_T);}
| <PROCESS_T: "process"> {parser->outlineParser()->setLineParsed(PROCESS_T);}
| <PROPERTY_T: "property">
| <PROTECTED_T: "protected">
| <PURE_T: "pure">
| <RANGE_T: "range">
| <RECORD_T: "record"> {parser->outlineParser()->setLineParsed(RECORD_T);}
| <REGISTER_T: "register">
| <REJECT_T: "reject">
| <RELEASE_T: "release">
| <RESTRICT_T: "restrict">
| <RESTRICT_GUARANTEE_T: "restrict_guarantee">
| <REM_T: "rem">
| <REPORT_T: "report">
| <ROL_T: "rol">
| <ROR_T: "ror">
| <RETURN_T: "return">
| <SELECT_T: "select">
| <SEQUENCE_T: "sequence">
| <SEVERITY_T: "severity">
| <SIGNAL_T: "signal"> {parser->outlineParser()->setLineParsed(SIGNAL_T);}
| <SHARED_T: "shared">
| <SLA_T: "sla">
| <SLL_T: "sll">
| <SRA_T: "sra">
| <SRL_T: "srl">
| <STRONG_T: "strong">
| <SUBTYPE_T: "subtype"> {parser->outlineParser()->setLineParsed(SUBTYPE_T);}
| <THEN_T: "then">
| <TO_T: "to">
| <TRANSPORT_T: "transport">
| <TYPE_T: "type"> {parser->outlineParser()->setLineParsed(TYPE_T);}
| <UNAFFECTED_T: "unaffected">
| <UNITS_T: "units"> {parser->outlineParser()->setLineParsed(UNITS_T);}
| <UNTIL_T: "until">
| <USE_T: "use">
| <VARIABLE_T: "variable">
| <VIEW_T: "view" >
| <VMODE_T: "vmode">
| <VPROP_T: "vprop">
| <VUNIT_T: "vunit">
| <WAIT_T: "wait">
| <WHEN_T: "when">
| <WHILE_T: "while">
| <WITH_T: "with">
| <XOR_T: "xor">
| <XNOR_T: "xnor">
}

/* OPERATORS */

TOKEN :
{
  < AMPERSAND_T: "&" >
| < APOSTROPHE_T: "'" >
| < LPAREN_T: "(" >
| < RPAREN_T: ")" >
| < DOUBLEMULT_T: "**" >
| < MULT_T: "*" >
| < PLUS_T: "+" >
| < MINUS_T: "-" >
| < COMMA_T: "," >
| < VARASSIGN_T: ":=" >
| < COLON_T: ":" >
| < SEMI_T: ";" >{parser->outlineParser()->setLineParsed(SEMI_T);}
| < LGT_T:   "<=>" >
| < LESSTHAN_T: "<=" >
| < GREATERTHAN_T: ">=" >
| < LT_T: "<" >
| < GT_T: ">" >
| < EQU_T: "=" >
| < NOTEQU_T: "/=" >
| < ARROW_T: "=>" >
| < BOX_T: "<>" >
| < SLSL_T: "<<" >
| < RSRS_T: ">>" >
| < QQ_T: "??" >
| < QGT_T: "?>=" >
| < QLT_T: "?<=" >
| < QG_T: "?>" >
| < QL_T: "?<" >
| < QEQU_T: "?=" >
| < QNEQU_T: "?/=" >
| < Q_T: "?" >
| < BAR_T: "|" >
| <DOT_T: "." >
| < SLASH_T: "/" >
| < AT_T: "@" >
| < NEG_T: "^" >
| < LBRACKET_T: "[" >
| < RBRACKET_T: "]" >
| < LBRACE: "{" >
| < RBRACE: "}" >

}

TOKEN:
{
  <INTEGER: <DIGIT> ((["_"])? (<DIGIT>))* >
 | <STRINGLITERAL: (( ["\""](<GRAPHIC_CHARACTER>)*) "\"")+ >
 | <BASIC_IDENTIFIER:  (<LETTER> ( (["_"])* <LETTER_OR_DIGIT> )*) >
 | <EXTENDED_CHARACTER: ( ["\\"](<GRAPHIC_CHARACTER>)*["\\"] ) >
 | <CHARACTER_LITERAL: (["'"](<GRAPHIC_CHARACTER>|<QUOTE>)["'"]) >
 | <DECIMAL_LITERAL: (<INTEGER> (["."]<INTEGER>)? (<EXPONENT>)? ) >
 | <BASED_INTEGER: <LETTER_OR_DIGIT>( <LETTER_OR_DIGIT>)* >
 | <BASED_LITERAL: <INTEGER>["#"]<BASED_INTEGER>(["."] <BASED_INTEGER>)? ["#"] (<EXPONENT>)? >
 | <#EXPONENT: (["e","E"] (["+","-"])? (<INTEGER>)+) >
 | < #BASIC_GRAPHIC_CHARACTER:    (<UPPER_CASE_LETTER>|<DIGIT>|<SPECIAL_CHARACTER>|<SPACE_CHARACTER>) >
 | < #GRAPHIC_CHARACTER: ( <BASIC_GRAPHIC_CHARACTER>|<LOWER_CASE_LETTER>|<OTHER_SPECIAL_CHARACTER> ) >
 | < LETTER_OR_DIGIT: ( <LETTER> | <DIGIT> ) >
 | < #LETTER_OR_DIGIT_OR_STD: (<LETTER_OR_DIGIT> | <STD_LOGIC> ) >
 | < #LETTER: (<UPPER_CASE_LETTER>|<LOWER_CASE_LETTER>) >
 | < #UPPER_CASE_LETTER: ["A"-"Z"]  >
 | <BIT_STRING_LITERAL : (<DIGIT>)*<BASE_SPECIFIER>["\""](<LETTER_OR_DIGIT_OR_STD>((["_"])*<LETTER_OR_DIGIT_OR_STD>)*)["\""] >
 | <#BASE_SPECIFIER: (<DIGIT>)*(["S","U"])*["B","O","X","b","o","x","d","D"] >
 | <#STD_LOGIC:["0","1","L","H","X","Z","W","-","l","h","x","z","w"]>
 | < #DIGIT: ["0"-"9"] >
 | < #SPECIAL_CHARACTER: ["#","&","'","(",")","*","+",",","-",".","/",":",";","<","=",">","_","|"] >
 | < #OTHER_SPECIAL_CHARACTER: ["%","!","$","@","?","[","\\","]","^","`","{","}","~","\u00A0"-"\u00FF"]>
 | < #SPACE_CHARACTER: [" ","\t"] >
 | < #LOWER_CASE_LETTER: ["a"-"z"] >
 | < #QUOTE: ["\""] >
 | <VHDL2008TOOLDIR  : ["`"](<GRAPHIC_CHARACTER>|<STRINGLITERAL>)+ >

}

QCString absolute_pathname(): {QCString s,s1;}
{
 LOOKAHEAD(<DOT_T>  pathname_element_list())
 <DOT_T>  s=pathname_element_list() s1=identifier() { return "."+s+s1;}
| <DOT_T>  s=identifier (){ return "."+s;}
}


QCString abstract_literal() :
{Token *tok;}
{
   tok=<DECIMAL_LITERAL> { return QCString(tok->image); }
 | tok=<INTEGER>         { return QCString(tok->image); }
 | tok=<BASED_LITERAL>   { return QCString(tok->image); }
}

QCString access_type_definition() :
{Token *tok=nullptr;QCString str,str1;}
{
  tok=<ACCESS_T> str1=subtype_indication() { str=tok->image; return str+str1; }
}

QCString access_incomplete_type_definition() :
{Token *tok=nullptr;QCString str,str1;}
{
  tok=<ACCESS_T> str1=incomplete_subtype_indication() { str=tok->image; return str+" "+str1; }
}

QCString actual_designator() :
{QCString str,s;Token *t=nullptr;}
{
t=<OPEN_T> { return QCString(t->image); }
|
LOOKAHEAD([ <INERTIAL_T> ] expression()) [ t=<INERTIAL_T> {s=QCString(t->image)+" ";}] str=expression() {  return s+str; }
|
 LOOKAHEAD(5) str=subtype_indication() {return str;}
|
 str=identifier(){return str;}
}


QCString actual_parameter_part() :
{QCString s;}
{
   s=association_list() { return s;}
}




QCString actual_part() :
{QCString s,s1;}
{
 LOOKAHEAD(actual_designator())
 s=actual_designator() { return s;}
 |
   <BOX_T> { return "<>";}
 |
 LOOKAHEAD(name() <LPAREN_T>)
 s=name() <LPAREN_T> s1=actual_designator() <RPAREN_T> {s+="(";s+=s1+")";return s;}

 }

QCString adding_operator () :
{}
{
  <PLUS_T> { return "+";}
  | <MINUS_T> { return "-";}
  |<AMPERSAND_T> { return "&";}
}

QCString aggregate() :  {QCString s,s1,s2;}
{
  <LPAREN_T> s=element_association() (<COMMA_T> s1=element_association(){s+=","+s1;})* <RPAREN_T> { return QCString("("+s+")");}
}

QCString alias_declaration() :  {QCString s,s1,s2;}
{
 <ALIAS_T> s2=alias_designator()
 [ <COLON_T>{ s+=":"; } s1=subtype_indication() { s+=s1; }]
 <IS_T> { s+=" is "; } s1=name() {s+=s1;} [s1=signature() {s+=s1;}]
 <SEMI_T>
{
 outlineParser()->addVhdlType(s2,outlineParser()->getLine(ALIAS_T),
      EntryType::makeVariable(),VhdlSpecifier::ALIAS,QCString(),s,Protection::Public);

 return s2+" "+s+";";
}
 }

QCString alias_designator()  : {Token *tok=nullptr;QCString s;}
{
 s=identifier() { return s;}
 | tok=<CHARACTER_LITERAL> { return QCString(tok->image); }
 | s=operator_symbol() { return s; }
}

void allocator()  :{}
{
  LOOKAHEAD(3)
     <NEW_T> qualified_expression()
  |  <NEW_T> subtype_indication()
}

void architecture_body() : {QCString s,s1;}
{

  <ARCHITECTURE_T> s=identifier() <OF_T> s1=name() <IS_T>
  {
    QCString t=s1+"::"+s;
    m_sharedState->genLabels.clear();
    outlineParser()->pushLabel(m_sharedState->genLabels,s1);
    m_sharedState->lastCompound=m_sharedState->current;
    outlineParser()->addVhdlType(t,outlineParser()->getLine(ARCHITECTURE_T),
                                 EntryType::makeClass(),VhdlSpecifier::ARCHITECTURE,QCString(),QCString(),Protection::Private);
  }
  try
  {
    architecture_declarative_part()
  }
  catch(...)
  {
    outlineParser()->error_skipto(BEGIN_T);
  }
  <BEGIN_T>
  architecture_statement_part()
  <END_T> [<ARCHITECTURE_T>] [name()] <SEMI_T>
  { m_sharedState->lastEntity=nullptr;m_sharedState->lastCompound=nullptr; m_sharedState->genLabels.clear(); }
}

void anonymous_type_indication() : {}
{
 <TYPE_T> <IS_T> incomplete_type_definition()
}

void architecture_declarative_part() : {}
{
  (block_declarative_item() )*
 // | (<VHDL2008TOOLDIR>)
}

void architecture_statement_part() :  {}
{
  (concurrent_statement())*
 // | (<VHDL2008TOOLDIR>)
}

void array_constraint() :  {}
{
  LOOKAHEAD(2) "(" <OPEN_T> ")" [ array_element_constraint() ]
  | index_constraint() [ array_element_constraint() ]
}

void array_element_constraint() :  {}
{
  element_constraint()
}

void array_element_resolution() :  {}
{
  resolution_indication()
}

void array_incomplete_type_definition() :  {}
{
  <ARRAY_T> <LPAREN_T> array_index_incomplete_type_list() <RPAREN_T>  <OF_T> incomplete_subtype_indication()
}

void array_index_incomplete_type() :  {}
{
 index_constraint()
 | index_subtype_definition()
 | anonymous_type_indication()
}


void array_index_incomplete_type_list() :  {}
{
 array_index_incomplete_type() (<COMMA_T> array_index_incomplete_type())*
}


QCString array_mode_view_indication ():  { QCString s;}
{

<VIEW_T>  <LPAREN_T> identifier() <RPAREN_T> <OF_T> subtype_indication() { return "";}

}

QCString array_type_definition ():  { QCString s;}
{

 LOOKAHEAD(<ARRAY_T> index_constraint() <OF_T>)
  s=constraint_array_definition()  {return s;}
  |
   s=unconstraint_array_definition() {return s;}
  
}

QCString assertion() :  {QCString s,s1,s2;Token *t=nullptr;Token *t1=nullptr;}
{
   <ASSERT_T> s=condition() [ t=<REPORT_T> s1=expression() ] [t1=<SEVERITY_T> s2=expression()]
 {
   s.prepend("assert ");
   if(t!=nullptr) s1.prepend(" report ");
   if(t1!=nullptr) s2.prepend(" report ");
    return s+s1+s2;
 }
}

QCString assertion_statement() :  {QCString s,s1,s2;Token *t=nullptr;}
{
  [ s=label() t=<COLON_T> ] s1=assertion() <SEMI_T>
  {
    if(t!=nullptr) s+=":";
    return s+s1+";";
  }
}
QCString association_element() : {QCString s,s1;}
{
 [LOOKAHEAD(formal_part() <ARROW_T>) s=formal_part() <ARROW_T> ] s1=actual_part()
 { return s+" => "+s1;}
}

QCString association_list ():  {QCString s,s1;}
{
s=association_element() (<COMMA_T> s1=association_element() { s+=","+s1; })* { return s; }
}

QCString attribute_declaration() : {QCString s,s1;}
{
 <ATTRIBUTE_T> s=identifier() <COLON_T> s1=type_mark() <SEMI_T>
  {
    outlineParser()->addVhdlType(s,outlineParser()->getLine(ATTRIBUTE_T),
                                 EntryType::makeVariable(),VhdlSpecifier::ATTRIBUTE,QCString(),s1,Protection::Public);
    return " attribute "+s+":"+s1+";";
  }
 }

QCString attribute_designator (): {QCString s;Token *tok=nullptr;}
{
  s=identifier() { return s;}
  | tok=<RANGE_T> { return QCString(tok->image); }
}


QCString attribute_name (): {QCString s,s1;}
{
  s=identifier() <APOSTROPHE_T> (<RANGE_T> | s1=name()) { s+=s1; }[LOOKAHEAD(1)<LPAREN_T>s1=expression() <RPAREN_T> {s+=s1;}] { return s; }
 }

QCString attribute_specification():  {QCString s,s1,s2;}
{
  <ATTRIBUTE_T> s=attribute_designator() <OF_T> s1=entity_specification() <IS_T> s2=conditional_expression() <SEMI_T>
  {
   QCString t= s1+" is "+s2;
   outlineParser()->addVhdlType(s,outlineParser()->getLine(ATTRIBUTE_T),
                                EntryType::makeVariable(),VhdlSpecifier::ATTRIBUTE,QCString(),t,Protection::Public);
   return " attribute "+s+" of "+s1+ " is "+s2+";";
  }
}

QCString base() :  {Token *tok=nullptr;}
{
  tok=<INTEGER> { return QCString(tok->image);}
}

QCString base_specifier ():  {Token *tok=nullptr;}
{
   tok=<BASIC_IDENTIFIER> { return QCString(tok->image);}
}

QCString base_unit_declaration() :
{QCString s;}
{
  s=identifier() { return s; }
}

QCString based_integer() :  {Token *tok=nullptr;}
{
  tok=<BASIC_IDENTIFIER> { return QCString(tok->image);}
}

QCString based_literal():  {Token *tok=nullptr;}
{
 tok=<BASED_LITERAL> { return QCString(tok->image);}
}

QCString basic_identifier() :  {Token *tok=nullptr;}
{
  tok=<BASIC_IDENTIFIER> { return QCString(tok->image);}
}

void binding_indication() :  {}
{
 [ <USE_T> entity_aspect() ]
 [ generic_map_aspect() ]
 [ port_map_aspect() ]
}

QCString bit_string_literal ():  {Token *tok=nullptr;}
{
  tok=<BIT_STRING_LITERAL> { return QCString(tok->image);}
}


QCString bit_value() :  {Token *tok=nullptr;}
{
  tok=<BASIC_IDENTIFIER> { return QCString(tok->image);}
}

void block_configuration() : {}
{
    <FOR_T> block_specification()
        ( use_clause() )*
        ( configuration_item())*
    <END_T> <FOR_T> <SEMI_T>
}

void block_declarative_item ():  {}
{
  subprogram_declaration()
| type_declaration()
| subtype_declaration()
| mode_view_declaration()
| constant_declaration()
| signal_declaration()
| variable_declaration()
| file_declaration()
| alias_declaration()
| LOOKAHEAD(2) package_body()
| LOOKAHEAD(package_declaration())package_declaration()
| package_instantiation_declaration()
| component_declaration()
|
LOOKAHEAD(attribute_declaration())
attribute_declaration()
| attribute_specification()
| configuration_specification()
| disconnection_specification ()
| use_clause()
|
LOOKAHEAD(3)
group_template_declaration()
| group_declaration()
//| <VHDL2008TOOLDIR>
}

void block_declarative_part() : {}
{
   (block_declarative_item() )*
}

void block_header() : {}
{
[LOOKAHEAD(generic_clause()) generic_clause()[ generic_map_aspect() <SEMI_T> ] ]
[ port_clause() [ port_map_aspect() <SEMI_T> ] ]
}

void block_specification() :  {}
{
  name() [ <LPAREN_T> index_specification() <RPAREN_T> ]
}

void block_statement() :  {QCString s;}
{
  s=identifier() <COLON_T>
        <BLOCK_T> { outlineParser()->pushLabel(m_sharedState->genLabels,s); }[ <LPAREN_T> expression() <RPAREN_T> ] [ <IS_T> ]
            block_header()
            block_declarative_part()
            <BEGIN_T>
            block_statement_part()
            <END_T> <BLOCK_T> [ identifier() ] <SEMI_T>
            {
              m_sharedState->genLabels=outlineParser()->popLabel(m_sharedState->genLabels);
            }
}

void block_statement_part() :  {}
{
  ( concurrent_statement() )*
}

void  case_statement() : {QCString s;}
{
[LOOKAHEAD(2) identifier()  <COLON_T> ]
  <CASE_T> [ <Q_T> ] s=expression()
    {
     QCString ca="case "+s;
     FlowChart::addFlowChart(FlowChart::CASE_NO,QCString(),ca);
    }
  <IS_T>
        case_statement_alternative()
        ( case_statement_alternative ())*
        <END_T> <CASE_T> [ <Q_T> ] [ identifier() ] <SEMI_T>
        {
         FlowChart::moveToPrevLevel();
         FlowChart::addFlowChart(FlowChart::END_CASE,"end case",QCString());
        }
}

void case_scheme (): {}
{
 <CASE_T> expression() <GENERATE_T> when_stats() [LOOKAHEAD(3) <END_T> [identifier()] <SEMI_T>]  <END_T>
 <GENERATE_T> generate_statement_body() <SEMI_T>
}

void when_stats() : {}
{
  (
   <WHEN_T> [LOOKAHEAD(2) label() <COLON_T>] choices() <ARROW_T> generate_statement_body()
   )+
}

void case_statement_alternative() :  {QCString s;}
{
  <WHEN_T> s=choices() <ARROW_T>
   {
    QCString t("when ");
    t+=s+"=> ";
    FlowChart::addFlowChart(FlowChart::WHEN_NO,s,t);
    }
  sequential_statement_body() {FlowChart::moveToPrevLevel(); }
}

QCString character_literal() :  {Token *tok=nullptr;}
{
  tok=<CHARACTER_LITERAL>{ return QCString(tok->image);}
}

QCString choice() : {QCString s;}
{
   LOOKAHEAD(simple_expression() direction ())
  s=range() { return s;}
  |
   LOOKAHEAD(simple_expression())
   s=simple_expression(){ return s; }
   |
   LOOKAHEAD(discrete_range())
  s=discrete_range(){ return s; }
  |
   s=identifier(){ return s; }
  | <OTHER_T> { return " others "; }
}


QCString choices() :  {QCString s,s1;}
{
  s=choice() (<BAR_T> s1=choice(){s+="|";s+=s1;})* { return s; }
}

void component_configuration () :{}
{
    <FOR_T> component_specification()
        [ binding_indication() <SEMI_T> ]
        [ block_configuration() ]
    <END_T> <FOR_T> <SEMI_T>
}
void component_declaration() :  {QCString s;}
{
 <COMPONENT_T> s=identifier() [ <IS_T> ]
   { m_sharedState->currP=VhdlSpecifier::COMPONENT; }
  [ generic_clause() ]
  [ port_clause() ]
   {
     outlineParser()->addVhdlType(s,outlineParser()->getLine(COMPONENT_T),
                                  EntryType::makeVariable(),VhdlSpecifier::COMPONENT,QCString(),QCString(),Protection::Public);
     m_sharedState->currP=VhdlSpecifier::UNKNOWN;
  }
  <END_T> [ <COMPONENT_T> ] [ identifier() ] <SEMI_T>

}

void component_instantiation_statement() :  {QCString s,s1;}
{

 s=identifier() <COLON_T>
 s1=instantiation_unit()
 {
       QCString s3;
       if (s1.contains("|")) {
         s3=VhdlDocGen::getIndexWord(s1,0);
         s1=VhdlDocGen::getIndexWord(s1,1);
       }

       outlineParser()->addCompInst(s.lower(),s1.lower(),s3,outlineParser()->getLine());
 }
        [ LOOKAHEAD(generic_map_aspect()) generic_map_aspect() ]
        [ port_map_aspect() ] <SEMI_T>
}

void component_specification() :  {}
{
instantiation_list() <COLON_T> name()
}

QCString composite_type_definition() :  { QCString s,s1;}
{
 s=array_type_definition(){ return s; }
| record_type_definition(){ return s+"#"; }
}

void concurrent_assertion_statement() :  {}
{
[  LOOKAHEAD(2) identifier() <COLON_T> ] [  <POSTPONED_T> ] assertion() <SEMI_T>
}

void concurrent_procedure_call_statement() :  {}
{
[  LOOKAHEAD(2) identifier() <COLON_T> ] [ <POSTPONED_T> ] procedure_call() <SEMI_T>
}

void concurrent_signal_assignment_statement() :  {}
{
[ LOOKAHEAD(2) identifier() <COLON_T> ] [<POSTPONED_T> ]
(
LOOKAHEAD(concurrent_conditional_signal_assignment()) concurrent_conditional_signal_assignment()
| LOOKAHEAD(concurrent_selected_signal_assignment()) concurrent_selected_signal_assignment()
| concurrent_simple_signal_assignment()
)
}

void  concurrent_conditional_signal_assignment(): {}
 {
     target() "<=" [ <GUARDED_T> ] [ delay_mechanism() ] conditional_waveforms() ";"
}

void  concurrent_simple_signal_assignment() :  {}
{
      target() "<=" [ <GUARDED_T> ] [ delay_mechanism() ] waveform() ";"
}

void  concurrent_selected_signal_assignment() :  {}
{
     <WITH_T> expression() <SELECT_T> [ "?" ] target() "<=" [ <GUARDED_T> ] [ delay_mechanism() ] selected_waveforms() ";"
}

void concurrent_signal_association_statement() :  {}
{
 [ LOOKAHEAD(2) identifier() ":" ] concurrent_simple_signal_association()
}

void concurrent_simple_signal_association() : {}
 {
 identifier() "<=>" identifier() ";"
}

void concurrent_statement() :  {}
{

LOOKAHEAD([identifier() ":"] <BLOCK_T>)
block_statement()
|
LOOKAHEAD([identifier() ":"] [<POSTPONED_T>] <PROCESS_T>)
process_statement()
|
LOOKAHEAD(3)
generate_statement()
|
LOOKAHEAD([identifier() ":"] [<POSTPONED_T>] <ASSERT_T>)
concurrent_assertion_statement()
|
LOOKAHEAD(concurrent_signal_assignment_statement())
 concurrent_signal_assignment_statement()
| LOOKAHEAD(concurrent_signal_association_statement())
concurrent_signal_association_statement()
|
LOOKAHEAD(component_instantiation_statement() )
component_instantiation_statement()
|
LOOKAHEAD(concurrent_procedure_call_statement())
concurrent_procedure_call_statement()

| <VHDL2008TOOLDIR>
 
}

QCString condition() :  {QCString s;}
{
  s=expression() { return s; }
}


QCString condition_operator() :  {QCString s;}
{
  <QQ_T> {return "??";}
}

QCString condition_clause() :  {QCString s;}
{
  <UNTIL_T> s=condition()
  {
    return " until "+s;
  }
}


void conditional_signal_assignment_wave(): {}
{
  LOOKAHEAD(conditional_force_assignment())
  conditional_force_assignment() |
  conditional_waveform_assignment()
}

void conditional_waveform_assignment():{}
{
  target()
  <LESSTHAN_T> [LOOKAHEAD(1) delay_mechanism() ] waveform_element()
  <WHEN_T> expression() [else_wave_list()]
  <SEMI_T>
}

void  else_wave_list(): {}
{
  <ELSE_T> expression() [ <WHEN_T> expression()]
}

void conditional_force_assignment(): {}
{
  target()
  <LESSTHAN_T>
  <FORCE_T>  [ <IN_T> |<OUT_T>] expression()
  <WHEN_T> [expression() else_stat()]
  <SEMI_T>
}

void else_stat(): {}
{
   (<ELSE_T> expression() [LOOKAHEAD(1) <WHEN_T> expression()])+
}

QCString conditional_expression() :  {QCString s;}
{
  s=expression() ( <WHEN_T> condition() <ELSE_T> expression() )* { return s;}
}

QCString  conditional_or_unaffected_expression() :  {QCString s;}
{
 s=expression_or_unaffected() (LOOKAHEAD(<WHEN_T> condition() <ELSE_T>) <WHEN_T> condition() <ELSE_T> expression_or_unaffected())* [LOOKAHEAD(1) <WHEN_T> condition() ] {return s;}
}

void conditional_signal_assignment() :  {}
{
  // LOOKAHEAD(  target() "<=" options_() conditional_waveforms() ";")
 target() <LESSTHAN_T> options() conditional_waveforms() <SEMI_T>
}

void conditional_waveforms() :  {}
{
waveform()
    ( LOOKAHEAD(<WHEN_T> condition() <ELSE_T>)
       <WHEN_T> condition() <ELSE_T> waveform() )*
    [ <WHEN_T> condition() ]
}



void configuration_declaration() :  {QCString s,s1;}
{
 <CONFIGURATION_T> s=identifier() <OF_T> s1=name() <IS_T>
  {

  m_sharedState->confName=s+"::"+s1;
  outlineParser()->addVhdlType(s,outlineParser()->getLine(CONFIGURATION_T),
                               EntryType::makeVariable(),VhdlSpecifier::CONFIG,"configuration",s1,Protection::Public);
  }
    configuration_declarative_part()
    block_configuration()
 <END_T> [ <CONFIGURATION_T> ] [ name() ] <SEMI_T>
 { m_sharedState->genLabels.clear(); m_sharedState->confName="";}
}

void configuration_declarative_item() : {}
{
 use_clause()
| attribute_specification()
| group_declaration()
}

void configuration_declarative_part() :  {}
{
 (configuration_declarative_item())*
}

void configuration_item ():  {}
{
 LOOKAHEAD(component_configuration())
 component_configuration()
 | block_configuration()

}

void configuration_specification() :  {}
{
<FOR_T> component_specification() binding_indication() <SEMI_T>
}

QCString constant_declaration() :  {QCString s,s1,s2;Token *t=nullptr;}
{
   <CONSTANT_T> s=identifier_list() <COLON_T> s1= subtype_indication() [ t=<VARASSIGN_T> s2=conditional_expression() ] <SEMI_T>
    {
     if(t!=nullptr)
      s2.prepend(":=");
     QCString it=s1+s2;
     outlineParser()->addVhdlType(s,outlineParser()->getLine(CONSTANT_T),
                                  EntryType::makeVariable(),VhdlSpecifier::CONSTANT,QCString(),it,Protection::Public);
     it.prepend("constant ");
     return it;
    }
}

QCString constraint_array_definition (): {QCString s,s1;}
{
<ARRAY_T> s=index_constraint() <OF_T> s1=subtype_indication(){ return s+" "+s1;}
}


void context_clause (): {}
{
  (LOOKAHEAD(3) context_item())+
}

QCString constraint () :{QCString s;}
 {
    LOOKAHEAD(range_constraint())
    s=range_constraint(){ return s;}
    |
    LOOKAHEAD(index_constraint())
     s=index_constraint(){ return s;}
}

void context_item() :  {}
{
 library_clause()
| use_clause()

| context_ref() 
}

QCString context_ref() : {QCString s, s1;}
{
 <CONTEXT_T>  s=identifier() (<DOT_T> s1=identifier() {s+=".";s+=s1;} )*  <SEMI_T>
 {
  return "context "+s ;
 }
}

void context_declaration(): {QCString s,s1;}
{
 <CONTEXT_T> s=identifier() <IS_T> { m_sharedState->parse_sec=VhdlSection::CONTEXT_SEC; }  context_clause() <END_T> [ <CONTEXT_T> ][identifier()] <SEMI_T>
                        {
                          m_sharedState->parse_sec=VhdlSection::UNKNOWN;
                          outlineParser()->addVhdlType(s,outlineParser()->getLine(LIBRARY_T),
                                                       EntryType::makeVariable(),VhdlSpecifier::LIBRARY,"context",s1,Protection::Public);
                        }
}

QCString decimal_literal() :  {Token *tok=nullptr;}
{
 tok=<DECIMAL_LITERAL> { return QCString(tok->image); }
}


QCString delay_mechanism ():  {QCString s;}
{
<TRANSPORT_T> { return " transport ";}
| [ <REJECT_T> s=expression() {s.prepend(" reject ");}] <INERTIAL_T> { return s+" inertial "; }
}

void design_file() :  {}
{
  (design_unit())+  {}
  | <EOF>
}

void design_unit() :  {}
{
  [LOOKAHEAD (3) context_clause()] library_unit()
}

QCString designator() : {QCString s;}
{
 s=identifier()          {return s;}
 | s=operator_symbol(){return s;}
}

QCString direction ():  {Token *tok=nullptr;}
{
tok=<TO_T>  { return QCString(tok->image);}
| tok=<DOWNTO_T> { return QCString(tok->image);}
}

QCString discrete_incomplete_type_definition ():  {Token *tok=nullptr;}
{
 <LPAREN_T> <BOX_T>  <RPAREN_T> { return "(<>)";}
}

void disconnection_specification() : {}
{
<DISCONNECT_T> guarded_signal_specificatio() <AFTER_T> expression() <SEMI_T>
}

void guarded_signal_specificatio() : {}
{
 signal_list() <COLON_T> name()
}

QCString discrete_range() : {QCString s;}
{
  LOOKAHEAD(range())
  s=range() { return s;}
  |
  LOOKAHEAD(subtype_indication())
   s=subtype_indication() { return s;}
}

QCString element_array_mode_view_indication() :  {QCString s;}
{
 <VIEW_T> <LPAREN_T> s=identifier() <RPAREN_T> {return "view("+s+")";}
}


QCString element_association() :  {QCString s,s1;}
{
[LOOKAHEAD(choices() <ARROW_T>) s=choices() <ARROW_T> ]  s1=expression()
 {
if(!s.isEmpty())
 return s+"=>"+s1;
return s1;
 }
}

QCString element_constraint() :  {QCString s,s1;}
{
  LOOKAHEAD(5) record_constraint() { return " ";}
 | array_constraint() { return " ";}
}

QCString element_declaration() :  {QCString rec_name,s1,s2;}
{
  rec_name=identifier_list() <COLON_T> s1=subtype_indication() <SEMI_T>
  {
    auto ql = split(rec_name.str(),",");
    for (const auto &n : ql)
    {
      std::string name=n+"~";
      name+=outlineParser()->getNameID().str();
      outlineParser()->addVhdlType(
          name.c_str(),outlineParser()->getLine(),
          EntryType::makeVariable(),
          VhdlSpecifier::RECORD,QCString(),
          s1,
          Protection::Public);
    }
    s2=rec_name+":"+s1;
    return s2;
  }
}

QCString element_resolution() :  {QCString s,s1;}
{
  LOOKAHEAD(array_element_resolution()) array_element_resolution()
  | record_resolution()
}

QCString element_mode_indication() :  {QCString s;}
{
  s=mode() {return s;}
  | s=element_mode_view_indication() {return s;}
}

QCString element_mode_view_indication() :  {QCString s;}
{
  LOOKAHEAD(2) s=element_record_mode_view_indication() {return s;}
  | s=element_array_mode_view_indication() {return s;}
}

QCString element_record_mode_view_indication() :  {QCString s;}
{
 <VIEW_T> s=identifier() { return "view "+s;}
}


QCString entity_aspect() :  {Token *tok=nullptr;QCString s,s1;}
{
tok=<ENTITY_T> s=name() [ LOOKAHEAD(1)<LPAREN_T> s1=identifier() <RPAREN_T> {s+="("+s1+")";} ] { return s;}
| tok=<CONFIGURATION_T> s=name() { return QCString(tok->image)+s;}
| tok=<OPEN_T> { return QCString(tok->image); }
}

QCString entity_class() :  {}
{
<ENTITY_T> { return "entity";}
| <ARCHITECTURE_T> {return "architecture";}
| <CONFIGURATION_T> {return "configuration";}
| <PROCEDURE_T> {return "procedure";}
| <FUNCTION_T> {return "function";}
| <PACKAGE_T> {return "package";}
| <TYPE_T> {return "type";}
| <SUBTYPE_T> {return "subtype";}
| <CONSTANT_T> {return "constant";}
| <SIGNAL_T> {return "signal";}
| <VARIABLE_T> {return "variable";}
| <COMPONENT_T> {return "component";}
| <LABEL_T> {return "label";}
| <LITERAL_T> {return "literal";}
| <UNITS_T> {return "units";}
| <GROUP_T> {return "group";}
| <FILE_T>  {return "file";}
}

QCString entity_class_entry() :  {QCString s;}
{
 s=entity_class() [ <BOX_T> {s+="<>";} ] { return s;}
}

QCString entity_class_entry_list() :  {QCString s,s1,s2;}
{
 ( s1=entity_class_entry() {s+=s1;} )(<COMMA_T> s=entity_class_entry(){s2+=",";s2+=s;}  )* { return s1+s2;}
}

void entity_declaration() :  {QCString s;}
{
   // try{
    <ENTITY_T> s=identifier()  <IS_T>
             {
                m_sharedState->lastEntity=m_sharedState->current;
                m_sharedState->lastCompound=nullptr;
                outlineParser()->addVhdlType(s,outlineParser()->getLine(ENTITY_T),
                              EntryType::makeClass(),VhdlSpecifier::ENTITY,QCString(),QCString(),Protection::Public);
               }
        entity_header()
        entity_declarative_part ()
      [ <BEGIN_T> entity_statement_part() ]
       <END_T> [ <ENTITY_T> ] [ name() ]
     //    }catch(...){outlineParser()->error_skipto(SEMI_T);}
     <SEMI_T>
     { m_sharedState->lastEntity=nullptr;m_sharedState->lastCompound=nullptr; m_sharedState->genLabels.clear(); }
}

void entity_declarative_item() : {}
{
subprogram_declaration()
//| subprogram_body()
| type_declaration()
| subtype_declaration()
| constant_declaration()
| signal_declaration()
| LOOKAHEAD(5) package_instantiation_declaration()
| LOOKAHEAD(3) package_body()
| LOOKAHEAD(3) package_declaration()
| variable_declaration()
| file_declaration()
| alias_declaration()
| mode_view_declaration()
|
LOOKAHEAD(attribute_declaration())
attribute_declaration()
| attribute_specification()
| disconnection_specification()
| use_clause()
|
LOOKAHEAD(3)
group_template_declaration()
| group_declaration()
|
LOOKAHEAD(5)
 package_instantiation_declaration()
|package_declaration()
| <VHDL2008TOOLDIR>
}

void entity_declarative_part() : {}
{
  (entity_declarative_item() )*
}

QCString entity_designator() :  {QCString s,s1;}
{
s=entity_tag() [ s1=signature() ] { return s+s1;}
}

void entity_header() : {}
{
 [  { m_sharedState->currP=VhdlSpecifier::GENERIC;m_sharedState->parse_sec=VhdlSection::GEN_SEC; } generic_clause()]
 [ { m_sharedState->currP=VhdlSpecifier::PORT; } port_clause()]
}

QCString entity_name_list() :  {QCString s,s1,s2;}
{
(s1=entity_designator() ) (<COMMA_T> s=entity_designator() { s2+=s;  } )* { return s2;}
| <OTHER_T> { return "other";}
| <ALL_T> {return "all";}
}



QCString entity_specification() :  {QCString s,s1;}
{
s=entity_name_list() <COLON_T> s1=entity_class(){ return s+":"+s1;}
}

void entity_statement() :  {}
{
LOOKAHEAD(concurrent_assertion_statement())
concurrent_assertion_statement()
|
LOOKAHEAD(process_statement())
 process_statement()
| concurrent_procedure_call_statement()

}

void entity_statement_part() :  {}
{
 (entity_statement())*
}


QCString entity_tag ():  {QCString s;}
{
s=name() { return s;}
| s=character_literal() { return s;}
}

QCString enumeration_literal() :  {QCString s;}
{
 s=identifier() { return s;}
 | s=character_literal() { return s;}
}

QCString enumeration_type_definition() : {QCString s,s1;}
{
  <LPAREN_T>s=enumeration_literal() (LOOKAHEAD(1)<COMMA_T> s1=enumeration_literal() {s+=",";s+=s1;} )* <RPAREN_T>
  { return "("+s+")";}
}

QCString exit_statement() :  {QCString s,s1,s2;Token *t=nullptr;Token *t1=nullptr;}
{
[ s=identifier() t=<COLON_T> ] <EXIT_T> [ s1=identifier() ]
[ t1=<WHEN_T> s2=condition() ] <SEMI_T>
{
  m_sharedState->lab.clear();
  if(t!=nullptr) s+=":";
  if(t1!=nullptr) s2.prepend(" when ");
   FlowChart::addFlowChart(FlowChart::EXIT_NO,"exit",s2,s1);

  return s+s1+s2+";";
}
}

QCString expression ():  {QCString s,s1,s2;}
{
/* LOOKAHEAD(5) */ s=relation() ( s1=logop() s2=relation() {s+=s1;s+=s2;} )* { return s; }
//|condition_operator() s=primary() {return " ?? "+s;}

}

QCString expression_or_unaffected ():  {QCString s;}
{
   s=expression() { return s;}
   | <UNAFFECTED_T> { return "unaffected";}
}

QCString external_pathname(): {QCString s;}
{
   s=absolute_pathname()  { return s;}
 | s=relative_pathname()   { return s;}
 | s=package_path_name()   { return s;}
 }

QCString external_name(): {QCString s,s1,s2;}
{
 <SLSL_T> s=sig_stat() s1=external_pathname() <COLON_T>  s2=subtype_indication()  <RSRS_T>
                        {
                         QCString t="<<"+s;
                         QCString t1=s1+":"+s2+">>";
                         return   s+s1;
                        }
}

QCString sig_stat(): {Token *t;}
{
  t=<CONSTANT_T>      { return QCString(t->image); }
  | t=<SIGNAL_T>      { return QCString(t->image); }
  | t=<VARIABLE_T>   { return QCString(t->image); }

}

QCString logop() : {}
{
  <AND_T> { return "and" ;}
  |<NAND_T> { return "nand" ;}
  |<NOR_T> { return "nor" ;}
  |<XNOR_T> { return "xnor" ;}
  |<XOR_T> { return "xor" ;}
  |<OR_T> { return "or" ;}
 }

QCString extended_identifier ():  {Token *t;}
{
 t=<EXTENDED_CHARACTER> { return QCString(t->image); }
}

QCString factor():  {QCString s,s1;}
{
s=primary() [LOOKAHEAD(1) <DOUBLEMULT_T> s1=primary(){ s+="**";s+=s1;} ] { return s;}
| <ABS_T> s=primary(){ s1 = "abs "; return s1+s; }
| <NOT_T>  s=primary(){s1="not ";return s1+s;}
| <QQ_T>  s=primary(){s1="?? ";return s1;}
| s=logop() s1=primary() { return s;}

}

QCString file_declaration() :  {QCString s,s1,s2,s3;}
{
 <FILE_T> s=identifier_list() <COLON_T> s2=subtype_indication() [ s3=file_open_information() ] <SEMI_T>
   {
   QCString t1=s2+" "+s3;
   outlineParser()->addVhdlType(s,outlineParser()->getLine(),
                                EntryType::makeVariable(),VhdlSpecifier::VFILE,QCString(),t1,Protection::Public);
   return " file "+s+":"+s2+" "+s3+";";
   }
 }

QCString  file_logical_name():  {QCString s;}
{
 s=expression() { return s; }
}

QCString file_open_information() :  {QCString s,s1,s2;}
{
 [ <OPEN_T> s=expression() ] <IS_T> [ <IN_T> |<OUT_T>] s1=file_logical_name() {s2="open "+s+" is "+s1;  return s2; }
}

QCString file_type_definition() :  {QCString s,s1;}
{
 <FILE_T> <OF_T> s=type_mark() { s1=" file of "+s; return s1;}
}

QCString file_incomplete_type_definition() :  {QCString s,s1;}
{
 <FILE_T> <OF_T> type_mark() { return  ""; }
}

QCString floating_incomplete_type_definition() :  {QCString s,s1;}
{
   <RANGE_T> <BOX_T>  <DOT_T> <BOX_T>  { return  "range <>.<>"; }
}

QCString floating_type_definition() :  {QCString s;}
{
  s=range_constraint(){ return s;}
}

QCString formal_designator() : {QCString s;Token *tok=nullptr;}
{
    s=name()  { return s; }
    |tok=<INTEGER> { return QCString(tok->image);}
}


QCString formal_parameter_list() :  {QCString s;}
{
 s=interface_list() { return s; }
}

QCString formal_part() : {QCString s,s1;}
{
s=name() [<LPAREN_T> formal_designator() <RPAREN_T> {s+"("+s1+")";}] {return s;}
}

QCString full_type_declaration() :  { std::shared_ptr<Entry> tmpEntry;QCString s,s1,s2; }
{
  <TYPE_T> s=identifier() <IS_T>
  {
    tmpEntry=m_sharedState->current;
    outlineParser()->addVhdlType(s,outlineParser()->getLine(),
                                 EntryType::makeVariable(),VhdlSpecifier::RECORD,QCString(),QCString(),Protection::Public);
  }
 
  s2=type_definition()
  
  <SEMI_T>
  {
     if (s2.contains("#")) {
      VhdlDocGen::deleteAllChars(s2,'#');
      tmpEntry->vhdlSpec=VhdlSpecifier::RECORD;
      tmpEntry->type=s2;
    }
    else if (s2.contains("%")) {
      VhdlDocGen::deleteAllChars(s2,'%');
      tmpEntry->vhdlSpec=VhdlSpecifier::UNITS;
      tmpEntry->type=s2;
     }
    else {
      tmpEntry->vhdlSpec=VhdlSpecifier::TYPE;
      tmpEntry->type=s2;
    }
   
    tmpEntry.reset();
    return "type "+s+" is "+s2+";";
  }
}

QCString function_call() :  {QCString s,s1;}
{
s=name()  <LPAREN_T> s1=actual_parameter_part()  <RPAREN_T> { return s+"("+s1+")";}
}

void geninter():{}
{
    [gen_interface_list() <SEMI_T> [gen_assoc_list() <SEMI_T>]]
}

void gen_assoc_list():{}
{
   <GENERIC_T> <MAP_T> <LPAREN_T>  association_list()<RPAREN_T>
}

void gen_interface_list() : {}
{
   <GENERIC_T><LPAREN_T>
                        {

                          m_sharedState->parse_sec=VhdlSection::GEN_SEC;

                        }
                        interface_list()
                        {

                          m_sharedState->parse_sec=VhdlSection::UNKNOWN;

                        }
                        <RPAREN_T>
}


void generate_statement_body() : {}
{
      [(LOOKAHEAD(block_declarative_item())block_declarative_item() )*  <BEGIN_T>] (concurrent_statement())*
}

void generate_statement_body1() : {}
{
   generate_statement_body()   generate_scheme_1()  [generate_scheme_2()]
}

void generate_scheme_1() : {}
{
 ( generate_scheme_3())*
}

void generate_scheme_2() : {}
{
<ELSE_T> [LOOKAHEAD(2) identifier() <COLON_T> ] <GENERATE_T> generate_statement_body()
}

void generate_scheme_3() : {}
{
 <ELSIF_T>[LOOKAHEAD(2) identifier() <COLON_T> ] expression() <GENERATE_T> generate_statement_body()
}

void generate_statement() :  {QCString s;}
{
s=identifier() <COLON_T>
          try{
        generate_scheme() <GENERATE_T>
        { outlineParser()->pushLabel(m_sharedState->genLabels,s); }
          generate_statement_body1()
        <END_T>
                 }catch(...){outlineParser()->error_skipto(GENERATE_T);}
        <GENERATE_T> [ identifier() ] <SEMI_T> {m_sharedState->genLabels=outlineParser()->popLabel(m_sharedState->genLabels); }
}

void generate_scheme() : {}
{
<FOR_T> parameter_specification()
| <IF_T> [LOOKAHEAD(2) identifier() <COLON_T> ] condition()
}

void generic_clause() : {QCString s;}
{
 <GENERIC_T>  <LPAREN_T> { m_sharedState->parse_sec=VhdlSection::GEN_SEC; } s=generic_list() <RPAREN_T> <SEMI_T> { m_sharedState->parse_sec=VhdlSection::UNKNOWN; }
}

QCString generic_list() :  {QCString s;}
{
 s=interface_list() { return s; }
}

void generic_map_aspect() :  {}
{
     <GENERIC_T> <MAP_T> <LPAREN_T> association_list() <RPAREN_T>
}

QCString group_constituent() :  {QCString s;}
{
 s=name() { return s; }
 | s=character_literal() { return s;}
}

QCString group_constituent_list() : {QCString s,s1,s2;}
{
  (s1=group_constituent())(<COMMA_T> s=group_constituent(){s2+=",";s2+=s1;})* { return s+s2;}
}

QCString group_declaration() :  {QCString s,s1,s2;}
{
  <GROUP_T> s=identifier() <COLON_T> s1=identifier() <LPAREN_T> s2=group_constituent_list() <RPAREN_T> <SEMI_T>
  {
   return "group "+s+":"+s1+"("+s2+");";
  }
}

QCString group_template_declaration() : {QCString s,s1;}
{
 <GROUP_T> s=identifier() <IS_T> <LPAREN_T> s1=entity_class_entry_list() <RPAREN_T> <SEMI_T>
  {
    return "group "+s+ "is ("+s1+");";
  }
 }

void guarded_signal_specification() : {}
{
 signal_list() <COLON_T> type_mark()
}

QCString identifier() : {Token *tok=nullptr;}
{
  tok=<EXTENDED_CHARACTER>{ return QCString(tok->image); }
  |tok=<BASIC_IDENTIFIER> { return QCString(tok->image); }
}

QCString identifier_list() : {QCString str,str1;}
{
   str=name() (<COMMA_T> str1=name() {str+=",";str+=str1;})* [ LOOKAHEAD(1,{checkListTok()}) <SEMI_T> ] { return str; }
}

void if_statement() :  {QCString s,s1;}
{
  [LOOKAHEAD(1) identifier() <COLON_T> ]
    <IF_T> s=condition() <THEN_T>
    {
      s.prepend("if ");
      FlowChart::addFlowChart(FlowChart::IF_NO,QCString(),s);
    }
  sequence_of_statements()
    (
     <ELSIF_T> s1=condition() <THEN_T>
     {
     s1.prepend("elsif ");
     FlowChart::addFlowChart(FlowChart::ELSIF_NO,QCString(),s1);
     }
     sequence_of_statements()
    )*
    [LOOKAHEAD(1) <ELSE_T>
    {
      FlowChart::addFlowChart(FlowChart::ELSE_NO,QCString(),QCString());
    }
  sequence_of_statements() ] <END_T> <IF_T> [ identifier() ] <SEMI_T>
  {
    FlowChart::moveToPrevLevel();
    FlowChart::addFlowChart(FlowChart::ENDIF_NO,QCString(),QCString());
  }
}

QCString incomplete_subtype_indication() :  {QCString s;}
{
  subtype_indication() {return "";}
  | anonymous_type_indication()  {return "";}
}

QCString incomplete_type_definition() :  {QCString s;}
{
 private_incomplete_type_definition()  {return "";}
  | scalar_incomplete_type_definition()  {return "";}
  | discrete_incomplete_type_definition()  {return "";}
  | physical_incomplete_type_definition()  {return "";}
  | LOOKAHEAD(4) floating_incomplete_type_definition()  {return "";}
  | integer_incomplete_type_definition()  {return "";}
  | array_incomplete_type_definition()  {return "";}
  | access_incomplete_type_definition()  {return "";}
  | file_incomplete_type_definition()  {return "";}
}

QCString incomplete_type_mark() :  {QCString s;}
{
 type_mark() {return "";}
 | anonymous_type_indication()  {return "";}

}

QCString integer_incomplete_type_definition() :  {QCString s;}
{
  <RANGE_T> <BOX_T> {return "range <>";}
}

QCString incomplete_type_declaration() :  {QCString s;}
{
  <TYPE_T> s=identifier() <SEMI_T>
  {
   return "type "+s+";";
  }
}

QCString index_constraint() :  {QCString s("("); QCString s1,s2;}
{
  <LPAREN_T> s2=discrete_range(){s+=s2;}(LOOKAHEAD(1)<COMMA_T> s1=discrete_range(){s+=",";s+=s1;})*  <RPAREN_T> {return s+")";}
  }

QCString index_specification() : {QCString s;}
{
 LOOKAHEAD( discrete_range())
 s=discrete_range() { return s;}
| s=expression(){ return s;}
}



QCString index_subtype_definition() :  {QCString s;}
{
 s=type_mark() <RANGE_T> <BOX_T> { return s+" range <> ";}
}

QCString instantiation_unit() :  {QCString s,s1,s2;}
{
[ <COMPONENT_T> ] s=name() {s1="component "; return s; }
| <ENTITY_T>  [LOOKAHEAD(2)<BASIC_IDENTIFIER> <DOT_T>] s2=name() {s="entity|"+s2;} [ <LPAREN_T> s1=identifier() <RPAREN_T> {s+="(";s+=s1;s+=")" ;}] { return s;}
| <CONFIGURATION_T> s=name() {s1="configuration ";return s;}
}

QCString instantiation_list() : {QCString s;Token *tok=nullptr;}
{
  s=identifier_list() { return s;}
| tok=<OTHER_T> {return QCString(tok->image);}
| tok=<ALL_T> {return QCString(tok->image);}
}

QCString integer() :  {Token *t;}
{
  t=<INTEGER> {return QCString(t->image);}
}

QCString integer_type_definition() :  {QCString s;}
{
  s=range_constraint(){ return s;}
}

QCString interface_declaration() :  {QCString s,s1;}
{
LOOKAHEAD(interface_variable_declaration())
 s=interface_variable_declaration() { return s;}
|
 LOOKAHEAD(interface_object_declaration())
 interface_object_declaration() { return " ";}
|
LOOKAHEAD(interface_subprogram_declaration())
 {m_sharedState->interf_sec=true;} s=interface_subprogram_declaration() {m_sharedState->interf_sec=false ;return s;}
|
LOOKAHEAD(interface_package_declaration())
interface_package_declaration() { return s;}
|

LOOKAHEAD(5)
s=interface_type_declaration() { return s;}
|
LOOKAHEAD(interface_subprogram_declaration())
interface_subprogram_declaration() { return s;}
|
 s=object_class() s1=identifier()
 {
   if (m_sharedState->parse_sec==VhdlSection::GEN_SEC)
     outlineParser()->addVhdlType(s,outlineParser()->getLine(),
                                  EntryType::makeVariable(),m_sharedState->currP,s1,QCString(),Protection::Public);
   return s;
 }
}

void interface_object_declaration() :  {QCString s,s1,s2;}
{
      LOOKAHEAD(interface_constant_declaration()) interface_constant_declaration()
      | LOOKAHEAD(interface_signal_declaration()) interface_signal_declaration()
    //  | interface_variable_declaration()
      | interface_file_declaration()
}

QCString interface_constant_declaration() :  {QCString s,s1,s2;}
{
  [ <CONSTANT_T> ] identifier_list() <COLON_T> [ <IN_T> ] interface_type_indication() [ <VARASSIGN_T> conditional_expression() ] {return "";}
}

QCString interface_element() :  {QCString s;}
{
  s=interface_declaration(){  return s;}
}

QCString interface_file_declaration() : {QCString s,s1;}
{
  <FILE_T> s=identifier_list() <COLON_T> s1=subtype_indication()
  {
    outlineParser()->addVhdlType(s,outlineParser()->getLine(),
                                 EntryType::makeVariable(),VhdlSpecifier::VFILE,QCString(),s1,Protection::Public);
    return QCString(" file "+s+":"+s1);
  }
}

QCString interface_list() :  {QCString s,s1,s2;}
{
  s=interface_element() (LOOKAHEAD(2) <SEMI_T> s1=interface_element(){s2+=";";s2+=s1;})* [ LOOKAHEAD(1,{checkListTok()}) <SEMI_T> ]  { return s+s2;}
}

QCString interface_package_declaration() :  {QCString s,s1,s2;}
{
  <PACKAGE_T> identifier() <IS_T> <NEW_T> name() interface_package_generic_map_aspect() {return "";}
}


QCString interface_package_generic_map_aspect() :  {QCString s,s1,s2;}
{
  LOOKAHEAD(4) <GENERIC_T> <MAP_T> <LPAREN_T> <BOX_T> <RPAREN_T> {return "";}
  | LOOKAHEAD(4)<GENERIC_T> <MAP_T> <LPAREN_T> <DEFAULT_T> <RPAREN_T> {return "";}
  | generic_map_aspect()  {return "";}
}

QCString interface_procedure_specification() :  {QCString s,s1,s2;}
{
 <PROCEDURE_T>  designator() [ [ <PARAMETER_T> ] <LPAREN_T> formal_parameter_list() <RPAREN_T> ] {return "";}
}

QCString interface_signal_declaration() :  {QCString s,s1,s2;}
{
 [ <SIGNAL_T> ] identifier_list() <COLON_T> /*[ <MODE_T> ]*/ interface_type_indication() [ <BUS_T> ] [ <VARASSIGN_T> conditional_expression() ] {return "";}
}

QCString interface_subprogram_declaration(): {QCString s;}
{
   s=iproc()  { return s;}
 | s=ifunc()  { return s; }
}

QCString iproc(): {QCString s,s1;}
{
  <PROCEDURE_T> s=identifier()  s1=param()
  {
    m_sharedState->current->name=s;
    return "procedure "+s+s1;
  }
}

QCString ifunc():{QCString s,s1,s2,s3;Token *t=nullptr;Token *t1=nullptr;Token *t2=nullptr;}
{
 [t=<PURE_T> | t=<IMPURE_T> ] <FUNCTION_T>  s=name() s1=param() <RETURN_T> s2=name() [t1=<IS_T> (s3=identifier() | t2=<BOX_T>)]
 {
   QCString q;
   if(t!=nullptr) q=t->image;
   if(t2!=nullptr) s3="<>";
   if (!s3.isEmpty())
   {
     s3.prepend(" is ");
   }
   m_sharedState->current->name=s;
   if (m_sharedState->parse_sec==VhdlSection::GEN_SEC)
   {
     QCString ss=q+" function "+s1+" return "+s2+s3;
     int a=outlineParser()->getLine(FUNCTION_T);
     int b=outlineParser()->getLine(PROCEDURE_T);

     if (a>b) b=a;
     outlineParser()->addVhdlType(m_sharedState->current->name,b,EntryType::makeVariable(),
                                  VhdlSpecifier::GENERIC,ss,QCString(),Protection::Public);
   }
   m_sharedState->currP=VhdlSpecifier::UNKNOWN;return QCString();
 }
}


QCString param(): {QCString s,s1;Token *tok=nullptr;}
{
  [ tok=<PARAMETER_T> ] { m_sharedState->param_sec=VhdlSection::PARAM_SEC; }
  [ <LPAREN_T>  s1=interface_list() <RPAREN_T>]
  {
    if(tok!=nullptr)
    {
      s = tok->image;
    }
    m_sharedState->param_sec=VhdlSection::UNKNOWN;
    return s+"("+s1+")";
  }
}

QCString interface_subprogram_default () :  {QCString s,s1,s2;}
{
 name()
 | <BOX_T>
}

QCString interface_subprogram_specification () :  {QCString s,s1,s2;}
{
     interface_procedure_specification() {return "";}
     | interface_function_specification() {return "";}
}

QCString  interface_function_specification() :  {QCString s,s1,s2;}
{
  [ <PURE_T>  | <IMPURE_T> ] <FUNCTION_T> designator() [LOOKAHEAD(1) subprogram_header() ]  [ [ <PARAMETER_T> ] <LPAREN_T> formal_parameter_list() <RPAREN_T> ] <RETURN_T> [LOOKAHEAD(2) identifier() <OF_T> ] type_mark() {return "";}
}

QCString  interface_incomplete_type_declaration() :  {QCString s="type";QCString s1;}
{
  <TYPE_T> s1=identifier()

  {
    if (m_sharedState->currP!=VhdlSpecifier::COMPONENT && m_sharedState->interf_sec==false)
    {
      if (m_sharedState->currP==VhdlSpecifier::FUNCTION || m_sharedState->currP==VhdlSpecifier::PROCEDURE)
      {
        outlineParser()->addProto("",s1,s,"","","");
      }
      else if(m_sharedState->parse_sec==VhdlSection::GEN_SEC)
      {
        outlineParser()->addVhdlType(s,outlineParser()->getLine(),EntryType::makeVariable(),VhdlSpecifier::GENERIC,s1,"",Protection::Public);
      }

      return s+" "+s1;
    }
  }
}

QCString  interface_type_declaration() :  {QCString s;}
{
  s=interface_incomplete_type_declaration() {return s;}
}

QCString  interface_type_indication() :  {QCString s,s1,s2;}
{
     subtype_indication() {return "";}
     | anonymous_type_indication() {return "";}
     | mode_view_indication() {return "";}
}


QCString interface_variable_declaration() :  {Token *tok=nullptr;Token *tok1=nullptr;Token *tok2=nullptr;QCString s,s1,s2,s3,s4,s5;}
{
[ ( tok=<VARIABLE_T> | tok=<SIGNAL_T> | tok=<CONSTANT_T>|tok=<SHARED_T>) ]
    s=identifier_list() <COLON_T> [ s1=mode() ]
    s2=subtype_indication()  [ tok1=<BUS_T> ] [ tok2=<VARASSIGN_T> s4=expression() ]
    {
      if(tok!=nullptr)
        s5=QCString(tok->image);

      if(tok1!=nullptr)
        s3=tok1->image;

      if(tok2!=nullptr)
        s3+=":=";

      QCString it=s+":"+s1+" "+s2+" "+s3+" "+s4;
      if (m_sharedState->currP!=VhdlSpecifier::COMPONENT && m_sharedState->interf_sec==false)
      {
          if (m_sharedState->currP==VhdlSpecifier::FUNCTION || m_sharedState->currP==VhdlSpecifier::PROCEDURE)
        {
          outlineParser()->addProto(s5,s,s1,s2,s3,s4);
        }
        else
        {
          QCString i=s2+s3+s4;
          outlineParser()->addVhdlType(s,outlineParser()->getLine(),
                                       EntryType::makeVariable(),m_sharedState->currP,i,s1,Protection::Public);
        }
      } // if component
      return it;
    }
}

QCString iteration_scheme() :  {QCString s;}
{
<WHILE_T> s=condition()
{
   s.prepend("while ");
   FlowChart::addFlowChart(FlowChart::WHILE_NO,QCString(),s,m_sharedState->lab);
   m_sharedState->lab="";
  return s;
}
| <FOR_T> s=parameter_specification()
{
    QCString q=m_sharedState->lab+" for "+s;
    FlowChart::addFlowChart(FlowChart::FOR_NO,QCString(),q,m_sharedState->lab);
    m_sharedState->lab="";
    return q;
}
}

QCString label() :  {QCString s;}
{
 s=identifier() { return s;}
}

QCString library_clause() :  {QCString s;}
{
 (<LIBRARY_T> s=identifier_list() <SEMI_T>
 )
 {
   if ( m_sharedState->parse_sec==VhdlSection::UNKNOWN && Config_getBool(SHOW_INCLUDE_FILES) )
   {
     outlineParser()->addVhdlType(s,outlineParser()->getLine(),
                                  EntryType::makeVariable(),VhdlSpecifier::LIBRARY,s,"_library_",Protection::Public);
   }
   QCString s1="library "+s;
   return s1;
 }
}

QCString library_unit() :  {QCString s;}
{
LOOKAHEAD(2)
primary_unit() {  return s; }
|  secondary_unit() {  return s; }


}

QCString literal() :  {QCString s;}
{

 LOOKAHEAD(bit_string_literal())
s=bit_string_literal() { return s;}
|
 LOOKAHEAD(numeric_literal())
 s=numeric_literal() { return s;}
|

LOOKAHEAD(enumeration_literal())
s=enumeration_literal() { return s;}
| s=string_literal() { return s;}
| <NULL_T> {return "null";}
}

QCString logical_operator() :  {QCString s;}
{
 s=logop() { return s;}
}

QCString loop_statement() :  {QCString s,s1,s2,s3;}
{
[ s=identifier() <COLON_T> {s+=":";} ]
    [ s1=iteration_scheme()  ]
      {
       if(s1.isEmpty())
        FlowChart::addFlowChart(FlowChart::LOOP_NO,QCString(),"infinite");
       }
      <LOOP_T>
        s2=sequence_of_statements()
        <END_T> <LOOP_T> [ s3=identifier() ] <SEMI_T>
        {
         QCString q = s+" loop "+s2+" end loop" +s3;
         QCString endLoop="end loop" + s3;
         FlowChart::moveToPrevLevel();
         FlowChart::addFlowChart(FlowChart::END_LOOP,endLoop,QCString());
        return q;
        }

}


QCString miscellaneous_operator():{Token *t=nullptr;}
{
  <DOUBLEMULT_T> { return "**"; }
  | <ABS_T>  { return "abs"; }
  | <NOT_T> { return "not"; }
}

QCString mode() :  {Token *tok=nullptr;}
{
tok=<IN_T> { return "in"; }
| tok=<OUT_T> { return "out"; }
| tok=<INOUT_T> { return "inout"; }
| tok=<BUFFER_T> { return "buffer"; }
| tok=<LINKAGE_T> { return "linkage"; }
}

QCString mode_indication() :  {Token *tok=nullptr;}
{
  simple_mode_indication() {return " ";}
  | mode_view_indication() {return " ";}
}

QCString mode_view_declaration() :  {Token *tok=nullptr;}
{
  <VIEW_T> identifier() <OF_T> subtype_indication() <IS_T> (mode_view_element_definition())* <END_T> <VIEW_T> [identifier()] <SEMI_T> {return "";}
}

QCString mode_view_element_definition() :  {Token *tok=nullptr;}
{
  record_element_list() <COLON_T> element_mode_indication() <SEMI_T> {return "";}
}

QCString mode_view_indication() :  {Token *tok=nullptr;}
{
  LOOKAHEAD(3) array_mode_view_indication() {return "";}
  | record_mode_view_indication()  {return "";}

}

QCString multiplying_operation() : {Token *tok=nullptr;}
{
tok=<MULT_T>      { return QCString(tok->image); }
| tok=<SLASH_T>  { return QCString(tok->image); }
| tok=<MOD_T>     { return QCString(tok->image); }
| tok=<REM_T>     { return QCString(tok->image); }
}


QCString name() :  {QCString s,s1;}
{
 (
   s=operator_symbol() [LOOKAHEAD(name_ext1()) s1=name_ext1(){ s+=s1;}] {  return s; }
   |s=external_name() [LOOKAHEAD(name_ext1()) s1=name_ext1(){ s+=s1;}] {  return s; }
   | s=identifier() [LOOKAHEAD(name_ext1()) s1=name_ext1(){ s+=s1;}] {  return s; }
  )
 
}


QCString name_ext1() : {QCString s,s1,s2;}
 {
   s=name_ext() (LOOKAHEAD(name_ext()) s1=name_ext(){s+=s1;})* { return s;}
 }

 QCString name_ext() : {QCString s,s1,s2;}
 {

  (
 LOOKAHEAD(<APOSTROPHE_T><SUBTYPE_T>)
 <APOSTROPHE_T><SUBTYPE_T>{s+="'subtype"; return s;}
|
 LOOKAHEAD(<DOT_T> suffix())
 <DOT_T> s1=suffix(){s+=".";s+=s1; return s;}
|
  LOOKAHEAD(test_att_name())
   s1=test_att_name() { s+=s1;return s;}
 |
 LOOKAHEAD( <LPAREN_T> discrete_range() <RPAREN_T>)
  <LPAREN_T> s1=discrete_range() <RPAREN_T> {s+="(";s+=s1;s+=")";return s;}
   |
  LOOKAHEAD( "(" expression() ("," expression() )* ")" )
  <LPAREN_T> s1=expression() {s+="(";s+=s1;} (LOOKAHEAD(1) <COMMA_T>  s1=expression(){s+=",";s+=s1;})*  <RPAREN_T> { s+=")";return s;}

 )
 
 }

 QCString test_att_name() : {QCString s,s1;}
 {
   LOOKAHEAD(4) <CHARACTER_LITERAL> <INTEGER> <APOSTROPHE_T> <RPAREN_T> {return "kkk";}
  |
  [ LOOKAHEAD(<LBRACKET_T>) s1=signature() {s=s1;}]
  <APOSTROPHE_T> s1=attribute_designator() {s+="'";s+=s1;}
  [LOOKAHEAD(1) <LPAREN_T> s1=expression() <RPAREN_T> {s+="(";s+=s1;s+=")";}]
   { return s;}
 }

 QCString indexed_name() : {QCString s,s1,s2;}
 {
   s2=identifier() <LPAREN_T> s1=expression(){s=s2+"("+s1;} (<COMMA_T> s1=expression(){s+=",";s+=s1;})* <RPAREN_T> {return s+")";}
 }

QCString next_statement() :  {QCString s,s1,s2;Token *t=nullptr;Token *t1=nullptr;}
{
[ s=identifier() t=<COLON_T> ] <NEXT_T> [ s1=identifier() ]
[ t1=<WHEN_T> s2=condition() ] <SEMI_T>
{
  if(t!=nullptr) s+=":";
   FlowChart::addFlowChart(FlowChart::NEXT_NO,"next ",s2,s1);
    m_sharedState->lab.clear();
  if(t1!=nullptr) s2.prepend("when ");
  return s+s1+s2+";";
}
}

QCString null_statement() : {QCString s;}
{
[ s=identifier() <COLON_T> {s+=":";}] <NULL_T> <SEMI_T>{return s+="null";}
}

QCString numeric_literal() :  {QCString s;}
{

 LOOKAHEAD(physical_literal())
  s=physical_literal(){ return s;}
 | s=abstract_literal() { return s;}
}

QCString object_class() :  {}
{
<CONSTANT_T>          { return "constant"; }
|<SIGNAL_T>            { return "signal"; }
|<VARIABLE_T>          { return "variable"; }
|<SHARED_T> <VARIABLE_T> { return "shared variable"; }
|<FILE_T>              { return "file"; }
|<TYPE_T>              { return "type"; }
}

QCString operator_symbol() :  {Token *tok=nullptr;}
{
tok=<STRINGLITERAL> {return QCString(tok->image);}
}

void options() :  {}
{
  [ <GUARDED_T> ] [ delay_mechanism() ]
}

void package_body() :  {QCString s;}
{
<PACKAGE_T> <BODY_T> s=name() <IS_T>
 {
                        m_sharedState->lastCompound=m_sharedState->current;
                        s.prepend("_");
                        outlineParser()->addVhdlType(s,outlineParser()->getLine(),
                                          EntryType::makeClass(),VhdlSpecifier::PACKAGE_BODY,QCString(),QCString(),Protection::Protected);
                      }
 package_body_declarative_part()

<END_T> [<PACKAGE_T> <BODY_T>  ] [ name() ] <SEMI_T> { m_sharedState->lastCompound=nullptr; m_sharedState->genLabels.clear(); }
}

void package_body_declarative_item() :  {}
{
subprogram_declaration()

| type_declaration()
| subtype_declaration()
| constant_declaration()
| variable_declaration()
| LOOKAHEAD(2) package_body()
| LOOKAHEAD(4)package_instantiation_declaration()
|  package_declaration()
| file_declaration()
| alias_declaration()
| mode_view_declaration()
| use_clause()
|
LOOKAHEAD(3)
group_template_declaration()
| group_declaration()
}

void package_body_declarative_part() :  {}
{
(package_body_declarative_item() )*
}

void package_header(): {QCString s;}
{
   [ generic_clause() [ generic_map_aspect() <SEMI_T> ] ]
}


void package_declaration():  {QCString s;}
{

 <PACKAGE_T> s=identifier() <IS_T>
                          {
                          m_sharedState->lastCompound=m_sharedState->current;
                          std::shared_ptr<Entry> clone=std::make_shared<Entry>(*m_sharedState->current);
                          clone->section=EntryType::makeNamespace();
                          clone->vhdlSpec=VhdlSpecifier::PACKAGE;
                          clone->name=s;
                          clone->startLine=outlineParser()->getLine(PACKAGE_T);
                          clone->bodyLine=outlineParser()->getLine(PACKAGE_T);
                          clone->protection=Protection::Package;
                          m_sharedState->current_root->moveToSubEntryAndKeep(clone);
                          outlineParser()->addVhdlType(s,outlineParser()->getLine(PACKAGE_T),
                                            EntryType::makeClass(),VhdlSpecifier::PACKAGE,QCString(),QCString(),Protection::Package);
                          }
    package_header()  
    package_declarative_part()
<END_T> [ <PACKAGE_T>] [ name() ] <SEMI_T>
{ m_sharedState->lastEntity=nullptr;m_sharedState->lastCompound=nullptr; m_sharedState->genLabels.clear(); }
}



void package_declarative_item() : {}
{

subprogram_declaration()
| type_declaration()
| subtype_declaration()
| LOOKAHEAD(5) package_instantiation_declaration()
| LOOKAHEAD(3) package_declaration()
| constant_declaration()
| signal_declaration()
| variable_declaration()
| file_declaration()
| alias_declaration()
| component_declaration()
| mode_view_declaration() 
|
LOOKAHEAD(attribute_declaration())
 attribute_declaration()
| attribute_specification()
| disconnection_specification()
| use_clause()
|
LOOKAHEAD(3)
 group_template_declaration()
| group_declaration()
|
 LOOKAHEAD(5)
 package_instantiation_declaration()
|package_declaration()

}

void package_declarative_part() : {}
{
 (package_declarative_item())*
}

void package_instantiation_declaration() : {QCString s,s1,s2;}
 {
 <PACKAGE_T> s=identifier() <IS_T>  <NEW_T> s1=name()  [gen_assoc_list()] <SEMI_T>
    {
      QCString q=" is new "+s1+s2;
      outlineParser()->addVhdlType(s,outlineParser()->getLine(PACKAGE_T),
                                   EntryType::makeVariable(),VhdlSpecifier::INSTANTIATION,"package",q,Protection::Public);
    }
}

QCString parameter_specification() : {QCString s,s1;}
{
s=identifier() <IN_T> s1=discrete_range(){ return s+" in "+s1;}
}



QCString pathname_element ():{QCString s,s1;}
{
  s=identifier() [<LPAREN_T> s1=expression()  <RPAREN_T>]
  {
    if(!s1.isEmpty())
     return s+"("+s1+")";

    return s;
  }
 }

QCString pathname_element_list():{QCString s,s1,s2;}
{
  ( s=pathname_element() <DOT_T> ) {s+=".";} (LOOKAHEAD(pathname_element() <DOT_T>) s1=pathname_element() <DOT_T> {s2+=s1;s2+="."; })*
  { return s+s2; }
}

QCString package_path_name():{QCString s;}
{
  <AT_T> s=name() { return "@"+s; }
}

QCString physical_literal() :  {QCString s,s1;}
{
 [LOOKAHEAD(abstract_literal()) s=abstract_literal()] s1=name(){s+=" ";s+=s1;s.prepend(" "); return s;}
}

QCString physical_type_definition() : {QCString s,s1,s2;Token *t=nullptr;}
{
        t=<UNITS_T>
            s=identifier()<SEMI_T> { outlineParser()->addVhdlType(s,t->beginLine,
                                                  EntryType::makeVariable(),VhdlSpecifier::UNITS,
                                                  QCString(),QCString(),Protection::Public);}
            (
             s1=secondary_unit_declaration()
            )*
            <END_T> <UNITS_T>  [name()]
            { return s;}

}

void physical_incomplete_type_definition() :  {}
{
  
    <UNITS_T> <BOX_T>
}

void port_clause() :  {}
{
   <PORT_T> <LPAREN_T>  port_list() <RPAREN_T>  <SEMI_T>{ m_sharedState->currP=VhdlSpecifier::UNKNOWN; }
}

QCString port_list() : {QCString s;}
{
  s=interface_list(){return s;}
}

void port_map_aspect() : {}
{
 <PORT_T> <MAP_T> <LPAREN_T> association_list() <RPAREN_T>
}

QCString primary() : {QCString s,s1;}
{
LOOKAHEAD(function_call())
s=function_call() { return s;}
|
LOOKAHEAD(<LPAREN_T> conditional_expression() <RPAREN_T>)
 <LPAREN_T> s1=conditional_expression() <RPAREN_T>{ s="("+s1+")"; return s;}
|
LOOKAHEAD(qualified_expression())
s=qualified_expression() { return s;}
|
LOOKAHEAD(type_conversion())
s=type_conversion() { return s;}
|
LOOKAHEAD(literal())
s=literal() { s.prepend(" ");return s;}
|
LOOKAHEAD(name())
s=name() { return s;}
|
LOOKAHEAD(allocator())
allocator() { return QCString();}
|
LOOKAHEAD(aggregate())
s=aggregate() { return s; }
//| <LPAREN_T> s=conditional_expression() <RPAREN_T> {return "("+s+")";}
}


void primary_unit() : {}
{
entity_declaration()
| configuration_declaration()
|
LOOKAHEAD(package_instantiation_declaration())
package_instantiation_declaration()
//|LOOKAHEAD(4)interface_package_declaration()
| package_declaration()
|  context_declaration()

}

QCString private_variable_declaration() : {QCString s,s1;}
{
  <PRIVATE_T> variable_declaration() {return "private";}
 }

QCString private_incomplete_type_definition() : {QCString s,s1;}
{
  <PRIVATE_T> {return "private";}
 }

QCString parameter_map_aspect() : {QCString s,s1;}
{
 // [ <PARAMETER_T> <MAP_T> ] <LPAREN_T>  association_list() <RPAREN_T>
   [ <PARAMETER_T> <MAP_T> ] <LPAREN_T> actual_parameter_part()  <RPAREN_T>
}

QCString procedure_call() : {QCString s,s1;}
{
 // name() [LOOKAHEAD(4) parameter_map_aspect()]/* [actual_parameter_part() ] */ { return "";}
  name() [ <PARAMETER_T> <MAP_T> ] [ LOOKAHEAD(1) <LPAREN_T> actual_parameter_part() <RPAREN_T> ]  { return "";}
 }

QCString procedure_call_statement() :  {QCString s,s1;}
{
[LOOKAHEAD(2) s=identifier() <COLON_T> { s+=":"; }] s1=procedure_call() <SEMI_T>
{
  return s+s1+";";
}
}

QCString procedure_specifiction() :  {QCString s,s1;}
{
<PROCEDURE_T> designator() [subprogram_header()] [[<PARAMETER_T> ] <LPAREN_T> formal_parameter_list() <RPAREN_T> ]
{return s+s1+";";}
}

QCString process_declarative_item() :  {QCString s;}
{
subprogram_declaration() { return QCString();}
| subprogram_body()
//| s=subprogram_instantiation_declaration() {return s;}
| LOOKAHEAD(2) package_body()       {return "";}
| LOOKAHEAD(package_declaration())package_declaration()  {return "";}
| package_instantiation_declaration() {return "";}
| s=subtype_declaration() { return s;}
| s=type_declaration() { return s;}
| s=constant_declaration() { return s;}
| s=variable_declaration() { return s;}
| s=file_declaration() { return s;}
| s=alias_declaration() { return s;}
|
LOOKAHEAD(3)
s=attribute_declaration() { return s;}
| s=attribute_specification() { return s;}
| s=use_clause() { return s;}
|
LOOKAHEAD(3)
s=group_template_declaration()  { return s;}
| s=group_declaration() { return s;}
}

QCString process_declarative_part() :{QCString s,s1;}
{
 ( s1=process_declarative_item(){s+=s1;} )* { return s;}
}

void process_statement() : {QCString s,s1,s2;Token *tok=nullptr;Token *tok1=nullptr;}
{
[ s=identifier() <COLON_T> ]
[ <POSTPONED_T> ] tok1=<PROCESS_T>
 {
	m_sharedState->currP=VhdlSpecifier::PROCESS;
    m_sharedState->current->startLine=tok1->beginLine;
    m_sharedState->current->bodyLine=tok1->beginLine;
 }

 [ <LPAREN_T>  (s1=sensitivity_list() ) <RPAREN_T>] [ LOOKAHEAD(1)<IS_T> ]
        s2=process_declarative_part()
             {
              if (!s2.isEmpty())
                FlowChart::addFlowChart(FlowChart::VARIABLE_NO,s2,QCString());
                FlowChart::addFlowChart(FlowChart::BEGIN_NO,"BEGIN",QCString());
              }
        <BEGIN_T>
        process_statement_part()
        <END_T> [ <POSTPONED_T> ]
         <PROCESS_T> [ identifier() ] <SEMI_T>
        {
          if(s.isEmpty())
            m_sharedState->currName=VhdlDocGen::getProcessNumber();
          else
            m_sharedState->currName=s;
          m_sharedState->current->name=m_sharedState->currName;
          m_sharedState->tempEntry=m_sharedState->current;
		  m_sharedState->tempEntry->type="";
          m_sharedState->current->endBodyLine=outlineParser()->getLine();
          m_sharedState->currP=VhdlSpecifier::UNKNOWN;
          if(tok!=nullptr)
            s1=tok->image;
          outlineParser()->createFunction(m_sharedState->currName,VhdlSpecifier::PROCESS,s1);
          outlineParser()->createFlow();
          m_sharedState->currName="";
          outlineParser()->newEntry();
        }
}

void process_statement_part() :  {}
{
  (sequential_statement())*
}


QCString protected_type_body() :{ }
{
  // try{
   <PROTECTED_T> <BODY_T>
          protected_type_body_declarative_part()

    //}catch(...){outlineParser()->error_skipto(END_T);}
    <END_T><PROTECTED_T> <BODY_T>   [identifier()]  {return QCString();}
}

void protected_type_body_declarative_item() :    { }
 {
    subprogram_declaration()
    | subprogram_body()
   // | subprogram_instantiation_declaration()
    | LOOKAHEAD(2) package_body()
    | LOOKAHEAD(package_declaration()) package_declaration()
    | package_instantiation_declaration()
    | type_declaration()
    | subtype_declaration()
    | constant_declaration()
    | variable_declaration()
    | file_declaration()
    | alias_declaration()
    |
      LOOKAHEAD( attribute_declaration())
      attribute_declaration()
    | attribute_specification()
    | use_clause()
    | LOOKAHEAD(3)
      group_template_declaration()
    | group_declaration()

}

void protected_type_body_declarative_part() :{  }
{
    ( protected_type_body_declarative_item ())*
}


QCString protected_type_declaration() : {  }
 {
   <PROTECTED_T>
        try{
          protected_type_header()
          protected_type_declarative_part()
        }catch(...){outlineParser()->error_skipto(END_T);}
       <END_T><PROTECTED_T> [ identifier() ] { return QCString();}
 }

void protected_type_header() :{  }
{
    [ generic_clause() [ generic_map_aspect()  ] ]
}

void protected_type_declarative_item():    { }
{
    LOOKAHEAD(subprogram_declaration() ) subprogram_declaration()
    | LOOKAHEAD(4) alias_declaration()
    | subprogram_instantiation_declaration()
    | attribute_specification()
    | private_variable_declaration()
    | use_clause()

}

void protected_type_declarative_part() :    {}
{
    (protected_type_declarative_item () )*
}


QCString qualified_expression() :  {QCString s,s1;Token *tok=nullptr;}
{
  // special case xxx'('1') | xxx'('Z')
  LOOKAHEAD(4) s1=identifier() <CHARACTER_LITERAL> tok=<LETTER_OR_DIGIT> <APOSTROPHE_T> <RPAREN_T> {return s1+"'('"+QCString(tok->image)+"')";}
  |
  s1=identifier() <APOSTROPHE_T> {s=s1+"'";}
  ( LOOKAHEAD(aggregate())
    s1=aggregate(){s+=s1;}
    | <LPAREN_T> s1=expression() <RPAREN_T>{s+="(";s+=s1;s+=")";}
 )
 {return s;}
}

QCString range() :  {QCString s,s1,s2;}
{
   LOOKAHEAD( simple_expression() direction() simple_expression())
   s=simple_expression() s1=direction() s2=simple_expression(){return s+" "+s1+" "+s2;}
  |
 LOOKAHEAD(attribute_name())
  s=attribute_name(){ return s;}
}

QCString range_constraint() :  {QCString s,s1;}
{
<RANGE_T> s=range(){return " range "+s;}
}

void record_type_definition() : {}
{
       <RECORD_T>
       (element_declaration())*
         <END_T>
       <RECORD_T> [ name()]
}

void record_constraint() : {}
{
     <LPAREN_T> record_element_constraint() ( <COMMA_T> record_element_constraint() )* <RPAREN_T>
}


void record_element_constraint() : {}
{
    identifier() element_constraint()
}

void record_element_list() : {}
{
    identifier() ( <COMMA_T> identifier() )*
}

void record_element_resolution() : {}
{
    identifier() resolution_indication()
}

void record_resolution() : {}
{
    record_element_resolution() ( <COMMA_T> record_element_resolution() )*
}

void record_mode_view_indication() : {}
{
   <VIEW_T> name() [<OF_T> subtype_indication() ]
}


QCString relation() :  {QCString s,s1,s2;}
{
  s=shift_expression() [LOOKAHEAD(1) s1=relation_operator() s2=shift_expression() ] {return s+s1+s2;}
}

QCString relative_pathname():{QCString s,s1,s2;}
{
  s=neg_list() [LOOKAHEAD( pathname_element_list()) s1=pathname_element_list() ] s2=identifier() { return s+s1+s2;}
}

QCString neg_list(): {QCString s;}
{
 (<NEG_T> <DOT_T>{s+="^.";})+     {return s; }
}

QCString relation_operator() :  {}
{
 <LT_T> {return "<";}
 |<GT_T> {return ">";}
 |<EQU_T> {return "=";}
 |<GREATERTHAN_T> {return ">=";}
 |<LESSTHAN_T> {return "<=";}
 |<NOTEQU_T> {return "/=";}
 |<QGT_T> { return "?>=";}
 |<QLT_T> { return "?<=";}
 |<QG_T> { return "?>";}
 |<QL_T> { return "?<";}
 |<QEQU_T> { return "?=";}
 |<QNEQU_T> {return "?/="; }


}

QCString report_statement() :  {Token *t=nullptr;Token *t1=nullptr;QCString s,s1,s2;}
{
[ s=identifier() t=<COLON_T> ]
    <REPORT_T> s1=expression()
        [ t1=<SEVERITY_T> s2=expression() ] <SEMI_T>
        {
        if(t!=nullptr) s.append(":");
        s1.prepend(" report ");
        if(t1!=nullptr) s2.prepend(" severity ");
        return s+s1+s2+";";
        }
}

QCString resolution_indication(): {QCString s;}
{
   s=identifier() { return s;}
  | <LPAREN_T> s=expression() <RPAREN_T> { return "("+s+")"; }
 }


QCString return_statement() :  {QCString s,s1;}
{
    LOOKAHEAD(plain_return_statement()) s=plain_return_statement() {return s;}
    | s=value_return_statement() {return s;}
}

QCString plain_return_statement() :  {QCString s,s1;}
{
[ s=identifier() <COLON_T> ] <RETURN_T> [LOOKAHEAD(1) <WHEN_T> condition() ] <SEMI_T> { return s;}
}

QCString value_return_statement() :  {QCString s,s1;}
{
[ s=identifier() <COLON_T> { s+=":";}] <RETURN_T> s1=conditional_or_unaffected_expression() <SEMI_T>
{ return s+" return "+s1+";";}
}


QCString scalar_type_definition() : {QCString s,s1;}
{
LOOKAHEAD(enumeration_type_definition())
s=enumeration_type_definition(){ return s;}
| s=range_constraint() [ s1=physical_type_definition()] { return s+" "+s1;}
}

void scalar_incomplete_type_definition() :  {}
{
  
    <BOX_T>
}

void secondary_unit() :  {}
{
architecture_body()
| package_body()
}

QCString secondary_unit_declaration() :  {QCString s,s1;Token *t1=nullptr;}
{
s=identifier() t1=<EQU_T> s1=physical_literal() <SEMI_T>
{
   outlineParser()->addVhdlType(s,t1->beginLine,
                                EntryType::makeVariable(),VhdlSpecifier::UNITS,
                                QCString(),s1,Protection::Public);  
   return s+"="+s1; }
}

QCString selected_name() : {QCString s,s1;}
{
 s=identifier() <DOT_T> s1=suffix(){ return s+"."+s1;}
}

void selected_signal_assignment() :  {}
{
  <WITH_T> expression() <SELECT_T>

    target() < LESSTHAN_T> options() selected_waveforms() <SEMI_T>
}

void selected_waveforms() :  {}
{
 waveform() <WHEN_T> choices()(<COMMA_T> waveform() <WHEN_T> choices())*
}

QCString sensitivity_clause() :  {QCString s;}
{
 <ON_T> s=sensitivity_list()
 {
  s.prepend(" on ");
  return s;
  }
}

void selected_signal_assignment_wave() : {}
{
  LOOKAHEAD(selected_force_assignment() )
  selected_force_assignment() |
  selected_waveform_assignment()
}

void selected_variable_assignment():{}
{
  <WITH_T> expression()
  <SELECT_T> [<Q_T>] select_name()
  <VARASSIGN_T> sel_var_list() // { $$=""; }
}

void select_name(): {}
{
  LOOKAHEAD(aggregate())
  aggregate() |
  name()
}

void selected_waveform_assignment():{}
{
  <WITH_T> expression()
  <SELECT_T> [<Q_T>] target()
  <LESSTHAN_T> [delay_mechanism()] sel_wave_list()
}

void selected_force_assignment():{}
{
  <WITH_T> expression() <SELECT_T> [<Q_T>] target() <LESSTHAN_T> <FORCE_T>
                                                  [ <IN_T> |<OUT_T>] sel_var_list()
}

void sel_var_list(): {}
{
  (expression() <WHEN_T> choices() (<COMMA_T>|<SEMI_T>))(LOOKAHEAD(expression() <WHEN_T>) expression() <WHEN_T> choices() (<COMMA_T>|<SEMI_T>))*
}


void sel_wave_list() : {}
{
   waveform_element() <WHEN_T> choices() (LOOKAHEAD(1) <COMMA_T> sel_wave_list())* <SEMI_T>
}


QCString sensitivity_list() :  {QCString s,s1;Token* tok=nullptr;}
{
  tok=<ALL_T> { if(tok!=nullptr) return "all" ;}
  | 
 s=name() (<COMMA_T> s1=name(){s+=",";s+=s1;} )* { return s;}
}

QCString sequence_of_statements() : {QCString s,s1;}
{
 ( LOOKAHEAD(3) s1=sequential_statement() {s+=s1;} )* { return s;}
}

QCString sequential_statement() :{QCString s;}
{
    LOOKAHEAD( [ identifier() ":" ] target() "<=")
    s=signal_assignment_statement(){FlowChart::addFlowChart(FlowChart::TEXT_NO,s,QCString());return s;}
    |
    LOOKAHEAD(3)
    s=assertion_statement(){FlowChart::addFlowChart(FlowChart::TEXT_NO,s,QCString());return s;}
    |
     LOOKAHEAD(3)
    s=report_statement(){FlowChart::addFlowChart(FlowChart::TEXT_NO,s,QCString());return s;}
    |
    LOOKAHEAD(3)
    s=wait_statement(){FlowChart::addFlowChart(FlowChart::TEXT_NO,s,QCString());return s;}
    |
    LOOKAHEAD(  [ identifier() ":" ] target() ":=" )
    s=variable_assignment_statement(){FlowChart::addFlowChart(FlowChart::TEXT_NO,s,QCString());return s;}
    |
    LOOKAHEAD(3)
    s=procedure_call_statement(){ FlowChart::addFlowChart(FlowChart::TEXT_NO,s,QCString());return s; }
    |
     LOOKAHEAD(3)
    if_statement(){return s;}
    |
     LOOKAHEAD(3)
    case_statement(){return s;}
    |
    LOOKAHEAD(3)
    loop_statement(){return s;}
    |
    LOOKAHEAD(3)
    s=next_statement() {return s;}
    |
    LOOKAHEAD(3)
    s=exit_statement(){return s;}
    |
    LOOKAHEAD(3)
    s=return_statement(){FlowChart::addFlowChart(FlowChart::RETURN_NO,s,QCString());return s;}
    |
    LOOKAHEAD(3)
     sequential_bock_statement() { return "";}
    |
    s=null_statement(){FlowChart::addFlowChart(FlowChart::TEXT_NO,s,QCString());return s;}

}

QCString sequential_bock_statement() :  {QCString s,s1,s2;}
{
LOOKAHEAD(6) [ label() <COLON_T> ] <BLOCK_T> [<IS_T>]  <BEGIN_T> sequential_block_statement_part() <END_T> [ <BLOCK_T> ] [ label() ] <SEMI_T> { return "";}
 |
 [ label() <COLON_T> ] <BLOCK_T> [LOOKAHEAD(1)<IS_T>] sequential_block_declarative_part() <BEGIN_T> sequential_block_statement_part() <END_T> [ <BLOCK_T> ] [ label() ] <SEMI_T> { return "";}
}

QCString sequential_block_declarative_part() :  {QCString s,s1,s2;}
{
 process_declarative_part() { return "";}
}

QCString sequential_block_statement_part() :  {QCString s,s1,s2;}
{
 (sequential_statement())* { return "";}
}

QCString sequential_statement_body() :  {QCString s,s1,s2;}
{
 [sequential_statement_declarative_part() <BEGIN_T> ] sequence_of_statements() { return "";}
}

QCString sequential_statement_declarative_part() :  {QCString s,s1,s2;}
{
 (process_declarative_item())* { return "";}
}




QCString shift_expression() :  {QCString s,s1,s2;}
{
 s=simple_expression() [ s1=shift_operator() s2=simple_expression() ] { return s+s1+s2;}
}
QCString shift_operator() :  {}
{
  <SLL_T> { return "sll";}
  | <SRL_T> { return "srl";}
  | <SLA_T> { return "sla";}
  | <SRA_T> { return "sra";}
  | <ROL_T> { return "rol";}
  | <ROR_T> { return "ror";}
}

QCString sign() :  {}
{
 <PLUS_T> { return "+";}
 | <MINUS_T> { return "-";}
}

QCString signal_assignment_statement() : {QCString s,s1,s2,s3;}
{

  LOOKAHEAD(conditional_signal_assignment_wave())
  conditional_signal_assignment_wave(){ return QCString(); }
|
  LOOKAHEAD(selected_signal_assignment_wave())
  selected_signal_assignment_wave() { return QCString(); }
  |
  [LOOKAHEAD(2) s=identifier() <COLON_T> {s+=":";} ]
s1=target() <LESSTHAN_T>
[ s2=delay_mechanism() ]
s3=waveform() <SEMI_T>
{
  return s+s1+"<="+s2+s3+";";
}

}


void signal_declaration() :  { Token* tok=nullptr;QCString s,s1,s2,s3,s4;}
{
<SIGNAL_T> s=identifier_list() <COLON_T> s1=subtype_indication() [ s2=signal_kind() ] [ tok=<VARASSIGN_T> s3=expression() ] <SEMI_T>
     {
     if(tok!=nullptr)
      s3.prepend(":=");
     s4=s1+s2+s3;
     outlineParser()->addVhdlType(s,outlineParser()->getLine(),
                                  EntryType::makeVariable(),VhdlSpecifier::SIGNAL,QCString(),s4,Protection::Public);
     }
}
QCString signal_kind() :  {}
{
  <REGISTER_T> { return "register";}
  | <BUS_T>  { return "bus";}
}

QCString signal_list() : {QCString s,s1;}
{
 s=name() (<COMMA_T>  s1=name() { s+=",";s+=s1;})*
| <OTHER_T> { return "other";}
| <ALL_T> { return "all";}
}


QCString simple_mode_indication() : {QCString s,s1;}
{
  [ mode() ] subtype_indication() interface_type_indication() [ <BUS_T> ] [ <VARASSIGN_T> expression()]
}



QCString signature() : {QCString s,s1,s2;}
{
<LBRACKET_T>
 [ s=name()  (<COMMA_T> s1=name() {s+=",";s+=s1; })* ]
 [ <RETURN_T> s1=name() {s+="return ";s+=s1;}]
  <RBRACKET_T>
  { s1="["+s+"]";return s1;}
 }

QCString simple_expression():  {QCString s,s1,s2;}
{
[ s=sign() ] s1=simpleTerm() {s+=s1;} ( LOOKAHEAD(adding_operator() simpleTerm()) s1=adding_operator() s2=simpleTerm() {s+=s1;s+=s2;})* { return s;}
}

void simple_name() :  {}
{
name()
}

QCString slice_name() :  {QCString s,s1;}
{
 s=identifier() <LPAREN_T> s1=discrete_range() <RPAREN_T> {return s+"("+s1+")";}
}

QCString string_literal() : {Token *tok=nullptr;}
{
tok=<STRINGLITERAL> {return QCString(tok->image);}
}


void subprogram_body() : {QCString s;}
{
//subprogram_specification()
<IS_T>

 s=subprogram_declarative_part()
   {
      if (!s.isEmpty())
      {
        FlowChart::addFlowChart(FlowChart::VARIABLE_NO,s,QCString());
      }
      FlowChart::addFlowChart(FlowChart::BEGIN_NO,"BEGIN",QCString());
    }
 
<BEGIN_T>
subprogram_statement_part()
<END_T> [ subprogram_kind() ] [ designator() ] <SEMI_T>
 {
      m_sharedState->tempEntry->endBodyLine=outlineParser()->getLine(END_T);
      outlineParser()->createFlow();
      m_sharedState->currP=VhdlSpecifier::UNKNOWN;
    }
}

void subprogram_declaration() :  {}
{
LOOKAHEAD(subprogram_instantiation_declaration())
subprogram_instantiation_declaration()
|
subprogram_specification() subprogram_1(){m_sharedState->currP=VhdlSpecifier::UNKNOWN;}
}

void subprogram_1() :  {}
{

 subprogram_body()
 | <SEMI_T>
}

QCString subprogram_declarative_item() : {QCString s;}
{
subprogram_declaration(){ return QCString();}
|s=type_declaration(){ return s;}
 | subprogram_body(){ return QCString();}
| s=subtype_declaration(){ return s;}
| s=constant_declaration(){ return s;}
| s=variable_declaration(){ return s;}
| s=file_declaration(){ return s;}
| s=alias_declaration(){ return s;}
|
LOOKAHEAD(attribute_declaration())
s=attribute_declaration(){ return s;}
| s=attribute_specification(){ return s;}
| s=use_clause(){ return s;}
|
LOOKAHEAD(3)
s=group_template_declaration(){ return s;}
| s=group_declaration() { return s;}
}

QCString subprogram_declarative_part() : {QCString s,s1;}
{
  (s1=subprogram_declarative_item(){s+=s1;})* { return s;}
}

void subprogram_kind() :  {}
{
 <FUNCTION_T>
 |<PROCEDURE_T>
}

void subprogram_header() :  {}
{
     <GENERIC_T> { m_sharedState->parse_sec=VhdlSection::GEN_SEC; } <LPAREN_T> generic_list() <RPAREN_T> { m_sharedState->parse_sec=VhdlSection::UNKNOWN; }[LOOKAHEAD(2) generic_map_aspect() ]
}

void subprogram_specification() : {QCString s;Token *tok=nullptr;Token *t;}
{
 <PROCEDURE_T> s=designator()
 {
   m_sharedState->currP=VhdlSpecifier::PROCEDURE;
   outlineParser()->createFunction(s,m_sharedState->currP,QCString());
   m_sharedState->tempEntry=m_sharedState->current;
   m_sharedState->current->startLine=outlineParser()->getLine(PROCEDURE_T);
   m_sharedState->current->bodyLine=outlineParser()->getLine(PROCEDURE_T);

 } [LOOKAHEAD(1) <LPAREN_T> { m_sharedState->param_sec=VhdlSection::PARAM_SEC; } interface_list() { m_sharedState->param_sec=VhdlSection::UNKNOWN; }<RPAREN_T> ]
   [LOOKAHEAD(2) gen_interface_list()]
   [ LOOKAHEAD(2) gen_assoc_list()]
   param()
 {  outlineParser()->newEntry(); }
 |
 [ (tok=<PURE_T> | tok=<IMPURE_T>) ] t=<FUNCTION_T> { m_sharedState->currP=VhdlSpecifier::FUNCTION;} s=designator() [subprogram_header()]
 {

   if (tok!=nullptr)
     outlineParser()->createFunction(tok->image,m_sharedState->currP,s);
   else
     outlineParser()->createFunction(QCString(),m_sharedState->currP,s);

   m_sharedState->tempEntry=m_sharedState->current;
   m_sharedState->current->startLine=outlineParser()->getLine(FUNCTION_T);
   m_sharedState->current->bodyLine=outlineParser()->getLine(FUNCTION_T);
 }
 [[<PARAMETER_T>]{ m_sharedState->param_sec=VhdlSection::PARAM_SEC; } <LPAREN_T> formal_parameter_list() <RPAREN_T> { m_sharedState->param_sec=VhdlSection::UNKNOWN; }]
    <RETURN_T> [ LOOKAHEAD(2)identifier() <OF_T> ] s=type_mark()
             {
                m_sharedState->tempEntry=m_sharedState->current;
                m_sharedState->current->type=s;
                outlineParser()->newEntry();
              }
}

void subprogram_statement_part() : {}
{
  (sequential_statement())*
}

QCString subprogram_instantiation_declaration():{QCString s,s1,s2;}
{
 <FUNCTION_T>  s=identifier() <IS_T> <NEW_T> s1=name()  [s2=signature()] [gen_assoc_list()] <SEMI_T>
    {
     QCString q= " is new "+s1+s2;
      outlineParser()->addVhdlType(s,outlineParser()->getLine(FUNCTION_T),
                                   EntryType::makeVariable(),VhdlSpecifier::INSTANTIATION,"function ",q,Protection::Public);
    return q;
    }
}

QCString subtype_declaration() :  {QCString s,s1;}
{
<SUBTYPE_T> s=identifier() <IS_T> s1=subtype_indication() <SEMI_T>
{
  outlineParser()->addVhdlType(s,outlineParser()->getLine(),
                               EntryType::makeVariable(),VhdlSpecifier::SUBTYPE,QCString(),s1,Protection::Public);
  return " subtype "+s+" is "+s1+";";
}
}


QCString subtype_indication() :  {QCString s,s1,s2;}
{
  [LOOKAHEAD(1)  <LPAREN_T> s=expression() <RPAREN_T> ]  (LOOKAHEAD(2) s1=name())+ [LOOKAHEAD(constraint() ) s2=constraint()]
 {return s+" "+s1+" "+s2;}
}

QCString suffix() :  { QCString s; }
{
LOOKAHEAD(name())
s=name() { return s;}
| s=character_literal() { return s;}
| s=operator_symbol(){ return s;}
| <ALL_T> {return " all ";}
}

QCString target() :  { QCString s; }
{
 s=name(){ return s;}
| s=aggregate() { return s;}
}

// use simpleTerm instead of term to prevent collision with function / macro in doxygen
QCString simpleTerm() : { QCString s,s1,s2; }
{
 s=factor() ( LOOKAHEAD(2) s1=multiplying_operation() s2=factor(){s+=s1;s+=s2;} )* { return s;}
}

QCString timeout_clause() : { QCString s; }
{
<FOR_T>  s=expression()
{
  return " for "+s;
}
}

QCString type_conversion() : {QCString s,s1;}
{
  s=name() <LPAREN_T> s1=expression() <RPAREN_T> { return s+"("+s1+")";}
}

QCString type_declaration() : {QCString s;}
{
LOOKAHEAD(3)
s=full_type_declaration(){ return s;}
| s=incomplete_type_declaration(){ return s;}
}

QCString type_definition() :  {QCString s;}
{
s=scalar_type_definition(){ return s;}
| s=composite_type_definition(){ return s;}
| s=access_type_definition(){ return s;}
| s=file_type_definition(){ return s;}
| protected_type_instantiation_definition() { return QCString(); }
|
 LOOKAHEAD(2)
 protected_type_body()            { return QCString(); }
| protected_type_declaration()     { return QCString(); }

}

void protected_type_instantiation_definition(): {QCString s; }
{
  <NEW_T> name() [ generic_map_aspect() ]
}


QCString type_mark() : {QCString s; }
{
  s=name() { return s;}
}

QCString unconstraint_array_definition() :  {QCString s,s1,s2,s3;}
{
<ARRAY_T> <LPAREN_T> s=index_subtype_definition() ( <COMMA_T> s1=index_subtype_definition(){s3+=",";s3+=s1;})* <RPAREN_T>
 <OF_T> s2=subtype_indication() {return "array("+s+s3+") of "+s2;}
}

 QCString use_clause() :  {QCString s,s1;}
{
 <USE_T> s=selected_name()(<COMMA_T> s1=selected_name(){s+=",";s+=s1;})*   <SEMI_T>
  {
                   auto ql1=split(s.str(),",");
                   for (const auto &name : ql1)
                   {
                     auto ql2=split(name,".");
                     if (ql2.size()>1)
                     {
                       std::string it=ql2[1];
                       if ( m_sharedState->parse_sec==VhdlSection::UNKNOWN && Config_getBool(SHOW_INCLUDE_FILES) )
                       {
                         outlineParser()->addVhdlType(it.c_str(),
                                                      outlineParser()->getLine(),
                                                      EntryType::makeVariable(),
                                                      VhdlSpecifier::USE,
                                                      it.c_str(),
                                                      "_use_",Protection::Public);
                       }
                     }
                   }
                   s1="use "+s;
                   return s1;
   }
}

QCString variable_assignment_statement() :  {QCString s,s1,s2;}
{
[LOOKAHEAD(2) s=identifier() <COLON_T> {s+=":";}]
 s1=target() <VARASSIGN_T> s2=conditional_or_unaffected_expression() <SEMI_T>
 {return s+s1+":="+s2+";";}
 |
 selected_variable_assignment() { return QCString();  }
}

QCString variable_declaration() :  {Token *tok=nullptr;Token *t1=nullptr;QCString s,s1,s2;}
{
[ tok=<SHARED_T> ] <VARIABLE_T> s=identifier_list()  <COLON_T> s1=subtype_indication() [ generic_map_aspect() ]

[ t1=<VARASSIGN_T> s2=conditional_expression() ] <SEMI_T>

{
  if(t1!=nullptr)
    s2.prepend(":=");
  QCString val=" variable "+s+":"+s1+s2+";";
  QCString it=s1;
  if(tok != nullptr)
  {
    it.prepend(" shared ");
    val.prepend(" shared");
  }
  VhdlSpecifier spec=VhdlSpecifier::SHAREDVARIABLE;

  if(t1 != nullptr)
  {
    it+=":=";
    it+=s2;
  }
  outlineParser()->addVhdlType(s,outlineParser()->getLine(),
                               EntryType::makeVariable(),spec,QCString(),it,Protection::Public);
  return val;
}

}

QCString wait_statement() :  {QCString s,s1,s2,s3;Token *t=nullptr;}
{
[ s=identifier() t=<COLON_T> ] <WAIT_T> [ s1=sensitivity_clause() ] [ s2=condition_clause() ] [ s3=timeout_clause() ] <SEMI_T>
{
  if(t!=nullptr) s.append(":");
  return s+" wait "+s1+s2+s3+";";
}
}

QCString waveform() :  {QCString s,s1;}
{
s=waveform_element() (LOOKAHEAD(1) <COMMA_T> s1=waveform_element(){s+=","; s+=s1;})* { return s;}
|
<UNAFFECTED_T> { return " unaffected ";}

}

QCString waveform_element() :  {QCString s,s1;}
{
 s=expression() [ <AFTER_T> s1=expression(){ s1.prepend(" after ");} ]
 { return s+s1;}

}


 // -----------------------------------------------------------------
 // needed for inline (function/process/procedure) parsing
 // -----------------------------------------------------------------

void parseInline() :  {}
{
  process_statement() |
  subprogram_declaration()
}
