c_pp_line.hpp

説明を見る。
00001 /*
00002  *  TOPPERS/FDMP Kernel
00003  *      Toyohashi Open Platform for Embedded Real-Time Systems/
00004  *      Function Distributed Multiprocessor Kernel
00005  *
00006  *  Copyright (C) 2005 by Takagi Nobuhisa  
00007  * 
00008  *  上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation 
00009  *  によって公表されている GNU General Public License の Version 2 に記
00010  *  述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
00011  *  を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
00012  *  利用と呼ぶ)することを無償で許諾する.
00013  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
00014  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
00015  *      スコード中に含まれていること.
00016  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
00017  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
00018  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
00019  *      の無保証規定を掲載すること.
00020  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
00021  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
00022  *      と.
00023  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
00024  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
00025  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
00026  *        報告すること.
00027  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
00028  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
00029  * 
00030  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
00031  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
00032  *  含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
00033  *  接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
00034  * 
00035  */
00036 
00041 #ifndef TOPPERS_C_PP_LINE_HPP_
00042 #define TOPPERS_C_PP_LINE_HPP_
00043 
00044 #include "toppers/text_line.hpp"
00045 #include "toppers/parser.hpp"
00046 #include <vector>
00047 #include <functional>
00048 #include <boost/shared_ptr.hpp>
00049 
00050 namespace toppers
00051 {
00052 
00053   namespace detail
00054   {
00055 
00056     struct c_pp_line_parser : boost::spirit::grammar<c_pp_line_parser>
00057     {
00058       template <class Scanner>
00059       struct definition
00060       {
00061         typedef boost::spirit::rule<Scanner> rule_t;
00062         rule_t r;
00063         definition( const c_pp_line_parser& self )
00064         {
00065           using namespace boost::spirit;
00066           r = (
00067                 '#' >> lexeme_d[ str_p( "line" ) >> space_p >> uint_p[ assign_a( self.line_ ) ] ] >>
00068                 c_strlit_parser( self.codeset_ )[ assign_a( self.file_ ) ]
00069               )
00070             | (
00071                 '#' >>
00072                 uint_p[ assign_a( self.line_ ) ] >>
00073                 c_strlit_parser( self.codeset_ )[ assign_a( self.file_ ) ] >>
00074                 *anychar_p
00075               );
00076         }
00077         const rule_t& start() const { return r; }
00078       };
00079 
00080       c_pp_line_parser( long& line, std::string& file, codeset_t codeset = ascii )
00081         : line_( line ), file_( file ), codeset_( codeset )
00082       {
00083       }
00084 
00085       long& line_;
00086       std::string& file_;
00087       codeset_t codeset_;
00088     };
00089 
00090     struct c_pp_pragma_parser : boost::spirit::grammar<c_pp_pragma_parser>
00091     {
00092       template <class Scanner>
00093       struct definition
00094       {
00095         typedef boost::spirit::rule<Scanner> rule_t;
00096         rule_t r;
00097         definition( const c_pp_pragma_parser& self )
00098         {
00099           using namespace boost::spirit;
00100           r = '#' >> lexeme_d[ str_p( "pragma" ) >> space_p >> ( +anychar_p )[ assign_a( self.parameter_ ) ] ];
00101         }
00102         const rule_t& start() const { return r; }
00103       };
00104 
00105       c_pp_pragma_parser( std::string& parameter ) : parameter_( parameter )
00106       {
00107       }
00108       std::string& parameter_;
00109     };
00110 
00111   }
00112 
00119   template <class Container>
00120   class c_pp_line : public std::binary_function<Container, line_buf, void>
00121   {
00122   public:
00123     typedef Container conatiner;
00124 
00129     explicit c_pp_line( codeset_t codeset = ascii )
00130       : codeset_( codeset ), pragmas_( new std::vector<line_buf> )
00131     {
00132     }
00138     void operator()( conatiner& cont, line_buf& buf )
00139     {
00140       using namespace boost::spirit;
00141       long line;
00142       std::string file;
00143       detail::c_pp_line_parser c_pp_line_p( line, file, codeset_ );
00144 
00145       if ( parse( buf.buf_.begin(), buf.buf_.end(), c_pp_line_p, space_p ).full ) // #line指令の処理
00146       {
00147         using namespace boost::filesystem;
00148         buf.line_.line_ = line;
00149         assert( file.size() >= 2 );
00150         try
00151         {
00152           std::string file_name( file.substr( 1, file.size()-2 ) );
00153           buf.line_.file_ = path( file_name, native );
00154         }
00155         catch ( ... )
00156         {
00157           // GNUのプリプロセッサはファイル名に相当する部分が<built-n>や<command line>
00158           // となる場合があるため、例外が発生する可能性あり
00159           buf.line_.file_ = path( "unknown", native );
00160         }
00161       }
00162       else
00163       {
00164         std::string param;
00165         detail::c_pp_pragma_parser c_pp_pragma_p( param );
00166 
00167         if ( parse( buf.buf_.begin(), buf.buf_.end(), c_pp_pragma_p, space_p ).full ) // #pragma指令の処理
00168         {
00169           line_buf t( buf );
00170           t.buf_ = param;
00171           pragmas_->push_back( t );
00172         }
00173         else
00174         {
00175           std::string::size_type pos = buf.buf_.find_first_not_of( " \t" );
00176           if ( pos == std::string::npos || buf.buf_[pos] != '#' )
00177           {
00178             cont.push_back( buf );
00179           }
00180           ++buf.line_.line_;
00181         }
00182       }
00183       buf.buf_.clear();
00184     }
00189     const std::vector<line_buf>& pragmas() const { return *pragmas_; }
00190   private:
00191     codeset_t codeset_;
00192     boost::shared_ptr<std::vector<line_buf> > pragmas_;
00193   };
00194 
00195 }
00196 
00197 #endif  // ! TOPPERS_C_PP_LINE_HPP_

Copyright © 2006 by TAKAGI Nobuhisa.
このページは Wed Apr 12 16:31:55 2006 に Doxygen によって生成されました。