Classifying ----------- The Classifying process takes the output of the tokenize process along with the defined tokens and applies the rules in the VHDL LRM. The process employs a recursive methodology to apply the rules. The rules are divided into python modules under the :code:`vsg/vhdlFile/classify` directory. Each module name under :code:`vsg/vhdlFile/classify` matches a VHDL production name. Each module provides functions to parse a VHDL production and will have at least one of the following functions: * :code:`detect` * :code:`classify` * :code:`classify_until` detect ====== The :code:`detect` function checks if a production exists. It will typically call the :code:`classify` function if the production is detected. classify ======== The :code:`classify` function takes each token in the tokenized list and assigns a corresponding token from the token classes. classify_until ============== The :code:`classify_until` function performs the same function as classify except it stops when it detects a particular token value. The token value can be a special character like a close parenthesis or a colon, or a known word. Example ======= Given the following production for the architecture_body: .. code-block:: text architecture_body ::= architecture identifier of *entity*_name is architecture_declarative_part begin architecture_statement_part end [ architecture ] [ *architecture*_simple_name ] ; There is a classifier file named :code:`vsg/vhdlFile/classify/architecture_body.py`. This file has a detect function: .. code-block:: python def detect(iToken, lObjects): ''' architecture identifier of *entity*_name is architecture_declarative_part begin architecture_statement_part end [ architecture ] [ *architecture*_simple_name ] ; ''' if utils.is_next_token('architecture', iToken, lObjects): return classify(iToken, lObjects) return iToken The detect function searches for the keyword :code:`architecture` in the token list. If this keyword is found then it calls the :code:`classify` function. The :code:`classify` function: .. code-block:: python def classify(iToken, lObjects): iCurrent = classify_opening_declaration(iToken, lObjects) iCurrent = architecture_declarative_part.detect(iCurrent, lObjects) iCurrent = utils.assign_next_token_required('begin', token.begin_keyword, iCurrent, lObjects) iCurrent = architecture_statement_part.classify_until(['end'], iCurrent, lObjects) iCurrent = classify_closing_declaration(iToken, lObjects) return iCurrent includes two helper functions :code:`classify_opening_declaration` and :code:`classify_closing_declaration`: .. code-block:: python def classify_opening_declaration(iToken, lObjects): iCurrent = utils.assign_next_token_required('architecture', token.architecture_keyword, iToken, lObjects) iCurrent = utils.assign_next_token(token.identifier, iCurrent, lObjects) iCurrent = utils.assign_next_token_required('of', token.of_keyword, iCurrent, lObjects) iCurrent = utils.assign_next_token(token.entity_name, iCurrent, lObjects) iCurrent = utils.assign_next_token_required('is', token.is_keyword, iCurrent, lObjects) return iCurrent .. code-block:: python def classify_closing_declaration(iToken, lObjects): iCurrent = utils.assign_next_token_required('end', token.end_keyword, iToken, lObjects) iCurrent = utils.assign_next_token_if('architecture', token.end_architecture_keyword, iCurrent, lObjects) iCurrent = utils.assign_next_token_if_not(';', token.architecture_simple_name, iCurrent, lObjects) iCurrent = utils.assign_next_token_required(';', token.semicolon, iCurrent, lObjects) return iCurrent The classification of the opening portion of the production, from :code:`architecture` to :code:`is`, is handled by the :code:`classify_opening_declaration` function. After the :code:`is` keyword, the detect function of the :code:`architecture_declarative_part` is called to check if there is anything in that production. If there are no more items in the :code:`architecture_declarative_part`, then the :code:`begin` keyword is classified. After the :code:`begin` keyword, the detect function of the :code:`architecture_statement_part` is called to check if there is anything in that production. If there are no more items in the :code:`architecture_statement_part`, then the closing portion of the production, from :code:`end` to the semicolon, is handled by the :code:`classify_closing_declaration` function. The recursive nature is implemented by calling other productions and then those productions returning to the caller.