LCOV - code coverage report
Current view: top level - spb-proto-compiler/parser - char_stream.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 82.5 % 63 52
Test Date: 2025-05-23 14:18:14 Functions: 80.0 % 15 12

            Line data    Source code
       1              : /***************************************************************************\
       2              : * Name        : input stream                                                *
       3              : * Description : char stream used for parsing proto files                    *
       4              : * Author      : antonin.kriz@gmail.com                                      *
       5              : * ------------------------------------------------------------------------- *
       6              : * This is free software; you can redistribute it and/or modify it under the *
       7              : * terms of the MIT license. A copy of the license can be found in the file  *
       8              : * "LICENSE" at the root of this distribution.                               *
       9              : \***************************************************************************/
      10              : 
      11              : #pragma once
      12              : #include <algorithm>
      13              : #include <cassert>
      14              : #include <cctype>
      15              : #include <stdexcept>
      16              : #include <string>
      17              : #include <string_view>
      18              : 
      19              : namespace spb
      20              : {
      21              : 
      22              : struct char_stream
      23              : {
      24              : private:
      25              :     //- start of the stream
      26              :     const char * p_start = nullptr;
      27              :     //- current position in the stream
      28              :     const char * p_begin = nullptr;
      29              :     //- end of the stream
      30              :     const char * p_end = nullptr;
      31              :     //- current char
      32              :     char m_current = { };
      33              : 
      34              :     /**
      35              :      * @brief gets the next char from the stream
      36              :      *
      37              :      * @param skip_white_space if true, skip white spaces
      38              :      */
      39        63413 :     void update_current( bool skip_white_space ) noexcept
      40              :     {
      41        90582 :         while( p_begin < p_end )
      42              :         {
      43        90568 :             m_current = *p_begin;
      44        90568 :             if( !skip_white_space || isspace( m_current ) == 0 )
      45              :             {
      46        63399 :                 return;
      47              :             }
      48        27169 :             p_begin += 1;
      49              :         }
      50           14 :         m_current = { };
      51              :     }
      52              : 
      53              : public:
      54           14 :     explicit char_stream( std::string_view content ) noexcept
      55           14 :         : p_start( content.data( ) )
      56           14 :         , p_begin( p_start )
      57           14 :         , p_end( p_begin + content.size( ) )
      58              :     {
      59           14 :         update_current( true );
      60           14 :     }
      61              : 
      62        95790 :     [[nodiscard]] auto begin( ) const noexcept -> const char *
      63              :     {
      64        95790 :         return p_begin;
      65              :     }
      66              : 
      67        70464 :     [[nodiscard]] auto end( ) const noexcept -> const char *
      68              :     {
      69        70464 :         return p_end;
      70              :     }
      71              : 
      72          420 :     [[nodiscard]] auto empty( ) const noexcept -> bool
      73              :     {
      74          420 :         return p_end <= p_begin;
      75              :     }
      76              : 
      77        75318 :     [[nodiscard]] auto current_char( ) const noexcept -> char
      78              :     {
      79        75318 :         return m_current;
      80              :     }
      81              : 
      82              :     /**
      83              :      * @brief consumes `current char` if its equal to c
      84              :      *
      85              :      * @param c consumed char
      86              :      * @return true if char was consumed
      87              :      */
      88        13778 :     [[nodiscard]] auto consume( char c ) noexcept -> bool
      89              :     {
      90        13778 :         if( auto current = current_char( ); current == c )
      91              :         {
      92         3798 :             consume_current_char( true );
      93         3798 :             return true;
      94              :         }
      95         9980 :         return false;
      96              :     }
      97              : 
      98              :     /**
      99              :      * @brief consumes an `token`
     100              :      *
     101              :      * @param token consumed `token` (whole word)
     102              :      * @return true if `token` was consumed
     103              :      */
     104        13384 :     auto consume( std::string_view token ) noexcept -> bool
     105              :     {
     106        13384 :         const auto state = *this;
     107              : 
     108        13384 :         if( content( ).starts_with( token ) )
     109              :         {
     110         2739 :             p_begin += token.size( );
     111         2739 :             update_current( false );
     112         2739 :             auto next = current_char( );
     113         2739 :             if( isspace( next ) || !isalnum( next ) )
     114              :             {
     115         2038 :                 update_current( true );
     116         2038 :                 return true;
     117              :             }
     118          701 :             *this = state;
     119              :         }
     120        11346 :         return false;
     121              :     }
     122              : 
     123        48349 :     void consume_current_char( bool skip_white_space ) noexcept
     124              :     {
     125        48349 :         if( begin( ) < end( ) )
     126              :         {
     127        48349 :             p_begin += 1;
     128        48349 :             update_current( skip_white_space );
     129              :         }
     130        48349 :     }
     131              : 
     132              :     /**
     133              :      * @brief trim current spaces
     134              :      *
     135              :      */
     136         5839 :     void consume_space( ) noexcept
     137              :     {
     138         5839 :         update_current( true );
     139         5839 :     }
     140              : 
     141         4434 :     void skip_to( const char * ptr ) noexcept
     142              :     {
     143         4434 :         assert( ptr >= p_start && ptr <= end( ) );
     144         4434 :         p_begin = ptr;
     145         4434 :         update_current( true );
     146         4434 :     }
     147              : 
     148        15983 :     [[nodiscard]] auto content( ) const noexcept -> std::string_view
     149              :     {
     150        15983 :         return { begin( ), size_t( end( ) - begin( ) ) };
     151              :     }
     152              : 
     153            0 :     [[nodiscard]] auto current_line( ) const noexcept -> size_t
     154              :     {
     155            0 :         return std::count( p_start, p_begin, '\n' ) + 1;
     156              :     }
     157            0 :     [[nodiscard]] auto current_column( ) const noexcept -> size_t
     158              :     {
     159            0 :         auto parsed = std::string_view( p_start, p_begin - p_start );
     160              : 
     161            0 :         if( auto p = parsed.rfind( '\n' ); p != std::string_view::npos )
     162              :         {
     163            0 :             parsed.remove_prefix( p );
     164              :         }
     165            0 :         return std::max< size_t >( parsed.size( ), 1 );
     166              :     }
     167            0 :     [[noreturn]] void throw_parse_error( std::string_view message )
     168              :     {
     169            0 :         throw std::runtime_error( std::to_string( current_line( ) ) + ":" +
     170            0 :                                   std::to_string( current_column( ) ) + ": " +
     171            0 :                                   std::string( message ) );
     172              :     }
     173              : };
     174              : }// namespace spb
        

Generated by: LCOV version 2.0-1