/***************************************************************
         * Function: rule
         * Description: Recursive descent regular expression parser.
         **************************************************************/
        private CNfa rule
        (
        )
        {
            CNfaPair pair;
            //CNfa p;
            CNfa start  = null;
            CNfa end    = null;
            int  anchor = CSpec.NONE;

            if (CUtility.DESCENT_DEBUG)
            {
                CUtility.enter("rule", m_spec.m_lexeme, m_spec.m_current_token);
            }

            pair = CAlloc.newCNfaPair();

            if (CLexGen.AT_BOL == m_spec.m_current_token)
            {
                anchor = anchor | CSpec.START;
                m_lexGen.advance();
                expr(pair);

                // CSA: fixed beginning-of-line operator. 8-aug-1999
                start        = CAlloc.newCNfa(m_spec);
                start.m_edge = m_spec.BOL;
                start.m_next = pair.m_start;
                end          = pair.m_end;
            }
            else
            {
                expr(pair);
                start = pair.m_start;
                end   = pair.m_end;
            }

            if (CLexGen.AT_EOL == m_spec.m_current_token)
            {
                m_lexGen.advance();
                // CSA: fixed end-of-line operator. 8-aug-1999
                CNfaPair nlpair = CAlloc.newNLPair(m_spec);
                end.m_next                = CAlloc.newCNfa(m_spec);
                end.m_next.m_next         = nlpair.m_start;
                end.m_next.m_next2        = CAlloc.newCNfa(m_spec);
                end.m_next.m_next2.m_edge = m_spec.EOF;
                end.m_next.m_next2.m_next = nlpair.m_end;
                end    = nlpair.m_end;
                anchor = anchor | CSpec.END;
            }

            /* Check for null rules. Charles Fischer found this bug. [CSA] */
            if (end == null)
            {
                CError.parse_error(CError.E_ZERO, m_input.m_line_number);
            }

            /* Handle end of regular expression.  See page 103. */
            end.m_accept = m_lexGen.packAccept();
            end.m_anchor = anchor;

            /* Begin: Removed for states. */
            /*m_lexGen.advance();*/
            /* End: Removed for states. */

            if (CUtility.DESCENT_DEBUG)
            {
                CUtility.leave("rule", m_spec.m_lexeme, m_spec.m_current_token);
            }

            return(start);
        }