source: cfg_itronx+oil_gcc/toppers/c_parser.hpp

Last change on this file was 54, checked in by ertl-ishikawa, 12 years ago

cfg+oil対応コンフィギュレータを追加

File size: 20.0 KB
Line 
1/*
2 * TOPPERS Software
3 * Toyohashi Open Platform for Embedded Real-Time Systems
4 *
5 * Copyright (C) 2005-2010 by TAKAGI Nobuhisa
6 *
7 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
8 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
9 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
10 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
11 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
12 * スコード中に含まれていること.
13 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
14 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
15 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
16 * の無保証規定を掲載すること.
17 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
18 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
19 * と.
20 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
21 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
22 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
23 * 報告すること.
24 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
25 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
26 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
27 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
28 * 免責すること.
29 *
30 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
31 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
32 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
33 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
34 * の責任を負わない.
35 *
36 */
37
38/*!
39 * \file toppers/c_parser.hpp
40 * \brief 一般的なパーサーの宣言定義
41 */
42#ifndef TOPPERS_PARSER_HPP_
43#define TOPPERS_PARSER_HPP_
44
45#include "toppers/codeset.hpp"
46#include <boost/spirit/include/classic_core.hpp>
47#include <boost/spirit/include/classic_actor.hpp>
48#include <boost/spirit/include/classic_utility.hpp>
49#include <boost/spirit/include/classic_dynamic.hpp>
50
51namespace toppers
52{
53
54 namespace detail
55 {
56
57 struct c_integer_suffix_parse_functor
58 {
59 typedef boost::spirit::classic::nil_t result_t;
60 template < class Scanner >
61 int operator()( Scanner scan, result_t& ) const
62 {
63 using namespace boost::spirit::classic;
64 int length =
65 as_lower_d
66 [
67 ch_p( 'u' ) >> !( str_p( "ll" ) | 'l' | "i8" | "i16" | "i32" | "i64" )
68 | ( str_p( "ll" ) | 'l' | "i8" | "i16" | "i32" | "i64" ) >> !ch_p( 'u' )
69 ].parse( scan ).length();
70 return length;
71 }
72 };
73
74 template < typename T >
75 struct c_integer_constant_parse_functor
76 {
77 typedef T result_t;
78 template < class Scanner >
79 int operator()( Scanner scan, result_t& result ) const
80 {
81 using namespace boost::spirit::classic;
82 result_t x = T( 0 );
83 int length =
84 (
85 if_p( '0' ) // 16進または8進
86 [
87 !(
88 ( ch_p( 'x' ) | 'X' ) >> uint_parser< T, 16 >()[ assign_a( x ) ]
89 | uint_parser< T, 8 >()[ assign_a( x ) ]
90 )
91 ]
92 .else_p // 10進
93 [
94 uint_parser< T, 10 >()[ assign_a( x ) ]
95 ]
96 ).parse( scan ).length();
97 result = x;
98 return length;
99 }
100 };
101
102 template < typename T >
103 struct c_integer_parse_functor
104 {
105 typedef T result_t;
106 template < class Scanner >
107 int operator()( Scanner scan, result_t& result ) const
108 {
109 using namespace boost::spirit::classic;
110 static functor_parser< c_integer_constant_parse_functor< T > > const c_int_const_p;
111 static functor_parser< c_integer_suffix_parse_functor > const c_int_suffix_p;
112 bool negative = false;
113 result_t x;
114 int length =
115 (
116 !sign_p[ assign_a( negative ) ] >> lexeme_d[ c_int_const_p[ assign_a( x ) ] >> !c_int_suffix_p ]
117 ).parse( scan ).length();
118 result = ( negative ? -x : x );
119 return length;
120 }
121 };
122
123 template < int CodeSet = -1 > struct mbchar_parse_functor;
124
125 template <>
126 struct mbchar_parse_functor< ascii >
127 {
128 typedef boost::spirit::classic::nil_t result_t;
129 template < class Scanner >
130 int operator()( Scanner scan, result_t& ) const
131 {
132 return boost::spirit::classic::range_p( '\x01', '\x7f' ).parse( scan ).length();
133 }
134 };
135
136 template <>
137 struct mbchar_parse_functor< shift_jis >
138 {
139 typedef boost::spirit::classic::nil_t result_t;
140 template < class Scanner >
141 int operator()( Scanner scan, result_t& ) const
142 {
143 using namespace boost::spirit::classic;
144 int length =
145 (
146 range_p( '\x01', '\x7f' ) // 半角英数字記号
147 | range_p( '\xa1', '\xdf' ) // 半角カタカナ
148 | ( chset<>( "\x81-\x9f\xe0-\xef" ) >> chset<>( "\x40-\x7e\x80-\xfc" ) ) // 全角
149 ).parse( scan ).length();
150 return length;
151 }
152 };
153
154 template <>
155 struct mbchar_parse_functor< euc_jp >
156 {
157 typedef boost::spirit::classic::nil_t result_t;
158 template < class Scanner >
159 int operator()( Scanner scan, result_t& ) const
160 {
161 using namespace boost::spirit::classic;
162 int length =
163 (
164 range_p( '\x01', '\x7f' ) // 半角英数字記号
165 | ( ch_p( '\x8e' ) >> range_p( '\xa1', '\xdf' ) ) // 半角カタカナ
166 | ( !ch_p( '\x8f' ) >> range_p( '\xa1', '\xf0' ) >> range_p( '\xa1', '\xf0' ) ) // 全角
167 ).parse( scan ).length();
168 return length;
169 }
170 };
171
172 template <>
173 struct mbchar_parse_functor< utf8 >
174 {
175 typedef boost::spirit::classic::nil_t result_t;
176 template < class Scanner >
177 int operator()( Scanner scan, result_t& ) const
178 {
179 using namespace boost::spirit::classic;
180 int length =
181 (
182 range_p( '\x01', '\x7f' ) // 1バイト
183 | ( range_p( '\xc0', '\xdf' ) >> range_p( '\x80', '\xbf' ) ) // 2バイト
184 | ( range_p( '\xe0', '\xef' ) >> repeat_p( 2 )[ range_p( '\x80', '\xbf' ) ] ) // 3バイト
185 | ( range_p( '\xf0', '\xf7' ) >> repeat_p( 3 )[ range_p( '\x80', '\xbf' ) ] ) // 4バイト
186 | ( range_p( '\xf8', '\xfb' ) >> repeat_p( 4 )[ range_p( '\x80', '\xbf' ) ] ) // 5バイト
187 | ( range_p( '\xfc', '\xfd' ) >> repeat_p( 5 )[ range_p( '\x80', '\xbf' ) ] ) // 6バイト
188 ).parse( scan ).length();
189 return length;
190 }
191 };
192
193 template <>
194 struct mbchar_parse_functor< -1 >
195 {
196 typedef boost::spirit::classic::nil_t result_t;
197 explicit mbchar_parse_functor( codeset_t codeset = ascii ) : codeset_( codeset ) {}
198 template < class Scanner >
199 int operator()( Scanner scan, result_t& result ) const
200 {
201 int length;
202 switch ( codeset_ )
203 {
204 case ascii:
205 {
206 static mbchar_parse_functor< ascii > f;
207 length = f( scan, result );
208 }
209 break;
210 case shift_jis:
211 {
212 static mbchar_parse_functor< shift_jis > f;
213 length = f( scan, result );
214 }
215 break;
216 case euc_jp:
217 {
218 static mbchar_parse_functor< euc_jp > f;
219 length = f( scan, result );
220 }
221 break;
222 case utf8:
223 {
224 static mbchar_parse_functor< utf8 > f;
225 length = f( scan, result );
226 }
227 break;
228 default:
229 length = -1;
230 break;
231 }
232 return length;
233 }
234 codeset_t codeset_;
235 };
236
237 struct ucn_parse_functor
238 {
239 typedef long result_t;
240 template < class Scanner >
241 int operator()( Scanner scan, result_t& result ) const
242 {
243 using namespace boost::spirit::classic;
244 result_t x;
245 int length =
246 (
247 lexeme_d
248 [
249 ch_p( '\\' ) >>
250 (
251 ( 'U' >> int_parser< long, 16, 8, 8 >()[ assign_a( x ) ] ) // \Uhhhhhhhh形式
252 | ( 'u' >> int_parser< long, 16, 4, 4 >()[ assign_a( x ) ] ) // \uhhhh形式
253 )
254 ]
255 ).parse( scan ).length();
256 if ( ( x < 0xa0 && !( x == 0x24 || x == 0x40 || x == 0x60 ) )
257 || ( 0xd800 <= x && x <= 0xdfff )
258 || 0x10ffff < x ) // 国際文字名に使えない値(JIS X3010:2003 6.4.3)
259 {
260 x = -1;
261 }
262 result = x;
263 return length;
264 }
265 };
266
267 template < int CodeSet = -1 > struct c_strlit_parse_functor;
268
269 template < int CodeSet >
270 struct c_strlit_parse_functor
271 {
272 typedef boost::spirit::classic::nil_t result_t;
273 template < class Scanner >
274 int operator()( Scanner scan, result_t& result ) const
275 {
276 using namespace boost::spirit::classic;
277 static functor_parser< detail::mbchar_parse_functor< CodeSet > > const mbchar_p;
278 static functor_parser< detail::ucn_parse_functor > const ucn_p;
279 int length =
280 (
281 confix_p( '\"', *( "\\\"" | mbchar_p - '\\' | ucn_p | c_escape_ch_p ), '\"' )
282 ).parse( scan ).length();
283 return length;
284 }
285 };
286
287 template <>
288 struct c_strlit_parse_functor< -1 >
289 {
290 typedef boost::spirit::classic::nil_t result_t;
291 explicit c_strlit_parse_functor( codeset_t codeset = ascii ) : codeset_( codeset ) {}
292 template < class Scanner >
293 int operator()( Scanner scan, result_t& result ) const
294 {
295 using namespace boost::spirit::classic;
296 mbchar_parse_functor<> const functor( codeset_ );
297 functor_parser< detail::mbchar_parse_functor<> > const mbchar_p( functor );
298 static functor_parser< detail::ucn_parse_functor > const ucn_p;
299 int length =
300 (
301 confix_p( '\"', *( "\\\"" | ( mbchar_p - ch_p( '\\' ) ) | ucn_p | c_escape_ch_p ), '\"' )
302 ).parse( scan ).length();
303 return length;
304 }
305 codeset_t codeset_;
306 };
307
308 template < int CodeSet = -1 > struct c_chlit_parse_functor;
309
310 template < int CodeSet >
311 struct c_chlit_parse_functor
312 {
313 typedef boost::spirit::classic::nil_t result_t;
314 template < class Scanner >
315 int operator()( Scanner scan, result_t& result ) const
316 {
317 using namespace boost::spirit::classic;
318 static functor_parser< detail::mbchar_parse_functor< CodeSet > > const mbchar_p;
319 static functor_parser< detail::ucn_parse_functor > const ucn_p;
320 int length =
321 (
322 confix_p( '\'', +( "\\\'" | mbchar_p - '\\' | ucn_p | c_escape_ch_p ), '\'' )
323 ).parse( scan ).length();
324 return length;
325 }
326 };
327
328 template <>
329 struct c_chlit_parse_functor< -1 >
330 {
331 typedef boost::spirit::classic::nil_t result_t;
332 explicit c_chlit_parse_functor( codeset_t codeset = ascii ) : codeset_( codeset ) {}
333 template < class Scanner >
334 int operator()( Scanner scan, result_t& result ) const
335 {
336 using namespace boost::spirit::classic;
337 mbchar_parse_functor<> const functor( codeset_ );
338 functor_parser< detail::mbchar_parse_functor<> > const mbchar_p( functor );
339 static functor_parser< detail::ucn_parse_functor > const ucn_p;
340 int length =
341 (
342 confix_p( '\'', +( "\\\'" | mbchar_p - '\\' | ucn_p | c_escape_ch_p ), '\'' )
343 ).parse( scan ).length();
344 return length;
345 }
346 codeset_t codeset_;
347 };
348
349 extern char const* const c_keywords[];
350 extern char const* const c_plus_plus_keywords[];
351
352 struct c_identifier_parse_functor
353 {
354 typedef boost::spirit::classic::nil_t result_t;
355 template < class Scanner >
356 int operator()( Scanner scan, result_t& result ) const
357 {
358 using namespace boost::spirit::classic;
359 static functor_parser< detail::ucn_parse_functor > const ucn_p;
360 int length;
361 typename Scanner::iterator_t const first( scan.first );
362
363 if ( ucn_ )
364 {
365 length =
366 (
367 lexeme_d
368 [
369 ( alpha_p | '_' | ucn_p ) >>
370 *( alnum_p | '_' | ucn_p )
371 ]
372 ).parse( scan ).length();
373 }
374 else
375 {
376 length =
377 (
378 lexeme_d
379 [
380 ( alpha_p | '_' ) >>
381 *( alnum_p | '_' )
382 ]
383 ).parse( scan ).length();
384 }
385 std::string token( first, scan.first );
386
387 for ( int i = 0; c_keywords[i] != 0; i++ )
388 {
389 if ( token == c_keywords[i] )
390 {
391 length = -1;
392 break;
393 }
394 }
395 if ( c_plus_plus_ )
396 {
397 for ( int i = 0; c_plus_plus_keywords[i] != 0; i++ )
398 {
399 if ( token == c_plus_plus_keywords[i] )
400 {
401 length = -1;
402 break;
403 }
404 }
405 }
406 return length;
407 }
408 explicit c_identifier_parse_functor( bool ucn = false, bool c_plus_plus = false )
409 : ucn_( ucn ), c_plus_plus_( c_plus_plus )
410 {
411 }
412
413 bool ucn_;
414 bool c_plus_plus_;
415 };
416
417 }
418
419 /*!
420 * \brief C言語形式の整数定数パーサー
421 *
422 * boost::spirit::int_parserとの違いは、接頭辞に応じて8進数や16進数として解釈
423 * する点です。また型を特定するための接尾辞も受け入れます。
424 */
425 template < typename T >
426 inline boost::spirit::classic::functor_parser< detail::c_integer_parse_functor< T > > const c_int_parser()
427 {
428 return boost::spirit::classic::functor_parser< detail::c_integer_parse_functor< T > >();
429 }
430
431 extern boost::spirit::classic::functor_parser< detail::c_integer_parse_functor< int > > const c_int_p;
432 extern boost::spirit::classic::functor_parser< detail::c_integer_parse_functor< unsigned int > > const c_uint_p;
433
434 /*!
435 * \brief マルチバイト文字パーサー
436 *
437 * テンプレート引数 CodeSet で指定した文字コードを解析します。
438 * ascii 以外を指定した場合でも、ASCIIの範囲(0x7f以下)にも合致します。
439 * 0x00 は文字列の終端と区別できないため、合致対象にはなりません。
440 */
441 template < int CodeSet >
442 inline boost::spirit::classic::functor_parser< detail::mbchar_parse_functor< CodeSet > > const mbchar_parser()
443 {
444 return boost::spirit::classic::functor_parser< detail::mbchar_parse_functor< CodeSet > >();
445 }
446 inline boost::spirit::classic::functor_parser< detail::mbchar_parse_functor<> > const mbchar_parser( codeset_t codeset )
447 {
448 return boost::spirit::classic::functor_parser< detail::mbchar_parse_functor<> >( detail::mbchar_parse_functor<>( codeset ) );
449 }
450
451 extern boost::spirit::classic::functor_parser< detail::mbchar_parse_functor< ascii > > const ascii_p;
452 extern boost::spirit::classic::functor_parser< detail::mbchar_parse_functor< shift_jis > > const shift_jis_p;
453 extern boost::spirit::classic::functor_parser< detail::mbchar_parse_functor< euc_jp > > const euc_jp_p;
454 extern boost::spirit::classic::functor_parser< detail::mbchar_parse_functor< utf8 > > const utf8_p;
455
456 /*!
457 * \brief 国際文字名パーサー
458 *
459 * \\uまたは\\Uで始まる国際文字名(Universal Character Name)を解析します。
460 * \\uhhhhまたは\\Uhhhhhhhh(hは16進数字)に合致します。なお、これらの形式に
461 * 合致している場合でも、一部の値は国際文字名として使用できません。
462 */
463 inline boost::spirit::classic::functor_parser< detail::ucn_parse_functor > const ucn_parser()
464 {
465 return boost::spirit::classic::functor_parser< detail::ucn_parse_functor >();
466 }
467
468 extern boost::spirit::classic::functor_parser< detail::ucn_parse_functor > const ucn_p;
469
470 /*!
471 * \brief C言語形式の文字列定数パーサー
472 *
473 * 二重引用符で囲まれたC言語形式の文字列を解析します。
474 * 文字列の文字コードは CodeSet で指定したものになります。
475 */
476 template < int CodeSet >
477 inline boost::spirit::classic::functor_parser< detail::c_strlit_parse_functor< CodeSet > > const c_strlit_parser()
478 {
479 return boost::spirit::classic::functor_parser< detail::c_strlit_parse_functor< CodeSet > >();
480 }
481
482 typedef boost::spirit::classic::functor_parser< detail::c_strlit_parse_functor<> > c_strlit_parser_t;
483
484 /*!
485 * \brief C言語形式の文字列定数パーサー
486 * \param codeset 文字列に使用されている文字コード
487 *
488 * 二重引用符で囲まれたC言語形式の文字列を解析します。
489 */
490 inline boost::spirit::classic::functor_parser< detail::c_strlit_parse_functor<> > const c_strlit_parser( codeset_t codeset )
491 {
492 return boost::spirit::classic::functor_parser< detail::c_strlit_parse_functor<> >( detail::c_strlit_parse_functor<>( codeset ) );
493 }
494
495 extern boost::spirit::classic::functor_parser< detail::c_strlit_parse_functor< ascii > > const ascii_str_p;
496 extern boost::spirit::classic::functor_parser< detail::c_strlit_parse_functor< shift_jis > > const shift_jis_str_p;
497 extern boost::spirit::classic::functor_parser< detail::c_strlit_parse_functor< euc_jp > > const euc_jp_str_p;
498 extern boost::spirit::classic::functor_parser< detail::c_strlit_parse_functor< utf8 > > const utf8_str_p;
499
500 /*!
501 * \brief C言語形式の文字定数パーサー
502 *
503 * 単引用符で囲まれたC言語形式の文字定数を解析します。
504 * 文字コードは CodeSet で指定したものになります。
505 */
506 template < int CodeSet >
507 inline boost::spirit::classic::functor_parser< detail::c_chlit_parse_functor< CodeSet > > const c_chlit_parser()
508 {
509 return boost::spirit::classic::functor_parser< detail::c_chlit_parse_functor< CodeSet > >();
510 }
511
512 typedef boost::spirit::classic::functor_parser< detail::c_chlit_parse_functor<> > c_chlit_parser_t;
513
514 /*!
515 * \brief C言語形式の文字定数パーサー
516 * \param codeset 文字コード
517 *
518 * 単引用符で囲まれたC言語形式の文字定数を解析します。
519 */
520 inline boost::spirit::classic::functor_parser< detail::c_chlit_parse_functor<> > const c_chlit_parser( codeset_t codeset )
521 {
522 return boost::spirit::classic::functor_parser< detail::c_chlit_parse_functor<> >( detail::c_chlit_parse_functor<>( codeset ) );
523 }
524
525 extern boost::spirit::classic::functor_parser< detail::c_chlit_parse_functor< ascii > > const ascii_ch_p;
526 extern boost::spirit::classic::functor_parser< detail::c_chlit_parse_functor< shift_jis > > const shift_jis_ch_p;
527 extern boost::spirit::classic::functor_parser< detail::c_chlit_parse_functor< euc_jp > > const euc_jp_ch_p;
528 extern boost::spirit::classic::functor_parser< detail::c_chlit_parse_functor< utf8 > > const utf8_ch_p;
529
530 typedef boost::spirit::classic::functor_parser< detail::c_identifier_parse_functor > c_ident_parser_t;
531
532 /*!
533 * \brief C言語形式の識別子パーサー
534 * \param ucn 国際文字を許容する場合は true を指定
535 * \param c_plus_plus C++の予約語を禁止する場合は true を指定
536 *
537 * C言語の識別子として使用できる文字列の解析を行います。
538 * 識別子は下線または英文字で始まり、下線または英数字が続くのが原則ですが、
539 * C99以降では国際文字名も使用できるため、引数 ucn に true を指定することで、
540 * 国際文字名対応が可能になります。
541 *
542 * \note 翻訳限界および予約識別子の判別は行っていません。
543 */
544 inline boost::spirit::classic::functor_parser< detail::c_identifier_parse_functor > const c_ident_parser( bool ucn = false, bool c_plus_plus = false )
545 {
546 return boost::spirit::classic::functor_parser< detail::c_identifier_parse_functor >( detail::c_identifier_parse_functor( ucn, c_plus_plus ) );
547 }
548
549 extern boost::spirit::classic::functor_parser< detail::c_identifier_parse_functor > const c_ident_p;
550 extern boost::spirit::classic::functor_parser< detail::c_identifier_parse_functor > const c99_ident_p;
551 extern boost::spirit::classic::functor_parser< detail::c_identifier_parse_functor > const c_plus_plus_ident_p;
552
553}
554
555#endif // ! TOPPERS_PARSER_HPP_
Note: See TracBrowser for help on using the repository browser.