source: cfg_itronx+oil_gcc/toppers/c_expr.hpp@ 165

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

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

File size: 15.3 KB
Line 
1/*
2 * TOPPERS Software
3 * Toyohashi Open Platform for Embedded Real-Time Systems
4 *
5 * Copyright (C) 2005-2011 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_expr.hpp
40 * \brief C言語の式の構文解析に関する宣言定義
41 *
42 * このファイルで定義されるクラス
43 * \code
44 * struct c_expr_parser_base< Derived >;
45 * struct c_expr_parser;
46 * struct c_const_expr_parser;
47 * \endcode
48 */
49#ifndef TOPPERS_C_EXPR_HPP_
50#define TOPPERS_C_EXPR_HPP_
51
52#include "toppers/c_parser.hpp"
53#include <boost/cstdint.hpp>
54
55namespace toppers
56{
57
58 /*!
59 * \struct c_expr_parser_base c_expr.hpp "toppers/c_expr.hpp"
60 * \brief C言語の式を構文解析するための基底クラス
61 *
62 * 実際に使用する際は、 c_expr_parser_base および c_expr_parser_base::definition
63 * クラスを派生する必要があります。 c_expr_parser_base::definition の派生クラスでは、
64 * start メンバ関数を定義して、構文中の必要なルールを取り出すようにしてください。
65 * こうすることで、定数式の文法、一次式の文法といったように、C言語の文法のサブ
66 * セットを容易に作り出すことができます。
67 *
68 * \code
69 * // 一次式を取り出す例
70 * struct c_primary_expression : c_expr_parser_base< c_primary_expression >
71 * {
72 * template < class Scanner >
73 * struct definition : c_expr_parser_base< c_primary_expression >::definition
74 * {
75 * rule_t const& start() const { return primary_expression; }
76 * };
77 * };
78 * \endcode
79 */
80 template < class Derived >
81 struct c_expr_parser_base : boost::spirit::classic::grammar< Derived >
82 {
83 public:
84 /*!
85 * \struct definition c_expr.hpp "toppers/c_expr.hpp"
86 * \brief 文法定義
87 */
88 template < class Scanner >
89 struct definition
90 {
91 typedef boost::spirit::classic::rule< Scanner > rule_t;
92 rule_t primary_expression,
93 expression,
94 constant_expression,
95 conditional_expression,
96 assignment_expression,
97 assignment_operator,
98 postfix_expression,
99 unary_expression,
100 unary_operator,
101 cast_expression,
102 multiplicative_expression,
103 additive_expression,
104 shift_expression,
105 relational_expression,
106 equality_expression,
107 AND_expression,
108 exclusive_OR_expression,
109 inclusive_OR_expression,
110 logical_AND_expression,
111 logical_OR_expression,
112 string_literal,
113 constant,
114 floating_constant,
115 decimal_floating_constant,
116 hexadecimal_floating_constant,
117 integer_constant,
118 character_constant,
119 declaration_specifiers,
120 type_name,
121 specifier_qualifier_list,
122 storage_class_specifier,
123 type_specifier,
124 type_qualifier,
125 declarator,
126 direct_declarator,
127 struct_or_union_specifier,
128 struct_declaration,
129 struct_declarator,
130 enum_specifier,
131 enumerator,
132 abstract_declarator,
133 pointer,
134 parameter_type_list,
135 parameter_list,
136 parameter_declaration,
137 direct_abstract_declarator;
138
139 c_ident_parser_t identifier;
140 c_strlit_parser_t c_strlit_p;
141 c_chlit_parser_t c_chlit_p;
142
143 /*!
144 * \brief コンストラクタ
145 * \param self 文法クラス( c_expr_parser_base< Derived > クラスからの継承)への参照
146 */
147 definition( Derived const& self )
148 : identifier( c_ident_parser( self.ucn_, self.c_plus_plus_ ) ),
149 c_strlit_p( c_strlit_parser( self.codeset_ ) ),
150 c_chlit_p( c_chlit_parser( self.codeset_ ) )
151 {
152 using namespace boost::spirit::classic;
153 static functor_parser< detail::c_integer_constant_parse_functor< boost::uintmax_t > > const c_int_const_p;
154 static functor_parser< detail::c_integer_suffix_parse_functor > const c_int_suffix_p;
155
156 primary_expression = // 複合リテラル未対応
157 identifier
158 | constant
159 | string_literal
160 | ( '(' >> expression >> ')' );
161 expression =
162 assignment_expression % ',';
163 constant_expression =
164 conditional_expression;
165 conditional_expression =
166 logical_OR_expression >> *( '\?' >> expression >> ':' >> logical_OR_expression );
167 assignment_expression =
168 *( unary_expression >> assignment_operator ) >> conditional_expression;
169 assignment_operator =
170 ch_p( '=' ) | "*=" | "/=" | "%=" | "+=" | "?=" | "<<=" | ">>=" | "&=" | "^=" | "|=";
171 postfix_expression =
172 primary_expression >>
173 *(
174 ( '[' >> expression >> ']' )
175 | ( '(' >> list_p( assignment_expression, ',' ) >> ')' )
176 | ( '.' >> identifier )
177 | ( "->" >> identifier )
178 | "++"
179 | "--"
180 );
181 unary_expression =
182 *( str_p( "++" ) || "--" ) >>
183 (
184 ( "sizeof" >> unary_expression )
185 | ( str_p( "sizeof" ) >> '(' >> type_name >> ')' )
186 | postfix_expression
187 | ( unary_operator >> cast_expression )
188 );
189 unary_operator =
190 //chset<>( "&*~!+-" );
191 ch_p( '&' ) | '*' | '~' | '!' | '+' | '-';
192 cast_expression =
193 *( '(' >> type_name >> ')' ) >> unary_expression
194 | +( '(' >> ( type_name | identifier ) >> ')' ); // 構文解析に失敗する不具合対策
195 multiplicative_expression =
196 cast_expression >>
197 *(
198 ( '*' >> cast_expression )
199 | ( '/' >> cast_expression )
200 | ( '%' >> cast_expression )
201 );
202 additive_expression =
203 multiplicative_expression >>
204 *(
205 ( '+' >> multiplicative_expression )
206 | ( '-' >> multiplicative_expression )
207 );
208 shift_expression =
209 additive_expression >>
210 *(
211 ( "<<" >> additive_expression )
212 | ( ">>" >> additive_expression )
213 );
214 relational_expression =
215 shift_expression >>
216 *(
217 ( '<' >> shift_expression )
218 | ( '>' >> shift_expression )
219 | ( "<=" >> shift_expression )
220 | ( ">=" >> shift_expression )
221 );
222 equality_expression =
223 relational_expression >>
224 *(
225 ( "==" >> relational_expression )
226 | ( "!=" >> relational_expression )
227 );
228 AND_expression =
229 equality_expression >> *( '&' >> equality_expression );
230 exclusive_OR_expression =
231 AND_expression >> *( '^' >> AND_expression );
232 inclusive_OR_expression =
233 exclusive_OR_expression >> *( '|' >> exclusive_OR_expression );
234 logical_AND_expression =
235 inclusive_OR_expression >> *( "&&" >> inclusive_OR_expression );
236 logical_OR_expression =
237 logical_AND_expression >> *( "||" >> logical_AND_expression );
238 string_literal =
239 c_strlit_p
240 | lexeme_d[ 'L' >> c_strlit_p ];
241 constant =
242 floating_constant
243 | integer_constant
244 | identifier // 列挙定数
245 | character_constant;
246 floating_constant =
247 decimal_floating_constant
248 | hexadecimal_floating_constant;
249 decimal_floating_constant =
250 lexeme_d
251 [
252 as_lower_d
253 [
254 ( ( *digit_p >> '.' >> +digit_p ) | ( +digit_p >> '.' ) ) >>
255// 'e' >> !chset<>( "+-" ) >> +digit_p >>
256 'e' >> !( ch_p( '+' ) | '-' ) >> +digit_p >>
257// !chset<>( "fl" )
258 ( ch_p( 'f' ) | 'l' )
259 ]
260 ];
261 hexadecimal_floating_constant =
262 lexeme_d
263 [
264 as_lower_d
265 [
266 "0x" >>
267 ( ( *xdigit_p >> '.' >> +xdigit_p ) | ( +xdigit_p >> '.' ) ) >>
268// 'p' >> !chset<>( "+-" ) >> +digit_p >>
269 'p' >> !( ch_p( '+' ) | '-' ) >> +digit_p >>
270// !chset<>( "fl" )
271 ( ch_p( 'f' ) | 'l' )
272 ]
273 ];
274 integer_constant =
275 lexeme_d[ c_int_const_p >> !c_int_suffix_p ];
276 character_constant =
277 c_chlit_p
278 | lexeme_d[ 'L' >> c_chlit_p ];
279 declaration_specifiers =
280 +( storage_class_specifier | type_specifier | type_qualifier );
281 type_name =
282 specifier_qualifier_list >> !abstract_declarator;
283 specifier_qualifier_list =
284 +( type_specifier | type_qualifier );
285 storage_class_specifier =
286 str_p( "auto" )
287 | "register"
288 | "static"
289 | "extern"
290 | "typedef";
291 type_specifier =
292 str_p( "void" ) | "char" | "short" | "int" | "long" | "float" | "double"
293 | "signed" | "unsigned"
294 | identifier
295 | struct_or_union_specifier
296 | enum_specifier;
297 type_qualifier =
298 str_p( "const" ) | "volatile" | "restrict";
299 declarator =
300 !pointer >> direct_declarator;
301 direct_declarator =
302 ( identifier | ( '(' >> declarator >> ')' ) )
303 >>
304 *(
305 ( '[' >> !constant_expression >> ']' )
306 | ( '(' >> parameter_type_list >> ')' )
307 | ( '(' >> !( identifier % ',' ) >> ')' )
308 );
309 struct_or_union_specifier =
310 lexeme_d[ ( str_p( "struct" ) | "union" ) >> +space_p >> identifier ]
311 | ( lexeme_d[ ( str_p( "struct" ) | "union" ) >> +space_p >> !identifier ] >> '{' >> +struct_declaration >> '}' );
312 struct_declaration =
313 specifier_qualifier_list >> !list_p( struct_declarator, ',' ) >> ';';
314 // lisp_p( struct_declarator, ',' )を省略可能としているのは、
315 // struct_declarator の identifier を specifier_qualifier_list が
316 // typedef 名と間違うことを回避するため
317 struct_declarator =
318 ( !declarator >> ':' >> constant_expression ) // ビットフィールド
319 | declarator;
320 enum_specifier =
321 ( lexeme_d[ "enum" >> +space_p >> !identifier ] >> '{' >> list_p( enumerator, ',', ',' ) >> '}' ) // C99では末尾のカンマがあってもよい
322 | lexeme_d[ "enum" >> +space_p >> identifier ];
323 enumerator =
324 identifier >> !( '=' >> constant_expression );
325 abstract_declarator =
326 ( !pointer >> direct_abstract_declarator )
327 | pointer;
328 pointer =
329 +( '*' >> *type_qualifier );
330 parameter_type_list =
331 parameter_list >> !( ch_p( ',' ) >> "..." ); // 可変個引数
332 parameter_list =
333 parameter_declaration % ',';
334 parameter_declaration =
335 ( declaration_specifiers >> declarator )
336 | ( declaration_specifiers >> !abstract_declarator );
337 direct_abstract_declarator =
338 (
339 !( '(' >> abstract_declarator >> ')' ) >>
340 +(
341 ( '[' >> !constant_expression >> ']' )
342 | ( '(' >> !parameter_type_list >> ')' )
343 )
344 )
345 | ( '(' >> abstract_declarator >> ')' );
346 }
347 };
348 bool ucn_;
349 codeset_t codeset_;
350 bool c_plus_plus_;
351
352 /*!
353 * \brief コンストラクタ
354 * \param ucn 国際文字名に対応する場合は true を指定する
355 * \param codeset 文字コード
356 * \param c_plus_plus C++ に対応する場合は true を指定する
357 */
358 explicit c_expr_parser_base( bool ucn = false, codeset_t codeset = ascii, bool c_plus_plus = false )
359 : ucn_( ucn ), codeset_( codeset ), c_plus_plus_( c_plus_plus )
360 {
361 }
362 };
363
364 /*!
365 * \class c_expr_parser c_expr.hpp "toppers/c_expr.hpp"
366 * \brief C言語の式の構文解析クラス
367 */
368 struct c_expr_parser : c_expr_parser_base< c_expr_parser >
369 {
370 typedef c_expr_parser_base< c_expr_parser > base_t;
371
372 /*!
373 * \struct definition c_expr.hpp "toppers/c_expr.hpp"
374 * \brief 文法定義
375 */
376 template < class Scanner >
377 struct definition : base_t::definition< Scanner >
378 {
379 typedef typename base_t::definition< Scanner >::rule_t rule_t;
380
381 definition( c_expr_parser const& self ) : base_t::definition< Scanner >( self ) {}
382 rule_t const& start() const { return base_t::definition< Scanner >::expression; };
383 };
384
385 /*!
386 * \brief コンストラクタ
387 * \param ucn 国際文字名に対応する場合は true を指定する
388 * \param codeset 文字コード
389 */
390 explicit c_expr_parser( bool ucn = false, codeset_t codeset = ascii )
391 : c_expr_parser_base< c_expr_parser >( ucn, codeset )
392 {
393 }
394 };
395
396 /*!
397 * \class c_const_expr_parser c_expr.hpp "toppers/c_expr.hpp"
398 * \brief C言語の定数式の構文解析クラス
399 */
400 struct c_const_expr_parser : c_expr_parser_base< c_const_expr_parser >
401 {
402 typedef c_expr_parser_base< c_const_expr_parser > base_t;
403
404 /*!
405 * \struct definition c_expr.hpp "toppers/c_expr.hpp"
406 * \brief 文法定義
407 */
408 template < class Scanner >
409 struct definition : base_t::definition< Scanner >
410 {
411 typedef typename base_t::definition< Scanner >::rule_t rule_t;
412
413 definition( c_const_expr_parser const& self ) : base_t::definition< Scanner >( self ) {}
414 rule_t const& start() const { return base_t::definition< Scanner >::constant_expression; };
415 };
416
417 /*!
418 * \brief コンストラクタ
419 * \param ucn 国際文字名に対応する場合は true を指定する
420 * \param codeset 文字コード
421 */
422 explicit c_const_expr_parser( bool ucn = false, codeset_t codeset = ascii )
423 : c_expr_parser_base< c_const_expr_parser >( ucn, codeset )
424 {
425 }
426 };
427
428}
429
430#endif // ! TOPPERS_C_EXPR_HPP_
Note: See TracBrowser for help on using the repository browser.