├── eop_lex_stream.cpp ├── eop_lex_stream.hpp ├── eop_lex_stream_fwd.hpp ├── exp_parser.cpp ├── exp_parser.hpp └── main.cpp /eop_lex_stream.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2005-2007 Adobe Systems Incorporated 3 | Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt 4 | or a copy at http://stlab.adobe.com/licenses.html) 5 | */ 6 | 7 | /*************************************************************************************************/ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | #include "eop_lex_stream.hpp" 24 | 25 | /*************************************************************************************************/ 26 | 27 | #ifdef BOOST_MSVC 28 | namespace std 29 | { 30 | using ::isspace; 31 | using ::isdigit; 32 | using ::isalnum; 33 | using ::isalpha; 34 | } 35 | #endif 36 | 37 | /*************************************************************************************************/ 38 | 39 | ADOBE_ONCE_DECLARATION(adobe_lex_stream) 40 | 41 | /*************************************************************************************************/ 42 | 43 | namespace { 44 | 45 | using namespace adobe; 46 | 47 | /*************************************************************************************************/ 48 | #if 0 49 | #pragma mark - 50 | #endif 51 | 52 | /*************************************************************************************************/ 53 | namespace implementation { 54 | 55 | struct lex_fragment_t 56 | { 57 | lex_fragment_t( stream_lex_token_t token = stream_lex_token_t(), 58 | const line_position_t& line_position = line_position_t()) : 59 | token_value_m(move(token)), line_position_m(line_position) 60 | { } 61 | 62 | lex_fragment_t(move_from x) : 63 | token_value_m(move(x.source.token_value_m)), line_position_m(move(x.source.line_position_m)) 64 | { } 65 | 66 | lex_fragment_t& operator=(lex_fragment_t x) 67 | { 68 | token_value_m = move(x.token_value_m); 69 | line_position_m = move(x.line_position_m); 70 | return *this; 71 | } 72 | 73 | stream_lex_token_t token_value_m; 74 | line_position_t line_position_m; 75 | }; 76 | 77 | } // namespace implementation 78 | 79 | template < std::size_t S, 80 | typename I> // I models InputIterator 81 | struct stream_lex_base_t 82 | { 83 | public: 84 | typedef std::istream::pos_type pos_type; 85 | typedef boost::function parse_token_proc_t; 86 | 87 | stream_lex_base_t(I first, I last, const line_position_t& position); 88 | 89 | virtual ~stream_lex_base_t(); 90 | 91 | const stream_lex_token_t& get_token(); 92 | void putback_token(); 93 | void put_token(stream_lex_token_t token); 94 | 95 | bool get_char(char& c); 96 | void putback_char(char c); 97 | int peek_char(); 98 | void ignore_char(); 99 | 100 | void throw_exception(const name_t& expected, const name_t& found); 101 | void throw_parser_exception(const char* error_string); 102 | 103 | virtual void skip_white_space() = 0; 104 | 105 | const line_position_t& next_position(); 106 | 107 | bool is_line_end(char c); 108 | 109 | void set_parse_token_proc(parse_token_proc_t proc); 110 | 111 | std::vector identifier_buffer_m; 112 | 113 | private: 114 | I first_m; 115 | I last_m; 116 | std::streampos streampos_m; 117 | line_position_t line_position_m; 118 | parse_token_proc_t parse_proc_m; 119 | boost::array putback_m; // stack-based is faster 120 | std::size_t index_m; // for putback_m 121 | 122 | #if !defined(ADOBE_NO_DOCUMENTATION) 123 | circular_queue last_token_m; // N token lookahead 124 | #endif // !defined(ADOBE_NO_DOCUMENTATION) 125 | }; 126 | 127 | /*************************************************************************************************/ 128 | 129 | template 130 | stream_lex_base_t::stream_lex_base_t(I first, I last, const line_position_t& position) : 131 | identifier_buffer_m(128), 132 | first_m(first), 133 | last_m(last), 134 | streampos_m(1), 135 | line_position_m(position), 136 | index_m(0), 137 | last_token_m(S) 138 | { } 139 | 140 | /*************************************************************************************************/ 141 | 142 | template 143 | stream_lex_base_t::~stream_lex_base_t() 144 | { } 145 | 146 | /*************************************************************************************************/ 147 | 148 | template 149 | bool stream_lex_base_t::get_char(char& c) 150 | { 151 | if (index_m) 152 | { 153 | c = static_cast(putback_m[index_m]); 154 | 155 | --index_m; 156 | 157 | streampos_m += 1; 158 | 159 | return true; 160 | } 161 | 162 | if (first_m == last_m) return false; 163 | 164 | c = static_cast(*first_m); 165 | 166 | ++first_m; 167 | 168 | streampos_m += 1; 169 | 170 | return true; 171 | } 172 | 173 | /*************************************************************************************************/ 174 | 175 | template 176 | void stream_lex_base_t::putback_char(char c) 177 | { 178 | putback_m[++index_m] = c; 179 | 180 | streampos_m -= 1; 181 | } 182 | 183 | /*************************************************************************************************/ 184 | 185 | template 186 | int stream_lex_base_t::peek_char() 187 | { 188 | if (index_m) 189 | return putback_m[index_m]; 190 | else if (first_m == last_m) 191 | return EOF; 192 | else 193 | return *first_m; 194 | } 195 | 196 | /*************************************************************************************************/ 197 | 198 | template 199 | void stream_lex_base_t::ignore_char() 200 | { 201 | if (index_m) 202 | --index_m; 203 | else if (first_m == last_m) 204 | return; 205 | else 206 | ++first_m; 207 | 208 | streampos_m += 1; 209 | } 210 | 211 | /*************************************************************************************************/ 212 | 213 | template 214 | const stream_lex_token_t& stream_lex_base_t::get_token() 215 | { 216 | assert(parse_proc_m); 217 | 218 | if (last_token_m.empty()) 219 | { 220 | char c; 221 | 222 | /* 223 | REVISIT (sparent) : You can't get(c), tellg(), and then putback(c) on a stream - the 224 | tellg() in the middle will cause the putback(c) to move the stream to an invalid state. 225 | So instead of calling skip_space(c) we break up the call with the tellg() in the middle, 226 | prior to the callback. 227 | */ 228 | 229 | skip_white_space(); 230 | 231 | line_position_m.position_m = streampos_m; // remember the start of the token position 232 | 233 | /* 234 | REVISIT (sparent) : I don't like that eof is not handled as the other tokens are handled 235 | there should be a way to make this logic consistant. 236 | */ 237 | 238 | if (!get_char(c)) // eof 239 | put_token(stream_lex_token_t(eof_k, any_regular_t())); 240 | else 241 | parse_proc_m(c); 242 | } 243 | 244 | stream_lex_token_t& result(last_token_m.front().token_value_m); 245 | 246 | last_token_m.pop_front(); 247 | 248 | return result; 249 | } 250 | 251 | /*************************************************************************************************/ 252 | 253 | template 254 | void stream_lex_base_t::put_token(stream_lex_token_t token) 255 | { 256 | last_token_m.push_back(implementation::lex_fragment_t(move(token), line_position_m)); 257 | } 258 | 259 | /*************************************************************************************************/ 260 | 261 | template 262 | void stream_lex_base_t::putback_token() 263 | { 264 | last_token_m.putback(); // REVISIT (sparent) : Check for overflow 265 | } 266 | 267 | /*************************************************************************************************/ 268 | 269 | template 270 | const line_position_t& stream_lex_base_t::next_position() 271 | { 272 | /* 273 | REVISIT (sparent) : Clean this up - this primes the ring buffer so we can get the next position 274 | */ 275 | get_token(); putback_token(); 276 | 277 | return last_token_m.front().line_position_m; 278 | } 279 | 280 | /*************************************************************************************************/ 281 | 282 | template 283 | bool stream_lex_base_t::is_line_end(char c) 284 | { 285 | using adobe::is_line_end; 286 | 287 | std::size_t num_chars_eaten(is_line_end(first_m, last_m, c)); 288 | 289 | if (num_chars_eaten != 0) 290 | { 291 | ++line_position_m.line_number_m; 292 | 293 | if (num_chars_eaten == 2) 294 | streampos_m += 1; 295 | 296 | line_position_m.line_start_m = streampos_m; 297 | } 298 | 299 | return num_chars_eaten != 0; 300 | } 301 | 302 | /*************************************************************************************************/ 303 | 304 | template 305 | void stream_lex_base_t::throw_parser_exception(const char* error_string) 306 | { 307 | using adobe::throw_parser_exception; 308 | 309 | throw_parser_exception(error_string, line_position_m); 310 | } 311 | 312 | /*************************************************************************************************/ 313 | 314 | template 315 | void stream_lex_base_t::set_parse_token_proc(parse_token_proc_t proc) 316 | { 317 | parse_proc_m = proc; 318 | } 319 | 320 | /*************************************************************************************************/ 321 | 322 | /*************************************************************************************************/ 323 | 324 | typedef boost::array keyword_table_t; 325 | 326 | /*************************************************************************************************/ 327 | 328 | const keyword_table_t* keywords_g; 329 | const char* compound_match_g; 330 | const adobe::name_t* name_table_g; 331 | const int* compound_index_g; 332 | const int* simple_index_g; 333 | 334 | /*************************************************************************************************/ 335 | 336 | void init_once() 337 | { 338 | static keyword_table_t keywords_s = {{ 339 | adobe::true_k, 340 | adobe::false_k 341 | }}; 342 | 343 | static const char compound_match_s[] = { 344 | /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 345 | /* 00 */ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 346 | /* 10 */ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 347 | /* 20 */ '0', '=', '0', '0', '0', '0', '&', '0', '0', '0', '0', '0', '0', '0', '0', '0', 348 | /* 30 */ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '=', '=', '=', '0', 349 | /* 40 */ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 350 | /* 50 */ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 351 | /* 60 */ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 352 | /* 70 */ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '|', '0', '0', '0', 353 | /* 80 */ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 354 | /* 90 */ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 355 | /* A0 */ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 356 | /* B0 */ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 357 | /* C0 */ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 358 | /* D0 */ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 359 | /* E0 */ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', 360 | /* F0 */ '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0' 361 | }; 362 | 363 | static const adobe::name_t name_table_s[] = { 364 | /* 00 */ adobe::empty_k, 365 | /* 01 */ adobe::equal_k, 366 | /* 02 */ adobe::and_k, 367 | /* 03 */ adobe::or_k, 368 | /* 04 */ adobe::less_equal_k, 369 | /* 05 */ adobe::greater_equal_k, 370 | /* 06 */ adobe::not_equal_k, 371 | 372 | /* 07 */ adobe::add_k, 373 | /* 08 */ adobe::subtract_k, 374 | /* 09 */ adobe::multiply_k, 375 | /* 0A */ adobe::divide_k, 376 | /* 0B */ adobe::modulus_k, 377 | /* 0C */ adobe::question_k, // Removed... 378 | /* 0D */ adobe::colon_k, 379 | /* 0E */ adobe::semicolon_k, 380 | /* 0F */ adobe::assign_k, 381 | /* 10 */ adobe::not_k, 382 | /* 11 */ adobe::open_brace_k, 383 | /* 12 */ adobe::close_brace_k, 384 | /* 13 */ adobe::less_k, 385 | /* 14 */ adobe::greater_k, 386 | /* 15 */ adobe::open_parenthesis_k, 387 | /* 16 */ adobe::close_parenthesis_k, 388 | /* 17 */ eop::reference_k, 389 | /* 18 */ adobe::open_bracket_k, 390 | /* 19 */ adobe::close_bracket_k, 391 | /* 1A */ adobe::comma_k, 392 | /* 1B */ adobe::dot_k, 393 | /* 1C */ eop::destructor_k 394 | }; 395 | 396 | static const int compound_index_s[] = { 397 | /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 398 | /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 399 | /* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 400 | /* 20 */ 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 401 | /* 30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x05, 0x00, 402 | /* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 403 | /* 50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 404 | /* 60 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 405 | /* 70 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 406 | /* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 407 | /* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 408 | /* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 409 | /* B0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 410 | /* C0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 411 | /* D0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 412 | /* E0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 413 | /* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 414 | }; 415 | 416 | static const int simple_index_s[] = { 417 | /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 418 | /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 419 | /* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 420 | /* 20 */ 0x00, 0x10, 0x00, 0x00, 0x00, 0x0B, 0x17, 0x00, 0x15, 0x16, 0x09, 0x07, 0x1A, 0x08, 0x1B, 0x0A, 421 | /* 30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0E, 0x13, 0x0F, 0x14, 0x00, 422 | /* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 423 | /* 50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x19, 0x00, 0x00, 424 | /* 60 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 425 | /* 70 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x12, 0x1C, 0x00, 426 | /* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 427 | /* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 428 | /* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 429 | /* B0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 430 | /* C0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 431 | /* D0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 432 | /* E0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 433 | /* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 434 | }; 435 | 436 | adobe::sort(keywords_s); 437 | 438 | keywords_g = &keywords_s; 439 | compound_match_g = &compound_match_s[0]; 440 | name_table_g = &name_table_s[0]; 441 | compound_index_g = &compound_index_s[0]; 442 | simple_index_g = &simple_index_s[0]; 443 | } 444 | 445 | /*************************************************************************************************/ 446 | 447 | void once_instance() 448 | { 449 | ADOBE_ONCE_INSTANCE(adobe_lex_stream); 450 | } 451 | 452 | /*************************************************************************************************/ 453 | 454 | } // namespace 455 | 456 | /*************************************************************************************************/ 457 | 458 | ADOBE_ONCE_DEFINITION(adobe_lex_stream, init_once) 459 | 460 | /*************************************************************************************************/ 461 | 462 | namespace eop { 463 | 464 | /*************************************************************************************************/ 465 | 466 | aggregate_name_t reference_k = { "reference" }; 467 | aggregate_name_t pound_k = { "pound" }; 468 | aggregate_name_t shift_left_k = { "shift_left" }; 469 | aggregate_name_t shift_right_k = { "shift_right" }; 470 | aggregate_name_t destructor_k = { "destructor" }; 471 | 472 | /*************************************************************************************************/ 473 | 474 | #ifndef NDEBUG 475 | std::ostream& operator<<(std::ostream& out, const stream_lex_token_t& token) 476 | { 477 | out << "{" << token.first << ": " << token.second << "}"; 478 | return out; 479 | } 480 | #endif 481 | 482 | /*************************************************************************************************/ 483 | 484 | struct lex_stream_t::implementation_t : stream_lex_base_t<2, std::istream_iterator > 485 | { 486 | typedef stream_lex_base_t<2, std::istream_iterator > _super; 487 | 488 | public: 489 | typedef std::istream::pos_type pos_type; 490 | 491 | implementation_t(std::istream& in, const line_position_t& position); 492 | 493 | void set_keyword_extension_lookup(const keyword_extension_lookup_proc_t& proc); 494 | 495 | private: 496 | void parse_token(char c); 497 | 498 | bool is_comment(char c, stream_lex_token_t& result); 499 | bool is_string(char c, stream_lex_token_t& result); 500 | bool is_number(char c, stream_lex_token_t& result); 501 | bool is_compound(char c, stream_lex_token_t& result); 502 | bool is_simple(char c, stream_lex_token_t& result); 503 | bool is_identifier_or_keyword(char c, stream_lex_token_t& result); 504 | 505 | void skip_white_space(); 506 | bool skip_space(char& c); 507 | 508 | keyword_extension_lookup_proc_t keyword_proc_m; 509 | }; 510 | 511 | /*************************************************************************************************/ 512 | 513 | lex_stream_t::lex_stream_t(std::istream& in, const line_position_t& position ) : 514 | object_m(new lex_stream_t::implementation_t(in, position)) 515 | { once_instance(); } 516 | 517 | #if !defined(ADOBE_NO_DOCUMENTATION) 518 | 519 | lex_stream_t::lex_stream_t(const lex_stream_t& rhs) : 520 | object_m(new lex_stream_t::implementation_t(*rhs.object_m)) 521 | { once_instance(); } 522 | 523 | lex_stream_t::~lex_stream_t() 524 | { delete object_m; } 525 | 526 | lex_stream_t& lex_stream_t::operator = (const lex_stream_t& rhs) 527 | { *object_m = *rhs.object_m; return *this; } 528 | 529 | #endif // !defined(ADOBE_NO_DOCUMENTATION) 530 | 531 | const stream_lex_token_t& lex_stream_t::get() 532 | { return object_m->get_token(); } 533 | 534 | void lex_stream_t::putback() 535 | { object_m->putback_token(); } 536 | 537 | const line_position_t& lex_stream_t::next_position() 538 | { return object_m->next_position(); } 539 | 540 | void lex_stream_t::set_keyword_extension_lookup(const keyword_extension_lookup_proc_t& proc) 541 | { return object_m->set_keyword_extension_lookup(proc); } 542 | 543 | /*************************************************************************************************/ 544 | 545 | #if 0 546 | #pragma mark - 547 | #endif 548 | 549 | /*************************************************************************************************/ 550 | 551 | lex_stream_t::implementation_t::implementation_t(std::istream& in, const line_position_t& position) : 552 | _super(std::istream_iterator(in), std::istream_iterator(), position) 553 | { 554 | in.unsetf(std::ios_base::skipws); 555 | 556 | _super::set_parse_token_proc(boost::bind(&lex_stream_t::implementation_t::parse_token, boost::ref(*this), _1)); 557 | } 558 | 559 | /*************************************************************************************************/ 560 | 561 | void lex_stream_t::implementation_t::set_keyword_extension_lookup(const keyword_extension_lookup_proc_t& proc) 562 | { 563 | keyword_proc_m = proc; 564 | } 565 | 566 | /*************************************************************************************************/ 567 | 568 | bool lex_stream_t::implementation_t::is_number(char c, stream_lex_token_t& result) 569 | { 570 | if (!std::isdigit(c)) return false; 571 | 572 | _super::putback_char(c); 573 | 574 | std::stringstream temp; 575 | temp.imbue(std::locale::classic()); 576 | 577 | while (true) 578 | { 579 | if (!_super::get_char(c)) break; 580 | 581 | if (!std::isdigit(c) && c != '.') 582 | { 583 | _super::putback_char(c); 584 | 585 | break; 586 | } 587 | 588 | temp << c; 589 | } 590 | 591 | double re(0); 592 | temp >> re; 593 | 594 | result = stream_lex_token_t(number_k, any_regular_t(re)); 595 | return true; 596 | } 597 | 598 | /*************************************************************************************************/ 599 | 600 | bool lex_stream_t::implementation_t::is_identifier_or_keyword(char c, stream_lex_token_t& result) 601 | { 602 | if (!std::isalpha(c) && c != '_') return false; 603 | 604 | identifier_buffer_m.clear(); 605 | 606 | do 607 | { 608 | if (std::isalnum(c) || c == '_') 609 | { 610 | identifier_buffer_m.push_back(c); 611 | } 612 | else 613 | { 614 | _super::putback_char(c); 615 | break; 616 | } 617 | } 618 | while (_super::get_char(c)); 619 | 620 | identifier_buffer_m.push_back(0); 621 | 622 | name_t ident(&identifier_buffer_m.front()); 623 | keyword_table_t::const_iterator iter(lower_bound(*keywords_g, ident)); 624 | 625 | if ((iter != keywords_g->end() && *iter == ident) || 626 | (!keyword_proc_m.empty() && keyword_proc_m(ident))) 627 | { 628 | result = stream_lex_token_t(keyword_k, any_regular_t(ident)); 629 | } 630 | else 631 | { 632 | result = stream_lex_token_t(identifier_k, any_regular_t(ident)); 633 | } 634 | 635 | return true; 636 | } 637 | 638 | /*************************************************************************************************/ 639 | 640 | bool lex_stream_t::implementation_t::is_comment(char c, stream_lex_token_t& result) 641 | { 642 | if (c == '#') { 643 | while (_super::get_char(c) && !is_line_end(c)) identifier_buffer_m.push_back(c); 644 | 645 | identifier_buffer_m.push_back(0); 646 | 647 | result = stream_lex_token_t(trail_comment_k, any_regular_t(std::string(&identifier_buffer_m[0]))); 648 | return true; 649 | } 650 | 651 | if (c != '/') return false; 652 | 653 | std::istream::int_type peek_c (_super::peek_char()); 654 | 655 | if (peek_c == EOF || (peek_c != '/' && peek_c != '*')) return false; 656 | 657 | (void)_super::get_char(c); 658 | 659 | identifier_buffer_m.clear(); 660 | 661 | if (c == '/') 662 | { 663 | while (_super::get_char(c) && !is_line_end(c)) 664 | { 665 | identifier_buffer_m.push_back(c); 666 | } 667 | 668 | identifier_buffer_m.push_back(0); 669 | 670 | result = stream_lex_token_t(trail_comment_k, any_regular_t(std::string(&identifier_buffer_m[0]))); 671 | } 672 | else // if (c == '*') 673 | { 674 | while (true) 675 | { 676 | if (!_super::get_char(c)) 677 | throw_parser_exception("Unexpected EOF in comment."); 678 | 679 | if (c == '*') 680 | { 681 | peek_c = _super::peek_char(); 682 | 683 | if (peek_c != EOF && peek_c == '/') 684 | { _super::ignore_char(); break; } 685 | } 686 | else if (is_line_end(c)) 687 | { c = '\n'; } 688 | 689 | identifier_buffer_m.push_back(c); 690 | } 691 | 692 | identifier_buffer_m.push_back(0); 693 | 694 | result = stream_lex_token_t(lead_comment_k, any_regular_t(std::string(&identifier_buffer_m[0]))); 695 | } 696 | 697 | return true; 698 | 699 | } 700 | 701 | /*************************************************************************************************/ 702 | 703 | bool lex_stream_t::implementation_t::is_string(char c, stream_lex_token_t& result) 704 | { 705 | if (c != '\'' && c != '\"') return false; 706 | 707 | identifier_buffer_m.clear(); 708 | 709 | while (true) 710 | { 711 | char end_char (c); 712 | 713 | while (_super::get_char(c) && c != end_char) 714 | { 715 | // REVISIT (sparent) : Handle quoted characters here. 716 | // Also handle invalid characters such as line endings. 717 | identifier_buffer_m.push_back(c); 718 | } 719 | 720 | if (c != end_char) throw_parser_exception("Unexpected EOF in string."); 721 | 722 | if (!skip_space(c)) break; 723 | 724 | if (c != '\'' && c != '\"') 725 | { 726 | _super::putback_char(c); 727 | break; 728 | } 729 | } 730 | 731 | identifier_buffer_m.push_back(0); 732 | result = stream_lex_token_t(string_k, any_regular_t(std::string(&identifier_buffer_m[0]))); 733 | 734 | return true; 735 | } 736 | 737 | /*************************************************************************************************/ 738 | 739 | /* 740 | is_compound() works by noting that in all the current compound tokens the token is unique in 741 | the first character and only requires that the proper second character be present. 742 | */ 743 | 744 | bool lex_stream_t::implementation_t::is_compound(char c, stream_lex_token_t& result) 745 | { 746 | char next_char (compound_match_g[(unsigned char)c]); 747 | 748 | if (next_char == '0') return false; 749 | 750 | int actual_next (_super::peek_char()); 751 | 752 | if (actual_next == EOF) return false; 753 | 754 | char actual_char(actual_next); 755 | 756 | /* 757 | Special case the shift operators here - they aren't unique in the second character. 758 | */ 759 | 760 | if (c == '<' && actual_char == '<') { 761 | result = stream_lex_token_t(shift_left_k, any_regular_t()); 762 | _super::ignore_char(); 763 | return true; 764 | } 765 | 766 | if (c == '>' && actual_char == '>') { 767 | result = stream_lex_token_t(shift_right_k, any_regular_t()); 768 | _super::ignore_char(); 769 | return true; 770 | } 771 | 772 | if (actual_char != next_char) return false; 773 | 774 | _super::ignore_char(); 775 | 776 | /* 777 | There is only a single 3 character compound. It is special cased here rather than adding an 778 | additional table. The token is '<=='. 779 | */ 780 | 781 | if (c == '<' && _super::peek_char() == '=') 782 | { 783 | _super::ignore_char(); 784 | result = stream_lex_token_t(is_k, any_regular_t()); 785 | return true; 786 | } 787 | 788 | result = stream_lex_token_t(name_table_g[compound_index_g[(unsigned char)c]], any_regular_t()); 789 | return true; 790 | } 791 | 792 | /*************************************************************************************************/ 793 | 794 | bool lex_stream_t::implementation_t::is_simple(char c, stream_lex_token_t& result) 795 | { 796 | int index (simple_index_g[(unsigned char)c]); 797 | 798 | if (index == 0) return false; 799 | 800 | result = stream_lex_token_t(name_table_g[index], any_regular_t()); 801 | return true; 802 | } 803 | 804 | /*************************************************************************************************/ 805 | 806 | void lex_stream_t::implementation_t::skip_white_space() 807 | { 808 | char c; 809 | stream_lex_token_t tmp; 810 | 811 | while (get_char(c)) 812 | { 813 | // Handle any type of line ending. 814 | if (!is_line_end(c) && !std::isspace(c) && !is_comment(c, tmp)) 815 | { 816 | putback_char(c); 817 | 818 | break; 819 | } 820 | } 821 | } 822 | 823 | bool lex_stream_t::implementation_t::skip_space(char& c) 824 | { 825 | skip_white_space(); 826 | return get_char(c); 827 | } 828 | 829 | /*************************************************************************************************/ 830 | 831 | void lex_stream_t::implementation_t::parse_token(char c) 832 | { 833 | stream_lex_token_t result; 834 | 835 | if (!( is_number(c, result) 836 | || is_identifier_or_keyword(c, result) 837 | // || is_comment(c, result) 838 | || is_string(c,result) 839 | || is_compound(c, result) 840 | || is_simple(c, result))) 841 | { throw_parser_exception("Syntax Error"); } 842 | 843 | put_token(move(result)); 844 | } 845 | 846 | /*************************************************************************************************/ 847 | 848 | } // namespace eop 849 | 850 | /*************************************************************************************************/ 851 | -------------------------------------------------------------------------------- /eop_lex_stream.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2005-2007 Adobe Systems Incorporated 3 | Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt 4 | or a copy at http://stlab.adobe.com/licenses.html) 5 | */ 6 | 7 | /*************************************************************************************************/ 8 | 9 | #ifndef EOP_LEX_STREAM_HPP 10 | #define EOP_LEX_STREAM_HPP 11 | 12 | /*************************************************************************************************/ 13 | 14 | #include 15 | 16 | #include 17 | 18 | #include 19 | 20 | #include "eop_lex_stream_fwd.hpp" 21 | 22 | /*************************************************************************************************/ 23 | 24 | void swap(eop::lex_stream_t&, eop::lex_stream_t&); 25 | 26 | /*************************************************************************************************/ 27 | 28 | namespace eop { 29 | 30 | /* 31 | %---------------------------------------------------------------- 32 | 33 | comment = "//" {character} eol. 34 | whitespace = {" " | eol | comment}. 35 | 36 | identifer = (letter | "_") {letter | "_" | digit}. 37 | keyword = "case" | "const" | "do" | "else" | "enum" | "false" 38 | | "goto" | "if" | "operator" | "requires" 39 | | "return" | "struct" | "switch" | "template" 40 | | "true" | "typedef" | "typename" | "while". 41 | number = digit {digit} ["." digit {digit}]. 42 | string = """" {character} """". 43 | operator = "!=" | "&&" | "<=" | "==" | ">=" | "||" | "!" 44 | | "%" | "&" | "(" | ")" | "*" | "+" | "," | "." 45 | | "/" | ":" | ";" | "<" | "=" | ">" | "[" | "]" 46 | | "{" | "|" | "}" | "~". 47 | 48 | 49 | Notes: Currently "/*" {character} "*\/" comments are also supported 50 | Currently "#" {character} eol. is a comment. 51 | primitives = digit, letter, eol. 52 | 53 | definition of number could use some refinement. 54 | 55 | */ 56 | 57 | /*************************************************************************************************/ 58 | 59 | extern aggregate_name_t reference_k; 60 | extern aggregate_name_t pound_k; 61 | extern aggregate_name_t shift_left_k; 62 | extern aggregate_name_t shift_right_k; 63 | extern aggregate_name_t destructor_k; 64 | 65 | /*************************************************************************************************/ 66 | 67 | class lex_stream_t 68 | { 69 | public: 70 | lex_stream_t(std::istream& in, const line_position_t& position); 71 | 72 | #if !defined(ADOBE_NO_DOCUMENTATION) 73 | lex_stream_t(const lex_stream_t& rhs); 74 | 75 | ~lex_stream_t(); 76 | 77 | lex_stream_t& operator = (const lex_stream_t& rhs); 78 | #endif // !defined(ADOBE_NO_DOCUMENTATION) 79 | 80 | const stream_lex_token_t& get(); 81 | 82 | void putback(); 83 | 84 | const line_position_t& next_position(); 85 | 86 | void set_keyword_extension_lookup(const keyword_extension_lookup_proc_t& proc); 87 | 88 | #if !defined(ADOBE_NO_DOCUMENTATION) 89 | private: 90 | friend void ::swap(lex_stream_t&, lex_stream_t&); 91 | 92 | struct implementation_t; 93 | 94 | implementation_t* object_m; 95 | #endif // !defined(ADOBE_NO_DOCUMENTATION) 96 | }; 97 | 98 | /*************************************************************************************************/ 99 | 100 | } // namespace eop 101 | 102 | /*************************************************************************************************/ 103 | 104 | inline void swap(eop::lex_stream_t& x, eop::lex_stream_t& y) 105 | { 106 | std::swap(x.object_m, y.object_m); 107 | } 108 | 109 | /*************************************************************************************************/ 110 | 111 | #endif 112 | 113 | /*************************************************************************************************/ 114 | -------------------------------------------------------------------------------- /eop_lex_stream_fwd.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2005-2007 Adobe Systems Incorporated 3 | Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt 4 | or a copy at http://stlab.adobe.com/licenses.html) 5 | */ 6 | 7 | /*************************************************************************************************/ 8 | 9 | #ifndef EOP_LEX_STREAM_FWD_HPP 10 | #define EOP_LEX_STREAM_FWD_HPP 11 | 12 | /*************************************************************************************************/ 13 | 14 | #include 15 | 16 | #ifdef __MWERKS__ 17 | #pragma warn_implicitconv off 18 | #endif 19 | 20 | #include 21 | 22 | #ifdef __MWERKS__ 23 | #pragma warn_implicitconv reset 24 | #endif 25 | 26 | #include 27 | 28 | /*************************************************************************************************/ 29 | 30 | namespace eop { 31 | 32 | using namespace adobe; 33 | 34 | /*************************************************************************************************/ 35 | 36 | typedef bool (keyword_extension_lookup_proc_signature_t)(const name_t&); 37 | typedef boost::function keyword_extension_lookup_proc_t; 38 | 39 | /*************************************************************************************************/ 40 | 41 | class lex_stream_t; 42 | 43 | /*************************************************************************************************/ 44 | 45 | } // namespace eop 46 | 47 | /*************************************************************************************************/ 48 | 49 | #endif 50 | 51 | /*************************************************************************************************/ 52 | -------------------------------------------------------------------------------- /exp_parser.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2005-2007 Adobe Systems Incorporated 3 | Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt 4 | or a copy at http://stlab.adobe.com/licenses.html) 5 | */ 6 | 7 | /*************************************************************************************************/ 8 | 9 | /* 10 | REVISIT (sparent) : [Old comment - what does this mean?] I need to handle the pos_type correctly 11 | with regards to state. 12 | */ 13 | 14 | /*************************************************************************************************/ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | #include 32 | 33 | #include 34 | 35 | #include "exp_parser.hpp" 36 | #include "eop_lex_stream.hpp" 37 | 38 | #ifdef BOOST_MSVC 39 | namespace std { 40 | using ::isspace; 41 | using ::isalnum; 42 | using ::isalpha; 43 | using ::isdigit; 44 | } 45 | #endif 46 | 47 | /*************************************************************************************************/ 48 | 49 | namespace eop { 50 | 51 | /*************************************************************************************************/ 52 | 53 | class expression_parser::implementation 54 | { 55 | public: 56 | implementation(std::istream& in, const line_position_t& position) : 57 | token_stream_m(in, position) 58 | { } 59 | 60 | void set_keyword_extension_lookup(const keyword_extension_lookup_proc_t& proc) 61 | { token_stream_m.set_keyword_extension_lookup(proc); } 62 | 63 | lex_stream_t token_stream_m; 64 | 65 | typedef closed_hash_map class_name_index_t; 66 | class_name_index_t class_name_index_m; 67 | }; 68 | 69 | aggregate_name_t template_k = { "template" }; 70 | aggregate_name_t typename_k = { "typename" }; 71 | aggregate_name_t requires_k = { "requires" }; 72 | aggregate_name_t const_k = { "const" }; 73 | aggregate_name_t return_k = { "return" }; 74 | aggregate_name_t struct_k = { "struct" }; 75 | aggregate_name_t operator_k = { "operator" }; 76 | aggregate_name_t typedef_k = { "typedef" }; 77 | aggregate_name_t if_k = { "if" }; 78 | aggregate_name_t else_k = { "else" }; 79 | aggregate_name_t while_k = { "while" }; 80 | aggregate_name_t bitand_k = { "bitand" }; 81 | aggregate_name_t friend_k = { "friend" }; 82 | aggregate_name_t do_k = { "do" }; 83 | aggregate_name_t enum_k = { "enum" }; 84 | aggregate_name_t case_k = { "case" }; 85 | aggregate_name_t switch_k = { "switch" }; 86 | aggregate_name_t goto_k = { "goto" }; 87 | 88 | 89 | bool keyword_lookup(const name_t& x) 90 | { 91 | if (x == template_k) return true; 92 | if (x == typename_k) return true; 93 | if (x == requires_k) return true; 94 | if (x == const_k) return true; 95 | if (x == return_k) return true; 96 | if (x == struct_k) return true; 97 | if (x == operator_k) return true; 98 | if (x == typedef_k) return true; 99 | if (x == if_k) return true; 100 | if (x == else_k) return true; 101 | if (x == while_k) return true; 102 | if (x == bitand_k) return true; 103 | if (x == friend_k) return true; 104 | if (x == do_k) return true; 105 | if (x == enum_k) return true; 106 | if (x == case_k) return true; 107 | if (x == switch_k) return true; 108 | if (x == goto_k) return true; 109 | return false; 110 | } 111 | 112 | expression_parser::expression_parser(std::istream& in, const line_position_t& position) : 113 | object(new implementation(in, position)) 114 | { 115 | set_keyword_extension_lookup(&keyword_lookup); 116 | } 117 | 118 | expression_parser::~expression_parser() 119 | { delete object; } 120 | 121 | /*************************************************************************************************/ 122 | 123 | /* REVISIT (sparent) : Should this be const? And is there a way to specify the class to throw? */ 124 | 125 | void expression_parser::throw_exception(const char* errorString) 126 | { 127 | std::string error = errorString; 128 | 129 | error << " Found \"" << get_token().first.c_str() << "\"."; 130 | putback(); 131 | 132 | throw adobe::stream_error_t(error, next_position()); 133 | } 134 | 135 | /*************************************************************************************************/ 136 | 137 | /* REVISIT (sparent) : Should this be const? And is there a way to specify the class to throw? */ 138 | 139 | void expression_parser::throw_exception(const name_t& found, const name_t& expected) 140 | { throw_parser_exception(found, expected, next_position()); } 141 | 142 | /*************************************************************************************************/ 143 | 144 | const line_position_t& expression_parser::next_position() 145 | { 146 | return object->token_stream_m.next_position(); 147 | } 148 | 149 | /*************************************************************************************************/ 150 | 151 | void expression_parser::set_keyword_extension_lookup(const keyword_extension_lookup_proc_t& proc) 152 | { 153 | object->set_keyword_extension_lookup(proc); 154 | } 155 | 156 | /*************************************************************************************************/ 157 | 158 | // translation_unit = { declaration } eof. 159 | void expression_parser::parse() 160 | { 161 | name_t name; 162 | 163 | while (is_declaration(name)) ; 164 | require_token(eof_k); 165 | } 166 | 167 | /*************************************************************************************************/ 168 | 169 | // declaration = function_declaration | class_declaration | enum_declaration 170 | // | template_declaration. 171 | bool expression_parser::is_declaration(bool in_template) 172 | { 173 | return is_function_declaration(in_template) || is_class_declaration(in_template) 174 | || is_enum_declaration() || is_template_declaration(); 175 | } 176 | 177 | /*************************************************************************************************/ 178 | // template_declaration = template_declarator declaration. 179 | bool expression_parser::is_template_declaration() 180 | { 181 | if (!is_template_declarator()) return false; 182 | if (!is_declaration(true)) throw_exception("declaration required."); 183 | return true; 184 | } 185 | 186 | /*************************************************************************************************/ 187 | // template_declarator = "template" "<" [ function_parameter_list ] ">" [ template_constraint ]. 188 | bool expression_parser::is_template_declarator() 189 | { 190 | if (!is_keyword(template_k)) return false; 191 | require_token(less_k); 192 | is_function_parameter_list(); 193 | require_token(greater_k); 194 | is_template_constraint(); 195 | return true; 196 | } 197 | 198 | /*************************************************************************************************/ 199 | 200 | // constraint = "requires" "(" expression ")". 201 | bool expression_parser::is_template_constraint() 202 | { 203 | array_t tmp; 204 | 205 | if (!is_keyword(requires_k)) return false; 206 | require_token(open_parenthesis_k); 207 | if (!is_expression(tmp)) throw_exception("expression required."); 208 | require_token(close_parenthesis_k); 209 | return true; 210 | } 211 | 212 | /*************************************************************************************************/ 213 | // class_declaration = "struct" class_declarator [ class_body ] ";". 214 | bool expression_parser::is_class_declaration(bool in_template, bool in_class) 215 | { 216 | name_t name; 217 | 218 | if (!is_keyword(struct_k)) return false; 219 | if (!is_class_declarator(name)) throw_exception("class_name required."); 220 | if (name && !in_class) object->class_name_index_m.insert(make_pair(name, in_template)); 221 | is_class_body(name); 222 | require_token(semicolon_k); 223 | return true; 224 | } 225 | 226 | /*************************************************************************************************/ 227 | // class_declarator = identifier | expression_template. 228 | bool expression_parser::is_class_declarator(name_t& name) 229 | { 230 | return is_identifier(name) || is_expression_template(); 231 | } 232 | 233 | /*************************************************************************************************/ 234 | // class_name = identifier. 235 | bool expression_parser::is_class_name(name_t& class_name, bool& is_template) 236 | { 237 | any_regular_t x; 238 | if (!is_token(identifier_k, x)) return false; 239 | 240 | implementation::class_name_index_t::const_iterator f = object->class_name_index_m.find(x.cast()); 241 | if (f == object->class_name_index_m.end()) { putback(); return false; } 242 | class_name = f->first; 243 | is_template = f->second; 244 | return true; 245 | } 246 | 247 | /*************************************************************************************************/ 248 | // class_body = "{" { class_member } "}". 249 | bool expression_parser::is_class_body(name_t this_class) 250 | { 251 | if (!is_token(open_brace_k)) return false; 252 | while (is_class_member(this_class)) ; 253 | require_token(close_brace_k); 254 | return true; 255 | } 256 | 257 | /*************************************************************************************************/ 258 | // class_member = class_constructor | class_destructor | class_typed_member 259 | // | statement_typedef. 260 | bool expression_parser::is_class_member(name_t this_class) 261 | { 262 | return is_class_constructor(this_class) || is_class_destructor(this_class) 263 | || is_class_typed_member() || is_statement_typedef(); 264 | /* || is_class_member_template(this_class) || is_class_declaration(false, true); */ 265 | } 266 | 267 | /*************************************************************************************************/ 268 | // enum_declaration = "enum" identifier "{" identifier { "," identifier } "}" ";" 269 | bool expression_parser::is_enum_declaration() 270 | { 271 | if (!is_keyword(enum_k)) return false; 272 | require_identifier(); 273 | require_token(open_brace_k); 274 | require_identifier(); 275 | while (is_token(comma_k)) require_identifier(); 276 | require_token(close_brace_k); 277 | require_token(semicolon_k); 278 | return true; 279 | } 280 | 281 | /*************************************************************************************************/ 282 | // class_typed_member = expression ((identifier [ "[" expression "]" ] ";") | class_operator). 283 | bool expression_parser::is_class_typed_member() 284 | { 285 | array_t tmp; 286 | 287 | if (!is_expression(tmp)) return false; 288 | if (is_identifier()) { 289 | if (is_token(open_bracket_k)) { 290 | require_expression(tmp); 291 | require_token(close_bracket_k); 292 | } 293 | require_token(semicolon_k); 294 | return true; 295 | } 296 | if (!is_class_operator()) throw_exception("identifier or class_operator required.");\ 297 | return true; 298 | } 299 | 300 | /*************************************************************************************************/ 301 | // class_constructor = class_name "(" [ function_parameter_list ] ")" 302 | // [ ":" class_initializer_list ] statement_compound. 303 | bool expression_parser::is_class_constructor(name_t this_class) 304 | { 305 | bool tmp; 306 | name_t class_name; 307 | 308 | if (!is_class_name(class_name, tmp)) return false; 309 | if (class_name != this_class) { putback(); return false; } 310 | require_token(open_parenthesis_k); 311 | is_function_parameter_list(); 312 | require_token(close_parenthesis_k); 313 | if (is_token(colon_k)) { 314 | if (!is_class_initializer_list()) throw_exception("class_initializer_list required."); 315 | } 316 | if (!is_statement_compound()) throw_exception("statement_compound required."); 317 | return true; 318 | } 319 | 320 | /*************************************************************************************************/ 321 | // class_destructor = "~" class_name "(" ")" statement_compound. 322 | bool expression_parser::is_class_destructor(name_t this_class) 323 | { 324 | bool tmp; 325 | name_t class_name; 326 | 327 | if (!is_token(destructor_k)) return false; 328 | if (!is_class_name(class_name, tmp)) throw_exception("class_name required."); 329 | if (class_name != this_class) { putback(); throw_exception(class_name, this_class); } 330 | require_token(open_parenthesis_k); 331 | require_token(close_parenthesis_k); 332 | if (!is_statement_compound()) throw_exception("statement_compound required."); 333 | return true; 334 | } 335 | 336 | /*************************************************************************************************/ 337 | // class_operator = "operator" ( class_assignment | class_index | class_apply ). 338 | bool expression_parser::is_class_operator() 339 | { 340 | if (!is_keyword(operator_k)) return false; 341 | return is_class_assignment() || is_class_index() || is_class_apply(); 342 | } 343 | 344 | /*************************************************************************************************/ 345 | // class_assignment = "=" "(" function_parameter ")" statement_compound. 346 | bool expression_parser::is_class_assignment() 347 | { 348 | if (!is_token(assign_k)) return false; 349 | require_token(open_parenthesis_k); 350 | if (!is_function_parameter()) throw_exception("function_parameter required."); 351 | require_token(close_parenthesis_k); 352 | if (!is_statement_compound()) throw_exception("statement_compound required."); 353 | return true; 354 | } 355 | 356 | /*************************************************************************************************/ 357 | // class_index = "[" "]" "(" function_parameter ")" statement_compound. 358 | bool expression_parser::is_class_index() 359 | { 360 | if (!is_token(open_bracket_k)) return false; 361 | require_token(close_bracket_k); 362 | require_token(open_parenthesis_k); 363 | if (!is_function_parameter()) throw_exception("function_parameter required."); 364 | require_token(close_parenthesis_k); 365 | if (!is_statement_compound()) throw_exception("statement_compound required."); 366 | return true; 367 | } 368 | 369 | /*************************************************************************************************/ 370 | // class_apply = "(" ")" "(" [ function_parameter_list ] ")" statement_compound. 371 | bool expression_parser::is_class_apply() 372 | { 373 | if (!is_token(open_parenthesis_k)) return false; 374 | require_token(close_parenthesis_k); 375 | require_token(open_parenthesis_k); 376 | is_function_parameter_list(); 377 | require_token(close_parenthesis_k); 378 | if (!is_statement_compound()) throw_exception("statement_compound required."); 379 | return true; 380 | } 381 | 382 | /*************************************************************************************************/ 383 | // class_initializer_list = class_initializer { "," class_initializer }. 384 | bool expression_parser::is_class_initializer_list() 385 | { 386 | if (!is_class_initializer()) return false; 387 | while (is_token(comma_k)) { 388 | if (!is_class_initializer()) throw_exception("class_initializer required."); 389 | } 390 | return true; 391 | } 392 | 393 | /*************************************************************************************************/ 394 | // class_initializer = identifer "(" [expression_list] ")". 395 | bool expression_parser::is_class_initializer() 396 | { 397 | array_t tmp; 398 | 399 | if (!is_identifier()) return false; 400 | require_token(open_parenthesis_k); 401 | is_expression_list(tmp); 402 | require_token(close_parenthesis_k); 403 | return true; 404 | } 405 | 406 | /*************************************************************************************************/ 407 | 408 | #if 0 409 | // class_friend = "friend" function_declaration. 410 | bool expression_parser::is_class_friend() 411 | { 412 | if (!is_keyword(friend_k)) return false; 413 | if (!is_function_declaration(false)) throw_exception("function_declaration required."); 414 | return true; 415 | } 416 | #endif 417 | 418 | /*************************************************************************************************/ 419 | 420 | #if 0 421 | // class_member_template = template_declarator class_member. 422 | bool expression_parser::is_class_member_template(name_t this_class) 423 | { 424 | if (!is_template_declarator()) return false; 425 | if (!is_class_member(this_class)) throw_exception("class_member required."); 426 | return true; 427 | } 428 | #endif 429 | 430 | /*************************************************************************************************/ 431 | 432 | // function_declaration = expression function_name "(" [ function_parameter_list ] ")" 433 | // (statement_compound | ";"). 434 | bool expression_parser::is_function_declaration(bool in_template) 435 | { 436 | array_t tmp; 437 | name_t name; 438 | 439 | if (!is_expression(tmp)) return false; 440 | if (!is_function_name(name)) throw_exception("function_name required."); 441 | if (name) object->class_name_index_m.insert(make_pair(name, in_template)); 442 | require_token(open_parenthesis_k); 443 | is_function_parameter_list(); 444 | require_token(close_parenthesis_k); 445 | if (!(is_statement_compound() || is_token(semicolon_k))) { 446 | throw_exception("statement_compound or semicolon required."); 447 | } 448 | return true; 449 | } 450 | 451 | /*************************************************************************************************/ 452 | // function_name = identifier | class_name |function_operator. 453 | bool expression_parser::is_function_name(name_t& name) 454 | { 455 | name_t tmp; 456 | bool is_template; 457 | 458 | return is_identifier(name) || is_class_name(tmp, is_template) || is_function_operator(); 459 | } 460 | 461 | /*************************************************************************************************/ 462 | // function_operator = "operator" ("==" | "<" | "+" | "-" | "*" | "/" | "%"). 463 | bool expression_parser::is_function_operator() 464 | { 465 | if (!is_keyword(operator_k)) return false; 466 | if (!(is_token(equal_k) || is_token(less_k) || is_token(add_k) || is_token(subtract_k) 467 | || is_token(multiply_k) || is_token(divide_k) || is_token(modulus_k))) { 468 | throw_exception("'==', '<', '+', '-', '*', '/', or '%' required."); 469 | } 470 | return true; 471 | } 472 | 473 | /*************************************************************************************************/ 474 | // function_parameter_list = function_parameter { "," function_parameter }. 475 | bool expression_parser::is_function_parameter_list() 476 | { 477 | if (!is_function_parameter()) return false; 478 | while (is_token(comma_k)) { 479 | if (!is_function_parameter()) throw_exception("function_parameter required."); 480 | } 481 | return true; 482 | } 483 | 484 | /*************************************************************************************************/ 485 | // function_parameter = expression [ identifier ]. 486 | bool expression_parser::is_function_parameter() 487 | { 488 | array_t tmp; 489 | 490 | if (!is_expression(tmp)) return false; 491 | is_identifier(); 492 | return true; 493 | } 494 | 495 | /*************************************************************************************************/ 496 | // statement = [identifier ":"] statement_expression | statement_return 497 | // | statement_typedef | statement_conditional | statement_while 498 | // | statement_do | statement_compound | statement_switch 499 | // | statement_goto. 500 | bool expression_parser::is_statement() 501 | { 502 | bool has_label = false; 503 | 504 | if (is_identifier()) { 505 | if (is_token(colon_k)) has_label = true; 506 | else putback(); // LL(2) 507 | } 508 | 509 | if (is_statement_expression() || is_statement_return() || is_statement_typedef() 510 | || is_statement_conditional() || is_statement_while() || is_statement_do() 511 | || is_statement_compound() || is_statement_switch() || is_statement_goto()) return true; 512 | 513 | /* 514 | REVISIT (sparent) : inablity to name this group is a good reason to split statement from 515 | labeled statement. 516 | */ 517 | if (has_label) throw_exception("statement required."); 518 | 519 | return false; 520 | } 521 | 522 | /*************************************************************************************************/ 523 | // statement_expression = expression [ statement_assignment | statement_constructor] ";". 524 | bool expression_parser::is_statement_expression() 525 | { 526 | array_t tmp; 527 | 528 | if (!is_expression(tmp)) return false; 529 | is_statement_assignment() || is_statement_constructor(); 530 | require_token(semicolon_k); 531 | return true; 532 | } 533 | 534 | /*************************************************************************************************/ 535 | // statement_assignment = "=" expression. 536 | bool expression_parser::is_statement_assignment() 537 | { 538 | array_t tmp; 539 | 540 | if (!is_token(assign_k)) return false; 541 | require_expression(tmp); 542 | return true; 543 | } 544 | 545 | /*************************************************************************************************/ 546 | // statement_constructor = identifier [ ("(" expression_list ")") | statement_assignment 547 | // | ("[" expression "]") ]. 548 | bool expression_parser::is_statement_constructor() 549 | { 550 | array_t tmp; 551 | 552 | if (!is_identifier()) return false; 553 | if (is_token(open_parenthesis_k)) { 554 | if (!is_expression_list(tmp)) throw_exception("expression_list required."); 555 | require_token(close_parenthesis_k); 556 | } else if (is_statement_assignment()) { 557 | } else if (is_token(open_bracket_k)) { 558 | require_expression(tmp); 559 | require_token(close_bracket_k); 560 | } 561 | return true; 562 | } 563 | 564 | /*************************************************************************************************/ 565 | // statement_return = "return" [ expression ] ";". 566 | bool expression_parser::is_statement_return() 567 | { 568 | array_t tmp; 569 | 570 | if (!is_keyword(return_k)) return false; 571 | is_expression(tmp); 572 | require_token(semicolon_k); 573 | return true; 574 | } 575 | 576 | /*************************************************************************************************/ 577 | // statement_typedef = "typedef" expression identifier ";". 578 | bool expression_parser::is_statement_typedef() 579 | { 580 | array_t tmp; 581 | 582 | if (!is_keyword(typedef_k)) return false; 583 | require_expression(tmp); 584 | require_identifier(); 585 | require_token(semicolon_k); 586 | return true; 587 | } 588 | 589 | /*************************************************************************************************/ 590 | // statement_conditional = "if" "(" expression ")" statement [ "else" statement ]. 591 | bool expression_parser::is_statement_conditional() 592 | { 593 | array_t tmp; 594 | 595 | if (!is_keyword(if_k)) return false; 596 | require_token(open_parenthesis_k); 597 | require_expression(tmp); 598 | require_token(close_parenthesis_k); 599 | if (!is_statement()) throw_exception("statement required."); 600 | if (is_keyword(else_k)) { 601 | if (!is_statement()) throw_exception("statement required."); 602 | } 603 | return true; 604 | } 605 | 606 | /*************************************************************************************************/ 607 | // statement_while = "while" "(" expression ")" statement. 608 | bool expression_parser::is_statement_while() 609 | { 610 | array_t tmp; 611 | 612 | if (!is_keyword(while_k)) return false; 613 | require_token(open_parenthesis_k); 614 | require_expression(tmp); 615 | require_token(close_parenthesis_k); 616 | if (!is_statement()) throw_exception("statement required."); 617 | return true; 618 | } 619 | 620 | /*************************************************************************************************/ 621 | // statement_do = "do" statement "while" "(" expression ")" ";". 622 | bool expression_parser::is_statement_do() 623 | { 624 | array_t tmp; 625 | 626 | if (!is_keyword(do_k)) return false; 627 | if (!is_statement()) throw_exception("statement required."); 628 | require_keyword(while_k); 629 | require_token(open_parenthesis_k); 630 | require_expression(tmp); 631 | require_token(close_parenthesis_k); 632 | require_token(semicolon_k); 633 | return true; 634 | } 635 | 636 | /*************************************************************************************************/ 637 | // statement_compound = "{" { statement } "}". 638 | bool expression_parser::is_statement_compound() 639 | { 640 | if (!is_token(open_brace_k)) return false; 641 | while (is_statement()) ; 642 | require_token(close_brace_k); 643 | return true; 644 | } 645 | 646 | /*************************************************************************************************/ 647 | // statement_switch = "switch" "(" expression ")" "{" { statement_case } "}". 648 | bool expression_parser::is_statement_switch() 649 | { 650 | array_t tmp; 651 | 652 | if (!is_keyword(switch_k)) return false; 653 | require_token(open_parenthesis_k); 654 | require_expression(tmp); 655 | require_token(close_parenthesis_k); 656 | require_token(open_brace_k); 657 | while (is_statement_case()); 658 | require_token(close_brace_k); 659 | return true; 660 | } 661 | 662 | /*************************************************************************************************/ 663 | // statement_case = "case" expression ":" { statement }. 664 | bool expression_parser::is_statement_case() 665 | { 666 | array_t tmp; 667 | 668 | if (!is_keyword(case_k)) return false; 669 | require_expression(tmp); 670 | require_token(colon_k); 671 | while (is_statement()) ; 672 | return true; 673 | } 674 | 675 | /*************************************************************************************************/ 676 | // statement_goto = "goto" identifier ";" 677 | bool expression_parser::is_statement_goto() 678 | { 679 | if (!is_keyword(goto_k)) return false; 680 | require_identifier(); 681 | require_token(semicolon_k); 682 | return true; 683 | } 684 | 685 | /*************************************************************************************************/ 686 | // expression = expression_and { "||" expression_and }. 687 | bool expression_parser::is_expression(array_t& expression_stack) 688 | { 689 | if (!is_expression_and(expression_stack)) return false; 690 | 691 | while (is_token(or_k)) 692 | { 693 | array_t operand2; 694 | if (!is_expression_and(operand2)) throw_exception("expression_and required."); 695 | push_back(expression_stack, operand2); 696 | expression_stack.push_back(any_regular_t(or_k)); 697 | } 698 | 699 | return true; 700 | } 701 | 702 | void expression_parser::require_expression(array_t& expression_stack) 703 | { 704 | if (!is_expression(expression_stack)) 705 | { 706 | throw_exception("expression required."); 707 | } 708 | } 709 | 710 | /*************************************************************************************************/ 711 | 712 | // expression_and = expression_equality { "&&" expression_equality }. 713 | bool expression_parser::is_expression_and(array_t& expression_stack) 714 | { 715 | if (!is_expression_equality(expression_stack)) return false; 716 | 717 | while (is_token(and_k)) 718 | { 719 | array_t operand2; 720 | if (!is_expression_equality(operand2)) throw_exception("expression_bit_and required."); 721 | push_back(expression_stack, operand2); 722 | expression_stack.push_back(any_regular_t(and_k)); 723 | } 724 | 725 | return true; 726 | } 727 | 728 | /*************************************************************************************************/ 729 | 730 | // expression_equality = expression_relational { ("==" | "!=") expression_relational }. 731 | bool expression_parser::is_expression_equality(array_t& expression_stack) 732 | { 733 | if (!is_expression_relational(expression_stack)) return false; 734 | 735 | bool is_equal = false; 736 | while ((is_equal = is_token(equal_k)) || is_token(not_equal_k)) 737 | { 738 | if (!is_expression_relational(expression_stack)) throw_exception("Primary required."); 739 | expression_stack.push_back(is_equal ? any_regular_t(equal_k) : any_regular_t(not_equal_k)); 740 | } 741 | 742 | return true; 743 | } 744 | 745 | /*************************************************************************************************/ 746 | 747 | // expression_relational = expression_additive { ("<" | ">" | "<=" | ">=") expression_additive }. 748 | bool expression_parser::is_expression_relational(array_t& expression_stack) 749 | { 750 | if (!is_expression_additive(expression_stack)) return false; 751 | 752 | name_t operator_l; 753 | 754 | while (is_relational_operator(operator_l)) 755 | { 756 | if (!is_expression_additive(expression_stack)) throw_exception("expression_shift required."); 757 | expression_stack.push_back(any_regular_t(operator_l)); 758 | } 759 | 760 | return true; 761 | } 762 | /*************************************************************************************************/ 763 | // expression_additive = expression_multiplicative { additive_operator expression_multiplicative }. 764 | bool expression_parser::is_expression_additive(array_t& expression_stack) 765 | { 766 | if (!is_expression_multiplicative(expression_stack)) return false; 767 | 768 | name_t operator_l; 769 | 770 | while (is_additive_operator(operator_l)) 771 | { 772 | if (!is_expression_multiplicative(expression_stack)) throw_exception("Primary required."); 773 | expression_stack.push_back(any_regular_t(operator_l)); 774 | 775 | } 776 | 777 | return true; 778 | } 779 | 780 | /*************************************************************************************************/ 781 | // expression_multiplicative = expression_unary { ("*" | "/" | "%") expression_unary }. 782 | bool expression_parser::is_expression_multiplicative(array_t& expression_stack) 783 | { 784 | if (!is_expression_unary(expression_stack)) return false; 785 | 786 | name_t operator_l; 787 | 788 | while (is_multiplicative_operator(operator_l)) 789 | { 790 | if (!is_expression_unary(expression_stack)) throw_exception("Primary required."); 791 | expression_stack.push_back(any_regular_t(operator_l)); 792 | 793 | } 794 | 795 | return true; 796 | } 797 | 798 | /*************************************************************************************************/ 799 | // expression_unary = expression_postfix | ( ("+" | "-" | "!" | "*" | "&" | "const") expression_unary). 800 | bool expression_parser::is_expression_unary(array_t& expression_stack) 801 | { 802 | if (is_expression_postfix(expression_stack)) return true; 803 | 804 | name_t operator_l; 805 | 806 | if (is_unary_operator(operator_l)) 807 | { 808 | if (!is_expression_unary(expression_stack)) throw_exception("Unary expression required."); 809 | if (operator_l != add_k) 810 | { 811 | expression_stack.push_back(any_regular_t(operator_l)); 812 | 813 | } 814 | return true; 815 | } 816 | 817 | return false; 818 | } 819 | 820 | /*************************************************************************************************/ 821 | // expression_postfix = expression_primary { ("[" expression "]") | ("." identifier) | ("(" [expression_list] ")") | "&" }. 822 | bool expression_parser::is_expression_postfix(array_t& expression_stack) 823 | { 824 | if (!is_expression_primary(expression_stack)) return false; 825 | 826 | while (true) 827 | { 828 | if (is_token(open_bracket_k)) 829 | { 830 | require_expression(expression_stack); 831 | require_token(close_bracket_k); 832 | } 833 | else if (is_token(dot_k)) 834 | { 835 | any_regular_t result; 836 | require_identifier(result); 837 | expression_stack.push_back(result); 838 | } 839 | else if (is_token(open_parenthesis_k)) 840 | { 841 | is_expression_list(expression_stack); 842 | require_token(close_parenthesis_k); 843 | } 844 | else if (is_token(reference_k)) { } 845 | else break; 846 | 847 | expression_stack.push_back(any_regular_t(index_k)); 848 | 849 | } 850 | 851 | return true; 852 | } 853 | 854 | /*************************************************************************************************/ 855 | // expression_primary = number | "true" | "false" | string | identifier | "typename" 856 | // | expression_template | ("(" expression ")"). 857 | 858 | bool expression_parser::is_expression_primary(array_t& expression_stack) 859 | { 860 | any_regular_t result; // empty result used if is_keyword(empty_k) 861 | 862 | if (is_token(number_k, result) 863 | || is_boolean(result) 864 | || is_token(string_k, result) 865 | || is_identifier(result)) 866 | { 867 | expression_stack.push_back(move(result)); 868 | return true; 869 | } 870 | if (is_keyword(typename_k)) return true; 871 | if (is_expression_template()) return true; 872 | if (is_token(open_parenthesis_k)) { 873 | require_expression(expression_stack); 874 | require_token(close_parenthesis_k); 875 | return true; 876 | } 877 | 878 | return false; 879 | } 880 | 881 | /*************************************************************************************************/ 882 | // expression_template = class_name [ "<" expression_list ">" ]. 883 | bool expression_parser::is_expression_template() 884 | { 885 | bool is_template; 886 | name_t class_name; 887 | 888 | if (!is_class_name(class_name, is_template)) return false; 889 | if (is_template) { 890 | if (!is_token(less_k)) return true; 891 | if (!is_expression_additive_list()) throw_exception("expression_additive_list required."); 892 | require_token(greater_k); 893 | } 894 | return true; 895 | } 896 | 897 | /*************************************************************************************************/ 898 | // expression_additive_list = expression_additive { "," expression_additive }. 899 | bool expression_parser::is_expression_additive_list() 900 | { 901 | array_t tmp; 902 | 903 | if (!is_expression_additive(tmp)) return false; 904 | 905 | while (is_token(comma_k)) 906 | { 907 | if (!is_expression_additive(tmp)) throw_exception("expression_additive required."); 908 | } 909 | return true; 910 | } 911 | 912 | /*************************************************************************************************/ 913 | // expression_list = expression { "," expression }. 914 | bool expression_parser::is_expression_list(array_t& expression_stack) 915 | { 916 | if (!is_expression(expression_stack)) return false; 917 | 918 | std::size_t count = 1; 919 | 920 | while (is_token(comma_k)) 921 | { 922 | require_expression(expression_stack); 923 | ++count; 924 | } 925 | 926 | expression_stack.push_back(any_regular_t(count)); 927 | expression_stack.push_back(any_regular_t(array_k)); 928 | 929 | return true; 930 | } 931 | 932 | /*************************************************************************************************/ 933 | 934 | bool expression_parser::is_boolean(any_regular_t& result) 935 | { 936 | if (is_keyword(true_k)) 937 | { result = any_regular_t(true); return true; } 938 | else if (is_keyword(false_k)) 939 | { result = any_regular_t(false); return true; } 940 | 941 | return false; 942 | } 943 | 944 | /*************************************************************************************************/ 945 | 946 | // relational_operator = "<" | ">" | "<=" | ">=". 947 | bool expression_parser::is_relational_operator(name_t& name_result) 948 | { 949 | const stream_lex_token_t& result (get_token()); 950 | 951 | name_t name = result.first; 952 | if (name == less_k || name == greater_k || name == less_equal_k || name == greater_equal_k) 953 | { 954 | name_result = name; 955 | return true; 956 | } 957 | putback(); 958 | return false; 959 | } 960 | 961 | /*************************************************************************************************/ 962 | bool expression_parser::is_operator_shift(name_t& name_result) 963 | { 964 | const stream_lex_token_t& result (get_token()); 965 | 966 | name_t name = result.first; 967 | if (name == shift_left_k || name == shift_right_k) 968 | { 969 | name_result = name; 970 | return true; 971 | } 972 | putback(); 973 | return false; 974 | } 975 | 976 | /*************************************************************************************************/ 977 | 978 | // additive_operator = "+" | "-". 979 | bool expression_parser::is_additive_operator(name_t& name_result) 980 | { 981 | const stream_lex_token_t& result (get_token()); 982 | 983 | name_t name = result.first; 984 | if (name == add_k || name == subtract_k) 985 | { 986 | name_result = name; 987 | return true; 988 | } 989 | putback(); 990 | return false; 991 | } 992 | 993 | /*************************************************************************************************/ 994 | 995 | // multiplicative_operator = "*" | "/" | "%". 996 | bool expression_parser::is_multiplicative_operator(name_t& name_result) 997 | { 998 | const stream_lex_token_t& result (get_token()); 999 | 1000 | name_t name = result.first; 1001 | if (name == multiply_k || name == divide_k || name == modulus_k) 1002 | { 1003 | name_result = name; 1004 | return true; 1005 | } 1006 | putback(); 1007 | return false; 1008 | } 1009 | 1010 | /*************************************************************************************************/ 1011 | 1012 | // unary_operator = "+" | "-" | "!" | "*" | "&" | "const". 1013 | bool expression_parser::is_unary_operator(name_t& name_result) 1014 | { 1015 | const stream_lex_token_t& result (get_token()); 1016 | 1017 | name_t name = result.first; 1018 | if (name == subtract_k) 1019 | { 1020 | name_result = unary_negate_k; 1021 | return true; 1022 | } 1023 | else if (name == not_k || name == add_k || name == multiply_k /* || name == reference_k */) 1024 | { 1025 | name_result = name; 1026 | return true; 1027 | } 1028 | else if (name == keyword_k && result.second.cast() == const_k) { 1029 | name_result = const_k; 1030 | return true; 1031 | } 1032 | putback(); 1033 | return false; 1034 | } 1035 | 1036 | /*************************************************************************************************/ 1037 | 1038 | /* 1039 | REVISIT (sparent) : There should be a turn the simple lexical calls into templates 1040 | */ 1041 | 1042 | bool expression_parser::is_identifier(any_regular_t& result) 1043 | { 1044 | const stream_lex_token_t& token = get_token(); 1045 | 1046 | if (token.first == identifier_k) 1047 | { 1048 | if (!object->class_name_index_m.count(token.second.cast())) { 1049 | result = token.second; 1050 | return true; 1051 | } 1052 | } 1053 | 1054 | putback(); 1055 | return false; 1056 | } 1057 | 1058 | void expression_parser::require_identifier(any_regular_t& result) 1059 | { 1060 | if (!is_identifier(result)) throw_exception("identifier required."); 1061 | } 1062 | 1063 | bool expression_parser::is_identifier(name_t& name_result) 1064 | { 1065 | const stream_lex_token_t& result (get_token()); 1066 | 1067 | if (result.first == identifier_k) 1068 | { 1069 | name_result = result.second.cast(); 1070 | if (!object->class_name_index_m.count(name_result)) return true; 1071 | } 1072 | 1073 | putback(); 1074 | return false; 1075 | } 1076 | 1077 | bool expression_parser::is_identifier() 1078 | { 1079 | name_t tmp; 1080 | return is_identifier(tmp); 1081 | } 1082 | 1083 | void expression_parser::require_identifier() 1084 | { 1085 | if (!is_identifier()) throw_exception("identifier required."); 1086 | } 1087 | 1088 | 1089 | bool expression_parser::is_lead_comment(std::string& string_result) 1090 | { 1091 | const stream_lex_token_t& result (get_token()); 1092 | 1093 | if (result.first == lead_comment_k) 1094 | { 1095 | string_result = result.second.cast(); 1096 | return true; 1097 | } 1098 | 1099 | putback(); 1100 | return false; 1101 | } 1102 | 1103 | bool expression_parser::is_trail_comment(std::string& string_result) 1104 | { 1105 | const stream_lex_token_t& result (get_token()); 1106 | 1107 | if (result.first == trail_comment_k) 1108 | { 1109 | string_result = result.second.cast(); 1110 | return true; 1111 | } 1112 | 1113 | putback(); 1114 | return false; 1115 | } 1116 | 1117 | /*************************************************************************************************/ 1118 | 1119 | bool expression_parser::is_token(name_t tokenName, any_regular_t& tokenValue) 1120 | { 1121 | const stream_lex_token_t& result (get_token()); 1122 | if (result.first == tokenName) 1123 | { 1124 | tokenValue = result.second; 1125 | return true; 1126 | } 1127 | putback(); 1128 | return false; 1129 | } 1130 | 1131 | /*************************************************************************************************/ 1132 | 1133 | bool expression_parser::is_token(name_t tokenName) 1134 | { 1135 | const stream_lex_token_t& result (get_token()); 1136 | if (result.first == tokenName) 1137 | { 1138 | return true; 1139 | } 1140 | putback(); 1141 | return false; 1142 | } 1143 | 1144 | /*************************************************************************************************/ 1145 | 1146 | bool expression_parser::is_keyword(name_t keyword_name) 1147 | { 1148 | const stream_lex_token_t& result (get_token()); 1149 | if (result.first == keyword_k && result.second.cast() == keyword_name) return true; 1150 | putback(); 1151 | return false; 1152 | } 1153 | 1154 | /*************************************************************************************************/ 1155 | 1156 | const stream_lex_token_t& expression_parser::get_token() 1157 | { 1158 | return object->token_stream_m.get(); 1159 | } 1160 | 1161 | /*************************************************************************************************/ 1162 | 1163 | void expression_parser::putback() 1164 | { 1165 | object->token_stream_m.putback(); 1166 | } 1167 | 1168 | /*************************************************************************************************/ 1169 | 1170 | void expression_parser::require_token(name_t tokenName, any_regular_t& tokenValue) 1171 | { 1172 | const stream_lex_token_t& result (get_token()); 1173 | if (result.first != tokenName) 1174 | { 1175 | putback(); 1176 | throw_exception(tokenName, result.first); 1177 | } 1178 | 1179 | tokenValue = result.second; 1180 | } 1181 | 1182 | /*************************************************************************************************/ 1183 | 1184 | void expression_parser::require_keyword(name_t keyword_name) 1185 | { 1186 | const stream_lex_token_t& result (get_token()); 1187 | name_t result_name; 1188 | name_t result_token = result.first; 1189 | if (result_token == keyword_k) { 1190 | result_name = result.second.cast(); 1191 | if (result_name == keyword_name) return; 1192 | putback(); 1193 | throw_exception(keyword_name, result_name); 1194 | } 1195 | putback(); 1196 | throw_exception(keyword_name, result_token); 1197 | } 1198 | 1199 | /*************************************************************************************************/ 1200 | 1201 | void expression_parser::require_token(name_t tokenName) 1202 | { 1203 | const stream_lex_token_t& result (get_token()); 1204 | if (result.first == tokenName) return; 1205 | 1206 | putback(); 1207 | throw_exception(tokenName, result.first); 1208 | } 1209 | 1210 | /*************************************************************************************************/ 1211 | 1212 | } // namespace eop 1213 | 1214 | /*************************************************************************************************/ 1215 | -------------------------------------------------------------------------------- /exp_parser.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2005-2007 Adobe Systems Incorporated 3 | Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt 4 | or a copy at http://stlab.adobe.com/licenses.html) 5 | */ 6 | 7 | /*************************************************************************************************/ 8 | 9 | #ifndef EOP_EXPRESSION_PARSER_HPP 10 | #define EOP_EXPRESSION_PARSER_HPP 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #include "eop_lex_stream_fwd.hpp" 21 | 22 | /*************************************************************************************************/ 23 | 24 | namespace eop { 25 | 26 | using namespace adobe; 27 | 28 | /*************************************************************************************************/ 29 | 30 | /*! \page expression_language Expression Language 31 | 32 | \code 33 | 34 | translation_unit = { declaration } eof. 35 | 36 | %---------------------------------------------------------------- 37 | 38 | %---------------------------------------------------------------- 39 | 40 | template = template_decl declaration. 41 | template_decl = "template" "<" [parameter_list] ">" [constraint]. 42 | constraint = "requires" "(" expression ")". 43 | 44 | declaration = template | structure | enumeration | function. 45 | 46 | 47 | %---------------------------------------------------------------- 48 | structure = "struct" structure_decl [structure_body] ";". 49 | structure_decl = identifier | template_name. 50 | structure_name = identifier. 51 | structure_body = "{" {member} "}". 52 | member = constructor | destructor | typed_member 53 | | typedef. 54 | typed_member = expression ( 55 | (identifier ["[" expression "]"] ";") 56 | | member_operator). 57 | constructor = structure_name "(" [parameter_list] ")" 58 | [":" initializer_list] compound. 59 | destructor = "~" structure_name "(" ")" compound. 60 | member_operator = "operator" (assignment_body | index | apply). 61 | assignment_body = "=" "(" parameter ")" compound. 62 | index = "[" "]" "(" parameter ")" compound. 63 | apply = "(" ")" "(" [ parameter_list ] ")" compound. 64 | initializer_list = initializer {"," initializer}. 65 | initializer = identifer "(" [expression_list] ")". 66 | 67 | %---------------------------------------------------------------- 68 | enumeration = "enum" identifier "{" identifer_list "}" ";". 69 | identifer_list = identifier {"," identifier}. 70 | 71 | %---------------------------------------------------------------- 72 | function = expression function_name 73 | "(" [parameter_list] ")" (compound | ";"). 74 | function_name = identifier | structure_name | operator. 75 | operator = "operator" ("==" | "<" | "+" | "-" | "*" | "/" 76 | | "%"). 77 | parameter_list = parameter {"," parameter}. 78 | parameter = expression [identifier]. 79 | %---------------------------------------------------------------- 80 | 81 | statement = [identifier ":"] (simple_statement 82 | | control_statement | typedef). 83 | simple_statement = expression [assignment | construction] ";". 84 | assignment = "=" expression. 85 | construction = identifier [("(" expression_list ")") 86 | | assignment | ("[" expression "]")]. 87 | control_statement = return | conditional | while | do 88 | | compound | switch | goto. 89 | return = "return" [expression] ";". 90 | typedef = "typedef" expression identifier ";". 91 | conditional = "if" "(" expression ")" statement 92 | ["else" statement]. 93 | while = "while" "(" expression ")" statement. 94 | do = "do" statement 95 | "while" "(" expression ")" ";". 96 | compound = "{" {statement} "}". 97 | switch = "switch" "(" expression ")" "{" {case} "}". 98 | case = "case" expression ":" {statement}. 99 | goto = "goto" identifier ";" 100 | 101 | %---------------------------------------------------------------- 102 | 103 | expression = and {"||" and}. 104 | and = equality {"&&" equality}. 105 | equality = relational {("==" | "!=") relational}. 106 | relational = additive {("<" | ">" | "<=" | ">=") additive}. 107 | additive = multiplicative {("+" | "-") multiplicative}. 108 | multiplicative = unary {("*" | "/" | "%") unary}. 109 | unary = postfix 110 | | ( ("+" | "-" | "!" | "*" | "const") unary). 111 | postfix = primary {("[" expression "]") 112 | | ("." identifier) 113 | | ("(" [expression_list] ")") | "&"}. 114 | primary = number | "true" | "false" | string 115 | | identifier | "typename" | template_name 116 | | ("(" expression ")"). 117 | template_name = structure_name ["<" additive_list ">"]. 118 | additive_list = additive {"," additive}. 119 | expression_list = expression {"," expression}. 120 | 121 | Intrinsic Functions: 122 | pointer(T) -> T* 123 | bit_and 124 | bit_or 125 | bit_complement 126 | bit_shift_left 127 | bit_shift_right 128 | ? reference(T) ->T& 129 | 130 | Notes: 131 | class_constructor 132 | class_name must match current class name. 133 | 134 | 135 | expression_template 136 | uses expression_shift_list to avoid ambiguity with >. Use parenthesis for more complex 137 | expressions. For example T<(a == b)>. 138 | 139 | if class_name names a template then the optional portion is optional, otherwise 140 | it is ommited. 141 | 142 | function_name 143 | points out need to change the name of class_name - perhaps 144 | 145 | class_friend can go away? 146 | 147 | class_friend = "friend" function_declaration. 148 | 149 | 150 | 151 | \endcode 152 | 153 | */ 154 | 155 | /*************************************************************************************************/ 156 | 157 | class expression_parser : public boost::noncopyable 158 | { 159 | public: 160 | 161 | expression_parser(std::istream& in, const line_position_t& position); 162 | 163 | ~expression_parser(); 164 | 165 | const line_position_t& next_position(); 166 | 167 | 168 | // translation_unit = { declaration } eof. 169 | void parse(); 170 | 171 | // template_declaration = template_declarator declaration. 172 | bool is_template_declaration(); 173 | // template_declarator = "template" "<" [ function_parameter_list ] ">" [ template_constraint ]. 174 | bool is_template_declarator(); 175 | // template_constraint = "requires" "(" expression ")". 176 | bool is_template_constraint(); 177 | 178 | // declaration = function_declaration | class_declaration | enumeration 179 | // | template_declaration. 180 | bool is_declaration(bool); 181 | 182 | // class_declaration = "struct" class_declarator [ class_body ] ";". 183 | bool is_class_declaration(bool in_template, bool in_class = false); 184 | // class_declarator = identifier | expession_template. 185 | bool is_class_declarator(name_t&); 186 | // class_name = identifier. 187 | bool is_class_name(name_t&, bool&); 188 | // class_body = "{" { class_member } "}". 189 | bool is_class_body(name_t); 190 | // class_member = class_constructor | class_destructor | class_typed_member 191 | // | statement_typedef. 192 | bool is_class_member(name_t); 193 | // class_typed_member = expression ((identifier [ "[" expression "]" ] ";") | class_operator). 194 | bool is_class_typed_member(); 195 | // class_constructor = class_name "(" [ function_parameter_list ] ")" 196 | // [ ":" class_initializer_list ] statement_compound. 197 | bool is_class_constructor(name_t); 198 | // class_destructor = "~" class_name "(" ")" statement_compound. 199 | bool is_class_destructor(name_t); 200 | // class_operator = "operator" ( class_assignment | class_index | class_apply ). 201 | bool is_class_operator(); 202 | // class_assignment = "=" "(" function_parameter ")" statement_compound. 203 | bool is_class_assignment(); 204 | // class_index = "[" "]" "(" function_parameter ")" statement_compound. 205 | bool is_class_index(); 206 | // class_apply = "(" ")" "(" [ function_parameter_list ] ")" statement_compound. 207 | bool is_class_apply(); 208 | // class_initializer_list = class_initializer { "," class_initializer }. 209 | bool is_class_initializer_list(); 210 | // class_initializer = identifer "(" [expression_list] ")". 211 | bool is_class_initializer(); 212 | #if 0 213 | // class_friend = "friend" function_declaration. 214 | bool is_class_friend(); 215 | #endif 216 | #if 0 217 | // class_member_template = template_declarator class_member. 218 | bool is_class_member_template(name_t); 219 | #endif 220 | 221 | // enumeration = "enum" identifier "{" identifier { "," identifier } "}" ";" 222 | bool is_enum_declaration(); 223 | 224 | // function_declaration = expression function_name "(" [ function_parameter_list ] ")" 225 | // (statement_compound | ";"). 226 | bool is_function_declaration(bool in_template); 227 | // function_name = identifier | class_name | function_operator. 228 | bool is_function_name(name_t&); 229 | // function_operator = "operator" ("==" | "<" | "+" | "-" | "*" | "/" | "%"). 230 | bool is_function_operator(); 231 | // function_parameter_list = function_parameter { "," function_parameter }. 232 | bool is_function_parameter_list(); 233 | // function_parameter = expression [ identifier ]. 234 | bool is_function_parameter(); 235 | 236 | // statement = [identifier ":"] statement_expression | statement_return 237 | // | statement_typedef | statement_conditional | statement_while 238 | // | statement_do | statement_compound | statement_switch 239 | // | statement_goto. 240 | bool is_statement(); 241 | // statement_expression = expression [ statement_assignment | statement_constructor] ";". 242 | bool is_statement_expression(); 243 | // statement_assignment = "=" expression. 244 | bool is_statement_assignment(); 245 | // statement_constructor = identifier [ ("(" expression_list ")") | statement_assignment 246 | // | ("[" expression "]") ]. 247 | bool is_statement_constructor(); 248 | // statement_return = "return" [ expression ] ";". 249 | bool is_statement_return(); 250 | // statement_typedef = "typedef" expression identifier ";". 251 | bool is_statement_typedef(); 252 | // statement_conditional = "if" "(" expression ")" statement [ "else" statement ]. 253 | bool is_statement_conditional(); 254 | // statement_while = "while" "(" expression ")" statement. 255 | bool is_statement_while(); 256 | // statement_do = "do" statement "while" "(" expression ")" ";". 257 | bool is_statement_do(); 258 | // statement_compound = "{" { statement } "}". 259 | bool is_statement_compound(); 260 | // statement_switch = "switch" "(" expression ")" "{" { statement_case } "}". 261 | bool is_statement_switch(); 262 | // statement_case = "case" expression ":" { statement }. 263 | bool is_statement_case(); 264 | // statement_goto = "goto" identifier ";" 265 | bool is_statement_goto(); 266 | 267 | // expression = expression_and { "||" expression_and }. 268 | bool is_expression(array_t&); 269 | void require_expression(array_t&); 270 | 271 | // expression_and = expression_equality { "&&" expression_equality }. 272 | bool is_expression_and(array_t&); 273 | // expression_bit_and = expression_equality { "bitand" expression_equality }. 274 | bool is_expression_bit_and(array_t&); 275 | // expression_equality = expression_relational { ("==" | "!=") expression_relational }. 276 | bool is_expression_equality(array_t&); 277 | // expression_relational = expression_additive { ("<" | ">" | "<=" | ">=") expression_additive }. 278 | bool is_expression_relational(array_t&); 279 | // expression_additive = expression_multiplicative { ("+" | "-") expression_multiplicative }. 280 | bool is_expression_additive(array_t&); 281 | bool is_additive_operator(name_t&); 282 | // expression_multiplicative = expression_unary { ("*" | "/" | "%") expression_unary }. 283 | bool is_expression_multiplicative(array_t&); 284 | bool is_multiplicative_operator(name_t&); 285 | // expression_unary = expression_postfix | ( ("+" | "-" | "!" | "*" | "&" | "const") expression_unary). 286 | bool is_expression_unary(array_t&); 287 | bool is_unary_operator(name_t&); // helper 288 | // expression_postfix = expression_primary { ("[" expression "]") | ("." identifier) | ("(" [expression_list] ")") | "&" }. 289 | bool is_expression_postfix(array_t&); 290 | // expression_primary = number | "true" | "false" | string | identifier | "typename" | expression_template | ("(" expression ")"). 291 | bool is_expression_primary(array_t&); 292 | // expression_template = class_name [ "<" expression_list ">" ]. 293 | bool is_expression_template(); 294 | // expression_additive_list = expression_additive { "," expression_additive }. 295 | bool is_expression_additive_list(); 296 | // expression_list = expression { "," expression }. 297 | bool is_expression_list(array_t&); 298 | 299 | // boolean = "true" | "false". 300 | bool is_boolean(any_regular_t&); 301 | 302 | // helper functions 303 | bool is_relational_operator(name_t&); 304 | bool is_operator_shift(name_t&); 305 | 306 | // lexical tokens: 307 | 308 | bool is_identifier(name_t&); 309 | bool is_identifier(); 310 | void require_identifier(); 311 | bool is_identifier(any_regular_t&); 312 | void require_identifier(any_regular_t&); 313 | 314 | 315 | bool is_lead_comment(std::string&); 316 | bool is_trail_comment(std::string&); 317 | 318 | /* 319 | REVISIT (sparent) : We should provide a protected call to get the token stream and allow 320 | subclasses to access it directly - but for now we'll stick with the law of Demiter. 321 | */ 322 | 323 | protected: 324 | const stream_lex_token_t& get_token(); 325 | void putback(); 326 | 327 | bool is_token (name_t tokenName, any_regular_t& tokenValue); 328 | bool is_token (name_t tokenName); 329 | void require_token (name_t tokenName, any_regular_t& tokenValue); 330 | void require_token (name_t tokenName); 331 | bool is_keyword (name_t keywordName); 332 | void require_keyword (name_t keywordName); 333 | 334 | void throw_exception (const char* errorString); 335 | void throw_exception (const name_t& found, const name_t& expected); 336 | 337 | private: 338 | void set_keyword_extension_lookup(const keyword_extension_lookup_proc_t& proc); 339 | 340 | class implementation; 341 | implementation* object; 342 | }; 343 | 344 | /*************************************************************************************************/ 345 | 346 | } // namespace adobe 347 | 348 | /*************************************************************************************************/ 349 | 350 | #endif 351 | 352 | /*************************************************************************************************/ 353 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "exp_parser.hpp" 5 | 6 | namespace { 7 | 8 | std::string get_line(adobe::name_t n, std::streampos p) 9 | { 10 | std::string result; 11 | std::ifstream s(n.c_str()); 12 | p -= 1; // REVISIT (sparent) : This shouldn't be necessary! 13 | s.seekg(p); 14 | std::getline(s, result); 15 | #if 0 16 | std::getline(s, result); 17 | std::cout << result << std::endl; 18 | std::getline(s, result); 19 | std::cout << result << std::endl; 20 | #endif 21 | return result; 22 | } 23 | 24 | } // namespace 25 | 26 | int main (int argc, char * const argv[]) { 27 | const char* file((argc > 1) ? argv[1] : "/Users/sparent/Development/projects/eop_code/eop.hpp"); 28 | 29 | try { 30 | std::ifstream stream(file); 31 | 32 | eop::expression_parser parser(stream, 33 | adobe::line_position_t(adobe::name_t(file), 34 | adobe::line_position_t::getline_proc_t(new adobe::line_position_t::getline_proc_impl_t(&get_line)))); 35 | 36 | parser.parse(); 37 | std::cout << "Success!" << std::endl; 38 | 39 | } catch (const adobe::stream_error_t& error) { 40 | 41 | std::cerr << format_stream_error(error); 42 | 43 | } catch (const std::exception& error) { 44 | 45 | std::cerr << error.what(); 46 | } 47 | 48 | return 0; 49 | } 50 | --------------------------------------------------------------------------------