00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "string.h"
00032 #include "cr-parser.h"
00033 #include "cr-num.h"
00034 #include "cr-term.h"
00035 #include "cr-simple-sel.h"
00036 #include "cr-attr-sel.h"
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 typedef struct _CRParserError CRParserError;
00074
00075
00076
00077
00078
00079 struct _CRParserError {
00080 guchar *msg;
00081 enum CRStatus status;
00082 glong line;
00083 glong column;
00084 glong byte_num;
00085 };
00086
00087 enum CRParserState {
00088 READY_STATE = 0,
00089 TRY_PARSE_CHARSET_STATE,
00090 CHARSET_PARSED_STATE,
00091 TRY_PARSE_IMPORT_STATE,
00092 IMPORT_PARSED_STATE,
00093 TRY_PARSE_RULESET_STATE,
00094 RULESET_PARSED_STATE,
00095 TRY_PARSE_MEDIA_STATE,
00096 MEDIA_PARSED_STATE,
00097 TRY_PARSE_PAGE_STATE,
00098 PAGE_PARSED_STATE,
00099 TRY_PARSE_FONT_FACE_STATE,
00100 FONT_FACE_PARSED_STATE
00101 } ;
00102
00103
00104
00105
00106
00107 struct _CRParserPriv {
00108
00109
00110
00111 CRTknzr *tknzr;
00112
00113
00114
00115
00116
00117
00118 CRDocHandler *sac_handler;
00119
00120
00121
00122
00123
00124
00125
00126 GList *err_stack;
00127
00128 enum CRParserState state;
00129 gboolean resolve_import;
00130 gboolean is_case_sensitive;
00131 gboolean use_core_grammar;
00132 };
00133
00134 #define PRIVATE(obj) ((obj)->priv)
00135
00136 #define CHARS_TAB_SIZE 12
00137
00138
00139
00140
00141
00142 #define IS_NUM(a_char) (((a_char) >= '0' && (a_char) <= '9')?TRUE:FALSE)
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 #define CHECK_PARSING_STATUS(status, is_exception) \
00154 if ((status) != CR_OK) \
00155 { \
00156 if (is_exception == FALSE) \
00157 { \
00158 status = CR_PARSING_ERROR ; \
00159 } \
00160 goto error ; \
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 #define CHECK_PARSING_STATUS_ERR(a_this, a_status, a_is_exception,\
00176 a_err_msg, a_err_status) \
00177 if ((a_status) != CR_OK) \
00178 { \
00179 if (a_is_exception == FALSE) a_status = CR_PARSING_ERROR ; \
00180 cr_parser_push_error (a_this, a_err_msg, a_err_status) ; \
00181 goto error ; \
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 #define PEEK_NEXT_CHAR(a_this, a_to_char) \
00195 {\
00196 enum CRStatus status ; \
00197 status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, a_to_char) ; \
00198 CHECK_PARSING_STATUS (status, TRUE) \
00199 }
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 #define READ_NEXT_CHAR(a_this, a_to_char) \
00210 status = cr_tknzr_read_char (PRIVATE (a_this)->tknzr, a_to_char) ; \
00211 CHECK_PARSING_STATUS (status, TRUE)
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 #define RECORD_INITIAL_POS(a_this, a_pos) \
00224 status = cr_tknzr_get_cur_pos (PRIVATE \
00225 (a_this)->tknzr, a_pos) ; \
00226 g_return_val_if_fail (status == CR_OK, status)
00227
00228
00229
00230
00231
00232
00233
00234
00235 #define RECORD_CUR_BYTE_ADDR(a_this, a_addr) \
00236 status = cr_tknzr_get_cur_byte_addr \
00237 (PRIVATE (a_this)->tknzr, a_addr) ; \
00238 CHECK_PARSING_STATUS (status, TRUE)
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 #define PEEK_BYTE(a_parser, a_offset, a_byte_ptr) \
00252 status = cr_tknzr_peek_byte (PRIVATE (a_this)->tknzr, \
00253 a_offset, \
00254 a_byte_ptr) ; \
00255 CHECK_PARSING_STATUS (status, TRUE) ;
00256
00257 #define BYTE(a_parser, a_offset, a_eof) \
00258 cr_tknzr_peek_byte2 (PRIVATE (a_this)->tknzr, a_offset, a_eof)
00259
00260
00261
00262
00263
00264
00265
00266
00267 #define READ_NEXT_BYTE(a_this, a_byte_ptr) \
00268 status = cr_tknzr_read_byte (PRIVATE (a_this)->tknzr, a_byte_ptr) ; \
00269 CHECK_PARSING_STATUS (status, TRUE) ;
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 #define SKIP_BYTES(a_this, a_nb_bytes) \
00280 status = cr_tknzr_seek_index (PRIVATE (a_this)->tknzr, \
00281 CR_SEEK_CUR, a_nb_bytes) ; \
00282 CHECK_PARSING_STATUS (status, TRUE) ;
00283
00284
00285
00286
00287
00288
00289
00290
00291 #define SKIP_CHARS(a_parser, a_nb_chars) \
00292 { \
00293 glong nb_chars = a_nb_chars ; \
00294 status = cr_tknzr_consume_chars \
00295 (PRIVATE (a_parser)->tknzr,0, &nb_chars) ; \
00296 CHECK_PARSING_STATUS (status, TRUE) ; \
00297 }
00298
00299
00300
00301
00302
00303
00304
00305 #define ENSURE_PARSING_COND(condition) \
00306 if (! (condition)) {status = CR_PARSING_ERROR; goto error ;}
00307
00308 #define ENSURE_PARSING_COND_ERR(a_this, a_condition, \
00309 a_err_msg, a_err_status) \
00310 if (! (a_condition)) \
00311 { \
00312 status = CR_PARSING_ERROR; \
00313 cr_parser_push_error (a_this, a_err_msg, a_err_status) ; \
00314 goto error ; \
00315 }
00316
00317 #define GET_NEXT_TOKEN(a_this, a_token_ptr) \
00318 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, \
00319 a_token_ptr) ; \
00320 ENSURE_PARSING_COND (status == CR_OK) ;
00321
00322 #ifdef WITH_UNICODE_ESCAPE_AND_RANGE
00323 static enum CRStatus cr_parser_parse_unicode_escape (CRParser * a_this,
00324 guint32 * a_unicode);
00325 static enum CRStatus cr_parser_parse_escape (CRParser * a_this,
00326 guint32 * a_esc_code);
00327
00328 static enum CRStatus cr_parser_parse_unicode_range (CRParser * a_this,
00329 CRString ** a_inf,
00330 CRString ** a_sup);
00331 #endif
00332
00333 static enum CRStatus cr_parser_parse_stylesheet_core (CRParser * a_this);
00334
00335 static enum CRStatus cr_parser_parse_atrule_core (CRParser * a_this);
00336
00337 static enum CRStatus cr_parser_parse_ruleset_core (CRParser * a_this);
00338
00339 static enum CRStatus cr_parser_parse_selector_core (CRParser * a_this);
00340
00341 static enum CRStatus cr_parser_parse_declaration_core (CRParser * a_this);
00342
00343 static enum CRStatus cr_parser_parse_any_core (CRParser * a_this);
00344
00345 static enum CRStatus cr_parser_parse_block_core (CRParser * a_this);
00346
00347 static enum CRStatus cr_parser_parse_value_core (CRParser * a_this);
00348
00349 static enum CRStatus cr_parser_parse_string (CRParser * a_this,
00350 CRString ** a_str);
00351
00352 static enum CRStatus cr_parser_parse_ident (CRParser * a_this,
00353 CRString ** a_str);
00354
00355 static enum CRStatus cr_parser_parse_uri (CRParser * a_this,
00356 CRString ** a_str);
00357
00358 static enum CRStatus cr_parser_parse_function (CRParser * a_this,
00359 CRString ** a_func_name,
00360 CRTerm ** a_expr);
00361 static enum CRStatus cr_parser_parse_property (CRParser * a_this,
00362 CRString ** a_property);
00363
00364 static enum CRStatus cr_parser_parse_attribute_selector (CRParser * a_this,
00365 CRAttrSel ** a_sel);
00366
00367 static enum CRStatus cr_parser_parse_simple_selector (CRParser * a_this,
00368 CRSimpleSel ** a_sel);
00369
00370 static enum CRStatus cr_parser_parse_simple_sels (CRParser * a_this,
00371 CRSimpleSel ** a_sel);
00372
00373 static CRParserError *cr_parser_error_new (const guchar * a_msg,
00374 enum CRStatus);
00375
00376 static void cr_parser_error_set_msg (CRParserError * a_this,
00377 const guchar * a_msg);
00378
00379 static void cr_parser_error_dump (CRParserError * a_this);
00380
00381 static void cr_parser_error_set_status (CRParserError * a_this,
00382 enum CRStatus a_status);
00383
00384 static void cr_parser_error_set_pos (CRParserError * a_this,
00385 glong a_line,
00386 glong a_column, glong a_byte_num);
00387 static void
00388 cr_parser_error_destroy (CRParserError * a_this);
00389
00390 static enum CRStatus cr_parser_push_error (CRParser * a_this,
00391 const guchar * a_msg,
00392 enum CRStatus a_status);
00393
00394 static enum CRStatus cr_parser_dump_err_stack (CRParser * a_this,
00395 gboolean a_clear_errs);
00396 static enum CRStatus
00397 cr_parser_clear_errors (CRParser * a_this);
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 static CRParserError *
00410 cr_parser_error_new (const guchar * a_msg, enum CRStatus a_status)
00411 {
00412 CRParserError *result = NULL;
00413
00414 result = g_try_malloc (sizeof (CRParserError));
00415
00416 if (result == NULL) {
00417 cr_utils_trace_info ("Out of memory");
00418 return NULL;
00419 }
00420
00421 memset (result, 0, sizeof (CRParserError));
00422
00423 cr_parser_error_set_msg (result, a_msg);
00424 cr_parser_error_set_status (result, a_status);
00425
00426 return result;
00427 }
00428
00429
00430
00431
00432
00433
00434 static void
00435 cr_parser_error_set_msg (CRParserError * a_this, const guchar * a_msg)
00436 {
00437 g_return_if_fail (a_this);
00438
00439 if (a_this->msg) {
00440 g_free (a_this->msg);
00441 }
00442
00443 a_this->msg = g_strdup (a_msg);
00444 }
00445
00446
00447
00448
00449
00450
00451
00452 static void
00453 cr_parser_error_set_status (CRParserError * a_this, enum CRStatus a_status)
00454 {
00455 g_return_if_fail (a_this);
00456
00457 a_this->status = a_status;
00458 }
00459
00460
00461
00462
00463
00464
00465
00466
00467 static void
00468 cr_parser_error_set_pos (CRParserError * a_this,
00469 glong a_line, glong a_column, glong a_byte_num)
00470 {
00471 g_return_if_fail (a_this);
00472
00473 a_this->line = a_line;
00474 a_this->column = a_column;
00475 a_this->byte_num = a_byte_num;
00476 }
00477
00478 static void
00479 cr_parser_error_dump (CRParserError * a_this)
00480 {
00481 g_return_if_fail (a_this);
00482
00483 g_printerr ("parsing error: %ld:%ld:", a_this->line, a_this->column);
00484
00485 g_printerr ("%s\n", a_this->msg);
00486 }
00487
00488
00489
00490
00491
00492 static void
00493 cr_parser_error_destroy (CRParserError * a_this)
00494 {
00495 g_return_if_fail (a_this);
00496
00497 if (a_this->msg) {
00498 g_free (a_this->msg);
00499 a_this->msg = NULL;
00500 }
00501
00502 g_free (a_this);
00503 }
00504
00505
00506
00507
00508
00509
00510
00511
00512 static enum CRStatus
00513 cr_parser_push_error (CRParser * a_this,
00514 const guchar * a_msg, enum CRStatus a_status)
00515 {
00516 enum CRStatus status = CR_OK;
00517
00518 CRParserError *error = NULL;
00519 CRInputPos pos;
00520
00521 g_return_val_if_fail (a_this && PRIVATE (a_this)
00522 && a_msg, CR_BAD_PARAM_ERROR);
00523
00524 error = cr_parser_error_new (a_msg, a_status);
00525
00526 g_return_val_if_fail (error, CR_ERROR);
00527
00528 RECORD_INITIAL_POS (a_this, &pos);
00529
00530 cr_parser_error_set_pos
00531 (error, pos.line, pos.col, pos.next_byte_index - 1);
00532
00533 PRIVATE (a_this)->err_stack =
00534 g_list_prepend (PRIVATE (a_this)->err_stack, error);
00535
00536 if (PRIVATE (a_this)->err_stack == NULL)
00537 goto error;
00538
00539 return CR_OK;
00540
00541 error:
00542
00543 if (error) {
00544 cr_parser_error_destroy (error);
00545 error = NULL;
00546 }
00547
00548 return status;
00549 }
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 static enum CRStatus
00560 cr_parser_dump_err_stack (CRParser * a_this, gboolean a_clear_errs)
00561 {
00562 GList *cur = NULL;
00563
00564 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
00565
00566 if (PRIVATE (a_this)->err_stack == NULL)
00567 return CR_OK;
00568
00569 for (cur = PRIVATE (a_this)->err_stack; cur; cur = cur->next) {
00570 cr_parser_error_dump ((CRParserError *) cur->data);
00571 }
00572
00573 if (a_clear_errs == TRUE) {
00574 cr_parser_clear_errors (a_this);
00575 }
00576
00577 return CR_OK;
00578 }
00579
00580
00581
00582
00583
00584
00585 static enum CRStatus
00586 cr_parser_clear_errors (CRParser * a_this)
00587 {
00588 GList *cur = NULL;
00589
00590 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
00591
00592 for (cur = PRIVATE (a_this)->err_stack; cur; cur = cur->next) {
00593 if (cur->data) {
00594 cr_parser_error_destroy ((CRParserError *)
00595 cur->data);
00596 }
00597 }
00598
00599 if (PRIVATE (a_this)->err_stack) {
00600 g_list_free (PRIVATE (a_this)->err_stack);
00601 PRIVATE (a_this)->err_stack = NULL;
00602 }
00603
00604 return CR_OK;
00605 }
00606
00607
00608
00609
00610
00611
00612
00613
00614 enum CRStatus
00615 cr_parser_try_to_skip_spaces_and_comments (CRParser * a_this)
00616 {
00617 enum CRStatus status = CR_ERROR;
00618 CRToken *token = NULL;
00619
00620 g_return_val_if_fail (a_this && PRIVATE (a_this)
00621 && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
00622 do {
00623 if (token) {
00624 cr_token_destroy (token);
00625 token = NULL;
00626 }
00627
00628 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
00629 &token);
00630 if (status != CR_OK)
00631 goto error;
00632 }
00633 while ((token != NULL)
00634 && (token->type == COMMENT_TK || token->type == S_TK));
00635
00636 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
00637
00638 return status;
00639
00640 error:
00641
00642 if (token) {
00643 cr_token_destroy (token);
00644 token = NULL;
00645 }
00646
00647 return status;
00648 }
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670 static enum CRStatus
00671 cr_parser_parse_stylesheet_core (CRParser * a_this)
00672 {
00673 CRToken *token = NULL;
00674 CRInputPos init_pos;
00675 enum CRStatus status = CR_ERROR;
00676
00677 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
00678
00679 RECORD_INITIAL_POS (a_this, &init_pos);
00680
00681 continue_parsing:
00682
00683 if (token) {
00684 cr_token_destroy (token);
00685 token = NULL;
00686 }
00687
00688 cr_parser_try_to_skip_spaces_and_comments (a_this);
00689 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
00690 if (status == CR_END_OF_INPUT_ERROR) {
00691 status = CR_OK;
00692 goto done;
00693 } else if (status != CR_OK) {
00694 goto error;
00695 }
00696
00697 switch (token->type) {
00698
00699 case CDO_TK:
00700 case CDC_TK:
00701 goto continue_parsing;
00702 break;
00703 default:
00704 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
00705 token);
00706 CHECK_PARSING_STATUS (status, TRUE);
00707 token = NULL;
00708 status = cr_parser_parse_statement_core (a_this);
00709 cr_parser_clear_errors (a_this);
00710 if (status == CR_OK) {
00711 goto continue_parsing;
00712 } else if (status == CR_END_OF_INPUT_ERROR) {
00713 goto done;
00714 } else {
00715 goto error;
00716 }
00717 }
00718
00719 done:
00720 if (token) {
00721 cr_token_destroy (token);
00722 token = NULL;
00723 }
00724
00725 cr_parser_clear_errors (a_this);
00726 return CR_OK;
00727
00728 error:
00729 cr_parser_push_error
00730 (a_this, "could not recognize next production", CR_ERROR);
00731
00732 cr_parser_dump_err_stack (a_this, TRUE);
00733
00734 if (token) {
00735 cr_token_destroy (token);
00736 token = NULL;
00737 }
00738
00739 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
00740
00741 return status;
00742 }
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752 static enum CRStatus
00753 cr_parser_parse_atrule_core (CRParser * a_this)
00754 {
00755 CRToken *token = NULL;
00756 CRInputPos init_pos;
00757 enum CRStatus status = CR_ERROR;
00758
00759 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
00760
00761 RECORD_INITIAL_POS (a_this, &init_pos);
00762
00763 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
00764 &token);
00765 ENSURE_PARSING_COND (status == CR_OK
00766 && token
00767 &&
00768 (token->type == ATKEYWORD_TK
00769 || token->type == IMPORT_SYM_TK
00770 || token->type == PAGE_SYM_TK
00771 || token->type == MEDIA_SYM_TK
00772 || token->type == FONT_FACE_SYM_TK
00773 || token->type == CHARSET_SYM_TK));
00774
00775 cr_token_destroy (token);
00776 token = NULL;
00777
00778 cr_parser_try_to_skip_spaces_and_comments (a_this);
00779
00780 do {
00781 status = cr_parser_parse_any_core (a_this);
00782 } while (status == CR_OK);
00783
00784 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
00785 &token);
00786 ENSURE_PARSING_COND (status == CR_OK && token);
00787
00788 if (token->type == CBO_TK) {
00789 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
00790 token);
00791 token = NULL;
00792 status = cr_parser_parse_block_core (a_this);
00793 CHECK_PARSING_STATUS (status,
00794 FALSE);
00795 goto done;
00796 } else if (token->type == SEMICOLON_TK) {
00797 goto done;
00798 } else {
00799 status = CR_PARSING_ERROR ;
00800 goto error;
00801 }
00802
00803 done:
00804 if (token) {
00805 cr_token_destroy (token);
00806 token = NULL;
00807 }
00808 return CR_OK;
00809
00810 error:
00811 if (token) {
00812 cr_token_destroy (token);
00813 token = NULL;
00814 }
00815 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr,
00816 &init_pos);
00817 return status;
00818 }
00819
00820
00821
00822
00823
00824
00825
00826
00827 static enum CRStatus
00828 cr_parser_parse_ruleset_core (CRParser * a_this)
00829 {
00830 CRToken *token = NULL;
00831 CRInputPos init_pos;
00832 enum CRStatus status = CR_ERROR;
00833
00834 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
00835 RECORD_INITIAL_POS (a_this, &init_pos);
00836
00837 status = cr_parser_parse_selector_core (a_this);
00838
00839 ENSURE_PARSING_COND (status == CR_OK
00840 || status == CR_PARSING_ERROR
00841 || status == CR_END_OF_INPUT_ERROR);
00842
00843 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
00844 ENSURE_PARSING_COND (status == CR_OK && token
00845 && token->type == CBO_TK);
00846 cr_token_destroy (token);
00847 token = NULL;
00848
00849 cr_parser_try_to_skip_spaces_and_comments (a_this);
00850 status = cr_parser_parse_declaration_core (a_this);
00851
00852 parse_declaration_list:
00853 if (token) {
00854 cr_token_destroy (token);
00855 token = NULL;
00856 }
00857
00858 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
00859 ENSURE_PARSING_COND (status == CR_OK && token);
00860 if (token->type == CBC_TK) {
00861 goto done;
00862 }
00863
00864 ENSURE_PARSING_COND (status == CR_OK
00865 && token && token->type == SEMICOLON_TK);
00866
00867 cr_token_destroy (token);
00868 token = NULL;
00869 cr_parser_try_to_skip_spaces_and_comments (a_this);
00870 status = cr_parser_parse_declaration_core (a_this);
00871 cr_parser_clear_errors (a_this);
00872 ENSURE_PARSING_COND (status == CR_OK || status == CR_PARSING_ERROR);
00873 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
00874 ENSURE_PARSING_COND (status == CR_OK && token);
00875 if (token->type == CBC_TK) {
00876 cr_token_destroy (token);
00877 token = NULL;
00878 cr_parser_try_to_skip_spaces_and_comments (a_this);
00879 goto done;
00880 } else {
00881 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
00882 token);
00883 token = NULL;
00884 goto parse_declaration_list;
00885 }
00886
00887 done:
00888 if (token) {
00889 cr_token_destroy (token);
00890 token = NULL;
00891 }
00892
00893 if (status == CR_OK) {
00894 return CR_OK;
00895 }
00896
00897 error:
00898 if (token) {
00899 cr_token_destroy (token);
00900 token = NULL;
00901 }
00902
00903 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
00904
00905 return status;
00906 }
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916 static enum CRStatus
00917 cr_parser_parse_selector_core (CRParser * a_this)
00918 {
00919 CRToken *token = NULL;
00920 CRInputPos init_pos;
00921 enum CRStatus status = CR_ERROR;
00922
00923 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
00924
00925 RECORD_INITIAL_POS (a_this, &init_pos);
00926
00927 status = cr_parser_parse_any_core (a_this);
00928 CHECK_PARSING_STATUS (status, FALSE);
00929
00930 do {
00931 status = cr_parser_parse_any_core (a_this);
00932
00933 } while (status == CR_OK);
00934
00935 return CR_OK;
00936
00937 error:
00938 if (token) {
00939 cr_token_destroy (token);
00940 token = NULL;
00941 }
00942
00943 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
00944
00945 return status;
00946 }
00947
00948
00949
00950
00951
00952
00953
00954
00955 static enum CRStatus
00956 cr_parser_parse_block_core (CRParser * a_this)
00957 {
00958 CRToken *token = NULL;
00959 CRInputPos init_pos;
00960 enum CRStatus status = CR_ERROR;
00961
00962 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
00963
00964 RECORD_INITIAL_POS (a_this, &init_pos);
00965
00966 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
00967 ENSURE_PARSING_COND (status == CR_OK && token
00968 && token->type == CBO_TK);
00969
00970 parse_block_content:
00971
00972 if (token) {
00973 cr_token_destroy (token);
00974 token = NULL;
00975 }
00976
00977 cr_parser_try_to_skip_spaces_and_comments (a_this);
00978
00979 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
00980 ENSURE_PARSING_COND (status == CR_OK && token);
00981
00982 if (token->type == CBC_TK) {
00983 cr_parser_try_to_skip_spaces_and_comments (a_this);
00984 goto done;
00985 } else if (token->type == SEMICOLON_TK) {
00986 goto parse_block_content;
00987 } else if (token->type == ATKEYWORD_TK) {
00988 cr_parser_try_to_skip_spaces_and_comments (a_this);
00989 goto parse_block_content;
00990 } else if (token->type == CBO_TK) {
00991 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
00992 token = NULL;
00993 status = cr_parser_parse_block_core (a_this);
00994 CHECK_PARSING_STATUS (status, FALSE);
00995 goto parse_block_content;
00996 } else {
00997 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
00998 token = NULL;
00999 status = cr_parser_parse_any_core (a_this);
01000 CHECK_PARSING_STATUS (status, FALSE);
01001 goto parse_block_content;
01002 }
01003
01004 done:
01005 if (token) {
01006 cr_token_destroy (token);
01007 token = NULL;
01008 }
01009
01010 if (status == CR_OK)
01011 return CR_OK;
01012
01013 error:
01014 if (token) {
01015 cr_token_destroy (token);
01016 token = NULL;
01017 }
01018
01019 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01020
01021 return status;
01022 }
01023
01024 static enum CRStatus
01025 cr_parser_parse_declaration_core (CRParser * a_this)
01026 {
01027 CRToken *token = NULL;
01028 CRInputPos init_pos;
01029 enum CRStatus status = CR_ERROR;
01030 CRString *prop = NULL;
01031
01032 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
01033
01034 RECORD_INITIAL_POS (a_this, &init_pos);
01035
01036 status = cr_parser_parse_property (a_this, &prop);
01037 CHECK_PARSING_STATUS (status, FALSE);
01038 cr_parser_clear_errors (a_this);
01039 ENSURE_PARSING_COND (status == CR_OK && prop);
01040 cr_string_destroy (prop);
01041 prop = NULL;
01042
01043 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01044 ENSURE_PARSING_COND (status == CR_OK
01045 && token
01046 && token->type == DELIM_TK
01047 && token->u.unichar == ':');
01048 cr_token_destroy (token);
01049 token = NULL;
01050 cr_parser_try_to_skip_spaces_and_comments (a_this);
01051 status = cr_parser_parse_value_core (a_this);
01052 CHECK_PARSING_STATUS (status, FALSE);
01053
01054 return CR_OK;
01055
01056 error:
01057
01058 if (prop) {
01059 cr_string_destroy (prop);
01060 prop = NULL;
01061 }
01062
01063 if (token) {
01064 cr_token_destroy (token);
01065 token = NULL;
01066 }
01067
01068 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01069
01070 return status;
01071 }
01072
01073
01074
01075
01076
01077
01078
01079
01080 static enum CRStatus
01081 cr_parser_parse_value_core (CRParser * a_this)
01082 {
01083 CRToken *token = NULL;
01084 CRInputPos init_pos;
01085 enum CRStatus status = CR_ERROR;
01086 glong ref = 0;
01087
01088 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
01089 RECORD_INITIAL_POS (a_this, &init_pos);
01090
01091 continue_parsing:
01092
01093 if (token) {
01094 cr_token_destroy (token);
01095 token = NULL;
01096 }
01097
01098 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01099 ENSURE_PARSING_COND (status == CR_OK && token);
01100
01101 switch (token->type) {
01102 case CBO_TK:
01103 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
01104 token);
01105 token = NULL;
01106 status = cr_parser_parse_block_core (a_this);
01107 CHECK_PARSING_STATUS (status, FALSE);
01108 ref++;
01109 goto continue_parsing;
01110
01111 case ATKEYWORD_TK:
01112 cr_parser_try_to_skip_spaces_and_comments (a_this);
01113 ref++;
01114 goto continue_parsing;
01115
01116 default:
01117 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
01118 token);
01119 token = NULL;
01120 status = cr_parser_parse_any_core (a_this);
01121 if (status == CR_OK) {
01122 ref++;
01123 goto continue_parsing;
01124 } else if (status == CR_PARSING_ERROR) {
01125 status = CR_OK;
01126 goto done;
01127 } else {
01128 goto error;
01129 }
01130 }
01131
01132 done:
01133 if (token) {
01134 cr_token_destroy (token);
01135 token = NULL;
01136 }
01137
01138 if (status == CR_OK && ref)
01139 return CR_OK;
01140 error:
01141 if (token) {
01142 cr_token_destroy (token);
01143 token = NULL;
01144 }
01145
01146 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01147
01148 return status;
01149 }
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161 static enum CRStatus
01162 cr_parser_parse_any_core (CRParser * a_this)
01163 {
01164 CRToken *token1 = NULL,
01165 *token2 = NULL;
01166 CRInputPos init_pos;
01167 enum CRStatus status = CR_ERROR;
01168
01169 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
01170
01171 RECORD_INITIAL_POS (a_this, &init_pos);
01172
01173 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token1);
01174
01175 ENSURE_PARSING_COND (status == CR_OK && token1);
01176
01177 switch (token1->type) {
01178 case IDENT_TK:
01179 case NUMBER_TK:
01180 case RGB_TK:
01181 case PERCENTAGE_TK:
01182 case DIMEN_TK:
01183 case EMS_TK:
01184 case EXS_TK:
01185 case LENGTH_TK:
01186 case ANGLE_TK:
01187 case FREQ_TK:
01188 case TIME_TK:
01189 case STRING_TK:
01190 case DELIM_TK:
01191 case URI_TK:
01192 case HASH_TK:
01193 case UNICODERANGE_TK:
01194 case INCLUDES_TK:
01195 case DASHMATCH_TK:
01196 case S_TK:
01197 case COMMENT_TK:
01198 case IMPORTANT_SYM_TK:
01199 status = CR_OK;
01200 break;
01201 case FUNCTION_TK:
01202
01203
01204
01205
01206
01207
01208 do {
01209 status = cr_parser_parse_any_core (a_this);
01210 } while (status == CR_OK);
01211
01212 ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
01213 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
01214 &token2);
01215 ENSURE_PARSING_COND (status == CR_OK
01216 && token2 && token2->type == PC_TK);
01217 break;
01218 case PO_TK:
01219 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
01220 &token2);
01221 ENSURE_PARSING_COND (status == CR_OK && token2);
01222
01223 if (token2->type == PC_TK) {
01224 cr_token_destroy (token2);
01225 token2 = NULL;
01226 goto done;
01227 } else {
01228 status = cr_tknzr_unget_token
01229 (PRIVATE (a_this)->tknzr, token2);
01230 token2 = NULL;
01231 }
01232
01233 do {
01234 status = cr_parser_parse_any_core (a_this);
01235 } while (status == CR_OK);
01236
01237 ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
01238
01239 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
01240 &token2);
01241 ENSURE_PARSING_COND (status == CR_OK
01242 && token2 && token2->type == PC_TK);
01243 status = CR_OK;
01244 break;
01245
01246 case BO_TK:
01247 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
01248 &token2);
01249 ENSURE_PARSING_COND (status == CR_OK && token2);
01250
01251 if (token2->type == BC_TK) {
01252 cr_token_destroy (token2);
01253 token2 = NULL;
01254 goto done;
01255 } else {
01256 status = cr_tknzr_unget_token
01257 (PRIVATE (a_this)->tknzr, token2);
01258 token2 = NULL;
01259 }
01260
01261 do {
01262 status = cr_parser_parse_any_core (a_this);
01263 } while (status == CR_OK);
01264
01265 ENSURE_PARSING_COND (status == CR_PARSING_ERROR);
01266
01267 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
01268 &token2);
01269 ENSURE_PARSING_COND (status == CR_OK
01270 && token2 && token2->type == BC_TK);
01271 status = CR_OK;
01272 break;
01273 default:
01274 status = CR_PARSING_ERROR;
01275 goto error;
01276 }
01277
01278 done:
01279 if (token1) {
01280 cr_token_destroy (token1);
01281 token1 = NULL;
01282 }
01283
01284 if (token2) {
01285 cr_token_destroy (token2);
01286 token2 = NULL;
01287 }
01288
01289 return CR_OK;
01290
01291 error:
01292
01293 if (token1) {
01294 cr_token_destroy (token1);
01295 token1 = NULL;
01296 }
01297
01298 if (token2) {
01299 cr_token_destroy (token2);
01300 token2 = NULL;
01301 }
01302
01303 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01304 return status;
01305 }
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318 static enum CRStatus
01319 cr_parser_parse_attribute_selector (CRParser * a_this,
01320 CRAttrSel ** a_sel)
01321 {
01322 enum CRStatus status = CR_OK;
01323 CRInputPos init_pos;
01324 CRToken *token = NULL;
01325 CRAttrSel *result = NULL;
01326 CRParsingLocation location = {0} ;
01327
01328 g_return_val_if_fail (a_this && a_sel, CR_BAD_PARAM_ERROR);
01329
01330 RECORD_INITIAL_POS (a_this, &init_pos);
01331
01332 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01333 ENSURE_PARSING_COND (status == CR_OK && token
01334 && token->type == BO_TK);
01335 cr_parsing_location_copy
01336 (&location, &token->location) ;
01337 cr_token_destroy (token);
01338 token = NULL;
01339
01340 cr_parser_try_to_skip_spaces_and_comments (a_this);
01341
01342 result = cr_attr_sel_new ();
01343 if (!result) {
01344 cr_utils_trace_info ("result failed") ;
01345 status = CR_OUT_OF_MEMORY_ERROR ;
01346 goto error ;
01347 }
01348 cr_parsing_location_copy (&result->location,
01349 &location) ;
01350 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01351 ENSURE_PARSING_COND (status == CR_OK
01352 && token && token->type == IDENT_TK);
01353
01354 result->name = token->u.str;
01355 token->u.str = NULL;
01356 cr_token_destroy (token);
01357 token = NULL;
01358
01359 cr_parser_try_to_skip_spaces_and_comments (a_this);
01360
01361 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01362 ENSURE_PARSING_COND (status == CR_OK && token);
01363
01364 if (token->type == INCLUDES_TK) {
01365 result->match_way = INCLUDES;
01366 goto parse_right_part;
01367 } else if (token->type == DASHMATCH_TK) {
01368 result->match_way = DASHMATCH;
01369 goto parse_right_part;
01370 } else if (token->type == DELIM_TK && token->u.unichar == '=') {
01371 result->match_way = EQUALS;
01372 goto parse_right_part;
01373 } else if (token->type == BC_TK) {
01374 result->match_way = SET;
01375 goto done;
01376 }
01377
01378 parse_right_part:
01379
01380 if (token) {
01381 cr_token_destroy (token);
01382 token = NULL;
01383 }
01384
01385 cr_parser_try_to_skip_spaces_and_comments (a_this);
01386
01387 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01388 ENSURE_PARSING_COND (status == CR_OK && token);
01389
01390 if (token->type == IDENT_TK) {
01391 result->value = token->u.str;
01392 token->u.str = NULL;
01393 } else if (token->type == STRING_TK) {
01394 result->value = token->u.str;
01395 token->u.str = NULL;
01396 } else {
01397 status = CR_PARSING_ERROR;
01398 goto error;
01399 }
01400
01401 if (token) {
01402 cr_token_destroy (token);
01403 token = NULL;
01404 }
01405
01406 cr_parser_try_to_skip_spaces_and_comments (a_this);
01407
01408 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01409
01410 ENSURE_PARSING_COND (status == CR_OK && token
01411 && token->type == BC_TK);
01412 done:
01413 if (token) {
01414 cr_token_destroy (token);
01415 token = NULL;
01416 }
01417
01418 if (*a_sel) {
01419 status = cr_attr_sel_append_attr_sel (*a_sel, result);
01420 CHECK_PARSING_STATUS (status, FALSE);
01421 } else {
01422 *a_sel = result;
01423 }
01424
01425 cr_parser_clear_errors (a_this);
01426 return CR_OK;
01427
01428 error:
01429
01430 if (result) {
01431 cr_attr_sel_destroy (result);
01432 result = NULL;
01433 }
01434
01435 if (token) {
01436 cr_token_destroy (token);
01437 token = NULL;
01438 }
01439
01440 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01441
01442 return status;
01443 }
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458 static enum CRStatus
01459 cr_parser_parse_property (CRParser * a_this,
01460 CRString ** a_property)
01461 {
01462 enum CRStatus status = CR_OK;
01463 CRInputPos init_pos;
01464
01465 g_return_val_if_fail (a_this && PRIVATE (a_this)
01466 && PRIVATE (a_this)->tknzr
01467 && a_property,
01468 CR_BAD_PARAM_ERROR);
01469
01470 RECORD_INITIAL_POS (a_this, &init_pos);
01471
01472 status = cr_parser_parse_ident (a_this, a_property);
01473 CHECK_PARSING_STATUS (status, TRUE);
01474
01475 cr_parser_try_to_skip_spaces_and_comments (a_this);
01476
01477 cr_parser_clear_errors (a_this);
01478 return CR_OK;
01479
01480 error:
01481
01482 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01483
01484 return status;
01485 }
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498 enum CRStatus
01499 cr_parser_parse_term (CRParser * a_this, CRTerm ** a_term)
01500 {
01501 enum CRStatus status = CR_PARSING_ERROR;
01502 CRInputPos init_pos;
01503 CRTerm *result = NULL;
01504 CRTerm *param = NULL;
01505 CRToken *token = NULL;
01506 CRString *func_name = NULL;
01507 CRParsingLocation location = {0} ;
01508
01509 g_return_val_if_fail (a_this && a_term, CR_BAD_PARAM_ERROR);
01510
01511 RECORD_INITIAL_POS (a_this, &init_pos);
01512
01513 result = cr_term_new ();
01514
01515 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
01516 &token);
01517 if (status != CR_OK || !token)
01518 goto error;
01519
01520 cr_parsing_location_copy (&location, &token->location) ;
01521 if (token->type == DELIM_TK && token->u.unichar == '+') {
01522 result->unary_op = PLUS_UOP;
01523 cr_token_destroy (token) ;
01524 token = NULL ;
01525 cr_parser_try_to_skip_spaces_and_comments (a_this);
01526 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
01527 &token);
01528 if (status != CR_OK || !token)
01529 goto error;
01530 } else if (token->type == DELIM_TK && token->u.unichar == '-') {
01531 result->unary_op = MINUS_UOP;
01532 cr_token_destroy (token) ;
01533 token = NULL ;
01534 cr_parser_try_to_skip_spaces_and_comments (a_this);
01535 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
01536 &token);
01537 if (status != CR_OK || !token)
01538 goto error;
01539 }
01540
01541 if (token->type == EMS_TK
01542 || token->type == EXS_TK
01543 || token->type == LENGTH_TK
01544 || token->type == ANGLE_TK
01545 || token->type == TIME_TK
01546 || token->type == FREQ_TK
01547 || token->type == PERCENTAGE_TK
01548 || token->type == NUMBER_TK) {
01549 status = cr_term_set_number (result, token->u.num);
01550 CHECK_PARSING_STATUS (status, TRUE);
01551 token->u.num = NULL;
01552 status = CR_OK;
01553 } else if (token && token->type == FUNCTION_TK) {
01554 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
01555 token);
01556 token = NULL;
01557 status = cr_parser_parse_function (a_this, &func_name,
01558 ¶m);
01559
01560 if (status == CR_OK) {
01561 status = cr_term_set_function (result,
01562 func_name,
01563 param);
01564 CHECK_PARSING_STATUS (status, TRUE);
01565 }
01566 } else if (token && token->type == STRING_TK) {
01567 status = cr_term_set_string (result,
01568 token->u.str);
01569 CHECK_PARSING_STATUS (status, TRUE);
01570 token->u.str = NULL;
01571 } else if (token && token->type == IDENT_TK) {
01572 status = cr_term_set_ident (result, token->u.str);
01573 CHECK_PARSING_STATUS (status, TRUE);
01574 token->u.str = NULL;
01575 } else if (token && token->type == URI_TK) {
01576 status = cr_term_set_uri (result, token->u.str);
01577 CHECK_PARSING_STATUS (status, TRUE);
01578 token->u.str = NULL;
01579 } else if (token && token->type == RGB_TK) {
01580 status = cr_term_set_rgb (result, token->u.rgb);
01581 CHECK_PARSING_STATUS (status, TRUE);
01582 token->u.rgb = NULL;
01583 } else if (token && token->type == UNICODERANGE_TK) {
01584 result->type = TERM_UNICODERANGE;
01585 status = CR_PARSING_ERROR;
01586 } else if (token && token->type == HASH_TK) {
01587 status = cr_term_set_hash (result, token->u.str);
01588 CHECK_PARSING_STATUS (status, TRUE);
01589 token->u.str = NULL;
01590 } else {
01591 status = CR_PARSING_ERROR;
01592 }
01593
01594 if (status != CR_OK) {
01595 goto error;
01596 }
01597 cr_parsing_location_copy (&result->location,
01598 &location) ;
01599 *a_term = cr_term_append_term (*a_term, result);
01600
01601 result = NULL;
01602
01603 cr_parser_try_to_skip_spaces_and_comments (a_this);
01604
01605 if (token) {
01606 cr_token_destroy (token);
01607 token = NULL;
01608 }
01609
01610 cr_parser_clear_errors (a_this);
01611 return CR_OK;
01612
01613 error:
01614
01615 if (result) {
01616 cr_term_destroy (result);
01617 result = NULL;
01618 }
01619
01620 if (token) {
01621 cr_token_destroy (token);
01622 token = NULL;
01623 }
01624
01625 if (param) {
01626 cr_term_destroy (param);
01627 param = NULL;
01628 }
01629
01630 if (func_name) {
01631 cr_string_destroy (func_name);
01632 func_name = NULL;
01633 }
01634
01635 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01636
01637 return status;
01638 }
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651 static enum CRStatus
01652 cr_parser_parse_simple_selector (CRParser * a_this, CRSimpleSel ** a_sel)
01653 {
01654 enum CRStatus status = CR_ERROR;
01655 CRInputPos init_pos;
01656 CRToken *token = NULL;
01657 CRSimpleSel *sel = NULL;
01658 CRAdditionalSel *add_sel_list = NULL;
01659 gboolean found_sel = FALSE;
01660 guint32 cur_char = 0;
01661
01662 g_return_val_if_fail (a_this && a_sel, CR_BAD_PARAM_ERROR);
01663
01664 RECORD_INITIAL_POS (a_this, &init_pos);
01665
01666 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
01667 if (status != CR_OK)
01668 goto error;
01669
01670 sel = cr_simple_sel_new ();
01671 ENSURE_PARSING_COND (sel);
01672
01673 cr_parsing_location_copy
01674 (&sel->location,
01675 &token->location) ;
01676
01677 if (token && token->type == DELIM_TK
01678 && token->u.unichar == '*') {
01679 sel->type_mask |= UNIVERSAL_SELECTOR;
01680 sel->name = cr_string_new_from_string ("*");
01681 found_sel = TRUE;
01682 } else if (token && token->type == IDENT_TK) {
01683 sel->name = token->u.str;
01684 sel->type_mask |= TYPE_SELECTOR;
01685 token->u.str = NULL;
01686 found_sel = TRUE;
01687 } else {
01688 status = cr_tknzr_unget_token
01689 (PRIVATE (a_this)->tknzr,
01690 token);
01691 token = NULL;
01692 }
01693
01694 if (token) {
01695 cr_token_destroy (token);
01696 token = NULL;
01697 }
01698
01699 cr_parser_try_to_skip_spaces_and_comments (a_this);
01700
01701 for (;;) {
01702 if (token) {
01703 cr_token_destroy (token);
01704 token = NULL;
01705 }
01706
01707 status = cr_tknzr_get_next_token
01708 (PRIVATE (a_this)->tknzr,
01709 &token);
01710 if (status != CR_OK)
01711 goto error;
01712
01713 if (token && token->type == HASH_TK) {
01714
01715 CRAdditionalSel *add_sel = NULL;
01716
01717 add_sel = cr_additional_sel_new_with_type
01718 (ID_ADD_SELECTOR);
01719
01720 add_sel->content.id_name = token->u.str;
01721 token->u.str = NULL;
01722
01723 cr_parsing_location_copy
01724 (&add_sel->location,
01725 &token->location) ;
01726 add_sel_list =
01727 cr_additional_sel_append
01728 (add_sel_list, add_sel);
01729 found_sel = TRUE;
01730 } else if (token && (token->type == DELIM_TK)
01731 && (token->u.unichar == '.')) {
01732 cr_token_destroy (token);
01733 token = NULL;
01734
01735 status = cr_tknzr_get_next_token
01736 (PRIVATE (a_this)->tknzr, &token);
01737 if (status != CR_OK)
01738 goto error;
01739
01740 if (token && token->type == IDENT_TK) {
01741 CRAdditionalSel *add_sel = NULL;
01742
01743 add_sel = cr_additional_sel_new_with_type
01744 (CLASS_ADD_SELECTOR);
01745
01746 add_sel->content.class_name = token->u.str;
01747 token->u.str = NULL;
01748
01749 add_sel_list =
01750 cr_additional_sel_append
01751 (add_sel_list, add_sel);
01752 found_sel = TRUE;
01753
01754 cr_parsing_location_copy
01755 (&add_sel->location,
01756 & token->location) ;
01757 } else {
01758 status = CR_PARSING_ERROR;
01759 goto error;
01760 }
01761 } else if (token && token->type == BO_TK) {
01762 CRAttrSel *attr_sel = NULL;
01763 CRAdditionalSel *add_sel = NULL;
01764
01765 status = cr_tknzr_unget_token
01766 (PRIVATE (a_this)->tknzr, token);
01767 if (status != CR_OK)
01768 goto error;
01769 token = NULL;
01770
01771 status = cr_parser_parse_attribute_selector
01772 (a_this, &attr_sel);
01773 CHECK_PARSING_STATUS (status, FALSE);
01774
01775 add_sel = cr_additional_sel_new_with_type
01776 (ATTRIBUTE_ADD_SELECTOR);
01777
01778 ENSURE_PARSING_COND (add_sel != NULL);
01779
01780 add_sel->content.attr_sel = attr_sel;
01781
01782 add_sel_list =
01783 cr_additional_sel_append
01784 (add_sel_list, add_sel);
01785 found_sel = TRUE;
01786 cr_parsing_location_copy
01787 (&add_sel->location,
01788 &attr_sel->location) ;
01789 } else if (token && (token->type == DELIM_TK)
01790 && (token->u.unichar == ':')) {
01791 CRPseudo *pseudo = NULL;
01792
01793
01794
01795 if (token) {
01796 cr_token_destroy (token);
01797 token = NULL;
01798 }
01799
01800 pseudo = cr_pseudo_new ();
01801
01802 status = cr_tknzr_get_next_token
01803 (PRIVATE (a_this)->tknzr, &token);
01804 ENSURE_PARSING_COND (status == CR_OK && token);
01805
01806 cr_parsing_location_copy
01807 (&pseudo->location,
01808 &token->location) ;
01809
01810 if (token->type == IDENT_TK) {
01811 pseudo->type = IDENT_PSEUDO;
01812 pseudo->name = token->u.str;
01813 token->u.str = NULL;
01814 found_sel = TRUE;
01815 } else if (token->type == FUNCTION_TK) {
01816 pseudo->name = token->u.str;
01817 token->u.str = NULL;
01818 cr_parser_try_to_skip_spaces_and_comments
01819 (a_this);
01820 status = cr_parser_parse_ident
01821 (a_this, &pseudo->extra);
01822
01823 ENSURE_PARSING_COND (status == CR_OK);
01824 READ_NEXT_CHAR (a_this, &cur_char);
01825 ENSURE_PARSING_COND (cur_char == ')');
01826 pseudo->type = FUNCTION_PSEUDO;
01827 found_sel = TRUE;
01828 } else {
01829 status = CR_PARSING_ERROR;
01830 goto error;
01831 }
01832
01833 if (status == CR_OK) {
01834 CRAdditionalSel *add_sel = NULL;
01835
01836 add_sel = cr_additional_sel_new_with_type
01837 (PSEUDO_CLASS_ADD_SELECTOR);
01838
01839 add_sel->content.pseudo = pseudo;
01840 cr_parsing_location_copy
01841 (&add_sel->location,
01842 &pseudo->location) ;
01843 add_sel_list =
01844 cr_additional_sel_append
01845 (add_sel_list, add_sel);
01846 status = CR_OK;
01847 }
01848 } else {
01849 status = cr_tknzr_unget_token
01850 (PRIVATE (a_this)->tknzr, token);
01851 token = NULL;
01852 break;
01853 }
01854 }
01855
01856 if (status == CR_OK && found_sel == TRUE) {
01857 cr_parser_try_to_skip_spaces_and_comments (a_this);
01858
01859 sel->add_sel = add_sel_list;
01860 add_sel_list = NULL;
01861
01862 if (*a_sel == NULL) {
01863 *a_sel = sel;
01864 } else {
01865 cr_simple_sel_append_simple_sel (*a_sel, sel);
01866 }
01867
01868 sel = NULL;
01869
01870 if (token) {
01871 cr_token_destroy (token);
01872 token = NULL;
01873 }
01874
01875 cr_parser_clear_errors (a_this);
01876 return CR_OK;
01877 } else {
01878 status = CR_PARSING_ERROR;
01879 }
01880
01881 error:
01882
01883 if (token) {
01884 cr_token_destroy (token);
01885 token = NULL;
01886 }
01887
01888 if (add_sel_list) {
01889 cr_additional_sel_destroy (add_sel_list);
01890 add_sel_list = NULL;
01891 }
01892
01893 if (sel) {
01894 cr_simple_sel_destroy (sel);
01895 sel = NULL;
01896 }
01897
01898 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01899
01900 return status;
01901
01902 }
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916 static enum CRStatus
01917 cr_parser_parse_simple_sels (CRParser * a_this,
01918 CRSimpleSel ** a_sel)
01919 {
01920 enum CRStatus status = CR_ERROR;
01921 CRInputPos init_pos;
01922 CRSimpleSel *sel = NULL;
01923 guint32 cur_char = 0;
01924
01925 g_return_val_if_fail (a_this
01926 && PRIVATE (a_this)
01927 && a_sel,
01928 CR_BAD_PARAM_ERROR);
01929
01930 RECORD_INITIAL_POS (a_this, &init_pos);
01931
01932 status = cr_parser_parse_simple_selector (a_this, &sel);
01933 CHECK_PARSING_STATUS (status, FALSE);
01934
01935 *a_sel = cr_simple_sel_append_simple_sel (*a_sel, sel);
01936
01937 for (;;) {
01938 guint32 next_char = 0;
01939 enum Combinator comb = 0;
01940
01941 sel = NULL;
01942
01943 PEEK_NEXT_CHAR (a_this, &next_char);
01944
01945 if (next_char == '+') {
01946 READ_NEXT_CHAR (a_this, &cur_char);
01947 comb = COMB_PLUS;
01948 cr_parser_try_to_skip_spaces_and_comments (a_this);
01949 } else if (next_char == '>') {
01950 READ_NEXT_CHAR (a_this, &cur_char);
01951 comb = COMB_GT;
01952 cr_parser_try_to_skip_spaces_and_comments (a_this);
01953 } else {
01954 comb = COMB_WS;
01955 }
01956
01957 status = cr_parser_parse_simple_selector (a_this, &sel);
01958 if (status != CR_OK)
01959 break;
01960
01961 if (comb && sel) {
01962 sel->combinator = comb;
01963 comb = 0;
01964 }
01965 if (sel) {
01966 *a_sel = cr_simple_sel_append_simple_sel (*a_sel,
01967 sel) ;
01968 }
01969 }
01970 cr_parser_clear_errors (a_this);
01971 return CR_OK;
01972
01973 error:
01974
01975 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
01976
01977 return status;
01978 }
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988 static enum CRStatus
01989 cr_parser_parse_selector (CRParser * a_this,
01990 CRSelector ** a_selector)
01991 {
01992 enum CRStatus status = CR_OK;
01993 CRInputPos init_pos;
01994 guint32 cur_char = 0,
01995 next_char = 0;
01996 CRSimpleSel *simple_sels = NULL;
01997 CRSelector *selector = NULL;
01998
01999 g_return_val_if_fail (a_this && a_selector, CR_BAD_PARAM_ERROR);
02000
02001 RECORD_INITIAL_POS (a_this, &init_pos);
02002
02003 status = cr_parser_parse_simple_sels (a_this, &simple_sels);
02004 CHECK_PARSING_STATUS (status, FALSE);
02005
02006 if (simple_sels) {
02007 selector = cr_selector_append_simple_sel
02008 (selector, simple_sels);
02009 if (selector) {
02010 cr_parsing_location_copy
02011 (&selector->location,
02012 &simple_sels->location) ;
02013 }
02014 simple_sels = NULL;
02015 } else {
02016 status = CR_PARSING_ERROR ;
02017 goto error ;
02018 }
02019
02020 status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr,
02021 &next_char);
02022 if (status != CR_OK) {
02023 if (status == CR_END_OF_INPUT_ERROR) {
02024 status = CR_OK;
02025 goto okay;
02026 } else {
02027 goto error;
02028 }
02029 }
02030
02031 if (next_char == ',') {
02032 for (;;) {
02033 simple_sels = NULL;
02034
02035 status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr,
02036 &next_char);
02037 if (status != CR_OK) {
02038 if (status == CR_END_OF_INPUT_ERROR) {
02039 status = CR_OK;
02040 break;
02041 } else {
02042 goto error;
02043 }
02044 }
02045
02046 if (next_char != ',')
02047 break;
02048
02049
02050 READ_NEXT_CHAR (a_this, &cur_char);
02051
02052 cr_parser_try_to_skip_spaces_and_comments (a_this);
02053
02054 status = cr_parser_parse_simple_sels
02055 (a_this, &simple_sels);
02056
02057 CHECK_PARSING_STATUS (status, FALSE);
02058
02059 if (simple_sels) {
02060 selector =
02061 cr_selector_append_simple_sel
02062 (selector, simple_sels);
02063
02064 simple_sels = NULL;
02065 }
02066 }
02067 }
02068
02069 okay:
02070 cr_parser_try_to_skip_spaces_and_comments (a_this);
02071
02072 if (!*a_selector) {
02073 *a_selector = selector;
02074 } else {
02075 *a_selector = cr_selector_append (*a_selector, selector);
02076 }
02077
02078 selector = NULL;
02079 return CR_OK;
02080
02081 error:
02082
02083 if (simple_sels) {
02084 cr_simple_sel_destroy (simple_sels);
02085 simple_sels = NULL;
02086 }
02087
02088 if (selector) {
02089 cr_selector_unref (selector);
02090 selector = NULL;
02091 }
02092
02093 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
02094
02095 return status;
02096 }
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110 static enum CRStatus
02111 cr_parser_parse_function (CRParser * a_this,
02112 CRString ** a_func_name,
02113 CRTerm ** a_expr)
02114 {
02115 CRInputPos init_pos;
02116 enum CRStatus status = CR_OK;
02117 CRToken *token = NULL;
02118 CRTerm *expr = NULL;
02119
02120 g_return_val_if_fail (a_this && PRIVATE (a_this)
02121 && a_func_name,
02122 CR_BAD_PARAM_ERROR);
02123
02124 RECORD_INITIAL_POS (a_this, &init_pos);
02125
02126 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
02127 if (status != CR_OK)
02128 goto error;
02129
02130 if (token && token->type == FUNCTION_TK) {
02131 *a_func_name = token->u.str;
02132 token->u.str = NULL;
02133 } else {
02134 status = CR_PARSING_ERROR;
02135 goto error;
02136 }
02137 cr_token_destroy (token);
02138 token = NULL;
02139
02140 cr_parser_try_to_skip_spaces_and_comments (a_this) ;
02141
02142 status = cr_parser_parse_expr (a_this, &expr);
02143
02144 CHECK_PARSING_STATUS (status, FALSE);
02145
02146 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
02147 if (status != CR_OK)
02148 goto error;
02149
02150 ENSURE_PARSING_COND (token && token->type == PC_TK);
02151
02152 cr_token_destroy (token);
02153 token = NULL;
02154
02155 if (expr) {
02156 *a_expr = cr_term_append_term (*a_expr, expr);
02157 expr = NULL;
02158 }
02159
02160 cr_parser_clear_errors (a_this);
02161 return CR_OK;
02162
02163 error:
02164
02165 if (*a_func_name) {
02166 cr_string_destroy (*a_func_name);
02167 *a_func_name = NULL;
02168 }
02169
02170 if (expr) {
02171 cr_term_destroy (expr);
02172 expr = NULL;
02173 }
02174
02175 if (token) {
02176 cr_token_destroy (token);
02177
02178 }
02179
02180 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
02181
02182 return status;
02183 }
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194 static enum CRStatus
02195 cr_parser_parse_uri (CRParser * a_this, CRString ** a_str)
02196 {
02197
02198 enum CRStatus status = CR_PARSING_ERROR;
02199
02200 g_return_val_if_fail (a_this && PRIVATE (a_this)
02201 && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
02202
02203 status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr,
02204 URI_TK, NO_ET, a_str, NULL);
02205 return status;
02206 }
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223 static enum CRStatus
02224 cr_parser_parse_string (CRParser * a_this, CRString ** a_str)
02225 {
02226 enum CRStatus status = CR_OK;
02227
02228 g_return_val_if_fail (a_this && PRIVATE (a_this)
02229 && PRIVATE (a_this)->tknzr
02230 && a_str, CR_BAD_PARAM_ERROR);
02231
02232 status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr,
02233 STRING_TK, NO_ET, a_str, NULL);
02234 return status;
02235 }
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251 static enum CRStatus
02252 cr_parser_parse_ident (CRParser * a_this, CRString ** a_str)
02253 {
02254 enum CRStatus status = CR_OK;
02255
02256 g_return_val_if_fail (a_this && PRIVATE (a_this)
02257 && PRIVATE (a_this)->tknzr
02258 && a_str, CR_BAD_PARAM_ERROR);
02259
02260 status = cr_tknzr_parse_token (PRIVATE (a_this)->tknzr,
02261 IDENT_TK, NO_ET, a_str, NULL);
02262 return status;
02263 }
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283 static enum CRStatus
02284 cr_parser_parse_stylesheet (CRParser * a_this)
02285 {
02286 enum CRStatus status = CR_OK;
02287 CRInputPos init_pos;
02288 CRToken *token = NULL;
02289 CRString *charset = NULL;
02290
02291 g_return_val_if_fail (a_this && PRIVATE (a_this)
02292 && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
02293
02294 RECORD_INITIAL_POS (a_this, &init_pos);
02295
02296 PRIVATE (a_this)->state = READY_STATE;
02297
02298 if (PRIVATE (a_this)->sac_handler
02299 && PRIVATE (a_this)->sac_handler->start_document) {
02300 PRIVATE (a_this)->sac_handler->start_document
02301 (PRIVATE (a_this)->sac_handler);
02302 }
02303
02304 parse_charset:
02305 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
02306
02307 if (status == CR_END_OF_INPUT_ERROR)
02308 goto done;
02309 CHECK_PARSING_STATUS (status, TRUE);
02310
02311 if (token && token->type == CHARSET_SYM_TK) {
02312 CRParsingLocation location = {0} ;
02313 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
02314 token);
02315 CHECK_PARSING_STATUS (status, TRUE);
02316 token = NULL;
02317
02318 status = cr_parser_parse_charset (a_this,
02319 &charset,
02320 &location);
02321
02322 if (status == CR_OK && charset) {
02323 if (PRIVATE (a_this)->sac_handler
02324 && PRIVATE (a_this)->sac_handler->charset) {
02325 PRIVATE (a_this)->sac_handler->charset
02326 (PRIVATE (a_this)->sac_handler,
02327 charset, &location);
02328 }
02329 } else if (status != CR_END_OF_INPUT_ERROR) {
02330 status = cr_parser_parse_atrule_core (a_this);
02331 CHECK_PARSING_STATUS (status, FALSE);
02332 }
02333
02334 if (charset) {
02335 cr_string_destroy (charset);
02336 charset = NULL;
02337 }
02338 } else if (token
02339 && (token->type == S_TK
02340 || token->type == COMMENT_TK)) {
02341 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
02342 token);
02343 token = NULL;
02344 CHECK_PARSING_STATUS (status, TRUE);
02345
02346 cr_parser_try_to_skip_spaces_and_comments (a_this);
02347 goto parse_charset ;
02348 } else if (token) {
02349 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
02350 token);
02351 token = NULL;
02352 CHECK_PARSING_STATUS (status, TRUE);
02353 }
02354
02355
02356 do {
02357 if (token) {
02358 cr_token_destroy (token);
02359 token = NULL;
02360 }
02361 cr_parser_try_to_skip_spaces_and_comments (a_this) ;
02362 status = cr_tknzr_get_next_token
02363 (PRIVATE (a_this)->tknzr, &token);
02364
02365 if (status == CR_END_OF_INPUT_ERROR)
02366 goto done;
02367 CHECK_PARSING_STATUS (status, TRUE);
02368 } while (token
02369 && (token->type == S_TK
02370 || token->type == CDO_TK || token->type == CDC_TK));
02371
02372 if (token) {
02373 status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr,
02374 token);
02375 token = NULL;
02376 }
02377
02378 for (;;) {
02379 status = cr_tknzr_get_next_token
02380 (PRIVATE (a_this)->tknzr, &token);
02381 if (status == CR_END_OF_INPUT_ERROR)
02382 goto done;
02383 CHECK_PARSING_STATUS (status, TRUE);
02384
02385 if (token && token->type == IMPORT_SYM_TK) {
02386 GList *media_list = NULL;
02387 CRString *import_string = NULL;
02388 CRParsingLocation location = {0} ;
02389
02390 status = cr_tknzr_unget_token
02391 (PRIVATE (a_this)->tknzr, token);
02392 token = NULL;
02393 CHECK_PARSING_STATUS (status, TRUE);
02394
02395 status = cr_parser_parse_import (a_this,
02396 &media_list,
02397 &import_string,
02398 &location);
02399 if (status == CR_OK) {
02400 if (import_string
02401 && PRIVATE (a_this)->sac_handler
02402 && PRIVATE (a_this)->sac_handler->import_style) {
02403 PRIVATE (a_this)->sac_handler->import_style
02404 (PRIVATE(a_this)->sac_handler,
02405 media_list,
02406 import_string,
02407 NULL, &location) ;
02408
02409 if ((PRIVATE (a_this)->sac_handler->resolve_import == TRUE)) {
02410
02411
02412
02413
02414 }
02415
02416 if ((PRIVATE (a_this)->sac_handler->import_style_result)) {
02417 PRIVATE (a_this)->sac_handler->import_style_result
02418 (PRIVATE (a_this)->sac_handler,
02419 media_list, import_string,
02420 NULL, NULL);
02421 }
02422 }
02423 } else if (status != CR_END_OF_INPUT_ERROR) {
02424 if (PRIVATE (a_this)->sac_handler
02425 && PRIVATE (a_this)->sac_handler->error) {
02426 PRIVATE (a_this)->sac_handler->error
02427 (PRIVATE (a_this)->sac_handler);
02428 }
02429 status = cr_parser_parse_atrule_core (a_this);
02430 CHECK_PARSING_STATUS (status, TRUE) ;
02431 } else {
02432 goto error ;
02433 }
02434
02435
02436
02437
02438
02439
02440 if (media_list) {
02441 GList *cur = NULL;
02442
02443
02444 for (cur = media_list; cur; cur = cur->next) {
02445 if (cur->data) {
02446 cr_string_destroy (cur->data);
02447 }
02448 }
02449
02450 g_list_free (media_list);
02451 media_list = NULL;
02452 }
02453
02454 if (import_string) {
02455 cr_string_destroy (import_string);
02456 import_string = NULL;
02457 }
02458
02459 cr_parser_try_to_skip_spaces_and_comments (a_this);
02460 } else if (token
02461 && (token->type == S_TK
02462 || token->type == CDO_TK
02463 || token->type == CDC_TK)) {
02464 status = cr_tknzr_unget_token
02465 (PRIVATE (a_this)->tknzr, token);
02466 token = NULL;
02467
02468 do {
02469 if (token) {
02470 cr_token_destroy (token);
02471 token = NULL;
02472 }
02473
02474 status = cr_tknzr_get_next_token
02475 (PRIVATE (a_this)->tknzr, &token);
02476
02477 if (status == CR_END_OF_INPUT_ERROR)
02478 goto done;
02479 CHECK_PARSING_STATUS (status, TRUE);
02480 } while (token
02481 && (token->type == S_TK
02482 || token->type == CDO_TK
02483 || token->type == CDC_TK));
02484 } else {
02485 if (token) {
02486 status = cr_tknzr_unget_token
02487 (PRIVATE (a_this)->tknzr, token);
02488 token = NULL;
02489 }
02490 goto parse_ruleset_and_others;
02491 }
02492 }
02493
02494 parse_ruleset_and_others:
02495
02496 cr_parser_try_to_skip_spaces_and_comments (a_this);
02497
02498 for (;;) {
02499 status = cr_tknzr_get_next_token
02500 (PRIVATE (a_this)->tknzr, &token);
02501 if (status == CR_END_OF_INPUT_ERROR)
02502 goto done;
02503 CHECK_PARSING_STATUS (status, TRUE);
02504
02505 if (token
02506 && (token->type == S_TK
02507 || token->type == CDO_TK || token->type == CDC_TK)) {
02508 status = cr_tknzr_unget_token
02509 (PRIVATE (a_this)->tknzr, token);
02510 token = NULL;
02511
02512 do {
02513 if (token) {
02514 cr_token_destroy (token);
02515 token = NULL;
02516 }
02517
02518 cr_parser_try_to_skip_spaces_and_comments
02519 (a_this);
02520 status = cr_tknzr_get_next_token
02521 (PRIVATE (a_this)->tknzr, &token);
02522 } while (token
02523 && (token->type == S_TK
02524 || token->type == COMMENT_TK
02525 || token->type == CDO_TK
02526 || token->type == CDC_TK));
02527 if (token) {
02528 cr_tknzr_unget_token
02529 (PRIVATE (a_this)->tknzr, token);
02530 token = NULL;
02531 }
02532 } else if (token
02533 && (token->type == HASH_TK
02534 || (token->type == DELIM_TK
02535 && token->u.unichar == '.')
02536 || (token->type == DELIM_TK
02537 && token->u.unichar == ':')
02538 || (token->type == DELIM_TK
02539 && token->u.unichar == '*')
02540 || (token->type == BO_TK)
02541 || token->type == IDENT_TK)) {
02542
02543
02544
02545
02546
02547 status = cr_tknzr_unget_token
02548 (PRIVATE (a_this)->tknzr, token);
02549 CHECK_PARSING_STATUS (status, TRUE);
02550 token = NULL;
02551
02552 status = cr_parser_parse_ruleset (a_this);
02553
02554 if (status == CR_OK) {
02555 continue;
02556 } else {
02557 if (PRIVATE (a_this)->sac_handler
02558 && PRIVATE (a_this)->sac_handler->error) {
02559 PRIVATE (a_this)->sac_handler->
02560 error
02561 (PRIVATE (a_this)->
02562 sac_handler);
02563 }
02564
02565 status = cr_parser_parse_ruleset_core
02566 (a_this);
02567
02568 if (status == CR_OK) {
02569 continue;
02570 } else {
02571 break;
02572 }
02573 }
02574 } else if (token && token->type == MEDIA_SYM_TK) {
02575 status = cr_tknzr_unget_token
02576 (PRIVATE (a_this)->tknzr, token);
02577 CHECK_PARSING_STATUS (status, TRUE);
02578 token = NULL;
02579
02580 status = cr_parser_parse_media (a_this);
02581 if (status == CR_OK) {
02582 continue;
02583 } else {
02584 if (PRIVATE (a_this)->sac_handler
02585 && PRIVATE (a_this)->sac_handler->error) {
02586 PRIVATE (a_this)->sac_handler->
02587 error
02588 (PRIVATE (a_this)->
02589 sac_handler);
02590 }
02591
02592 status = cr_parser_parse_atrule_core (a_this);
02593
02594 if (status == CR_OK) {
02595 continue;
02596 } else {
02597 break;
02598 }
02599 }
02600
02601 } else if (token && token->type == PAGE_SYM_TK) {
02602 status = cr_tknzr_unget_token
02603 (PRIVATE (a_this)->tknzr, token);
02604 CHECK_PARSING_STATUS (status, TRUE);
02605 token = NULL;
02606 status = cr_parser_parse_page (a_this);
02607
02608 if (status == CR_OK) {
02609 continue;
02610 } else {
02611 if (PRIVATE (a_this)->sac_handler
02612 && PRIVATE (a_this)->sac_handler->error) {
02613 PRIVATE (a_this)->sac_handler->
02614 error
02615 (PRIVATE (a_this)->
02616 sac_handler);
02617 }
02618
02619 status = cr_parser_parse_atrule_core (a_this);
02620
02621 if (status == CR_OK) {
02622 continue;
02623 } else {
02624 break;
02625 }
02626 }
02627 } else if (token && token->type == FONT_FACE_SYM_TK) {
02628 status = cr_tknzr_unget_token
02629 (PRIVATE (a_this)->tknzr, token);
02630 CHECK_PARSING_STATUS (status, TRUE);
02631 token = NULL;
02632 status = cr_parser_parse_font_face (a_this);
02633
02634 if (status == CR_OK) {
02635 continue;
02636 } else {
02637 if (PRIVATE (a_this)->sac_handler
02638 && PRIVATE (a_this)->sac_handler->error) {
02639 PRIVATE (a_this)->sac_handler->
02640 error
02641 (PRIVATE (a_this)->
02642 sac_handler);
02643 }
02644
02645 status = cr_parser_parse_atrule_core (a_this);
02646
02647 if (status == CR_OK) {
02648 continue;
02649 } else {
02650 break;
02651 }
02652 }
02653 } else {
02654 status = cr_tknzr_unget_token
02655 (PRIVATE (a_this)->tknzr, token);
02656 CHECK_PARSING_STATUS (status, TRUE);
02657 token = NULL;
02658 status = cr_parser_parse_statement_core (a_this);
02659
02660 if (status == CR_OK) {
02661 continue;
02662 } else {
02663 break;
02664 }
02665 }
02666 }
02667
02668 done:
02669 if (token) {
02670 cr_token_destroy (token);
02671 token = NULL;
02672 }
02673
02674 if (status == CR_END_OF_INPUT_ERROR || status == CR_OK) {
02675
02676 if (PRIVATE (a_this)->sac_handler
02677 && PRIVATE (a_this)->sac_handler->end_document) {
02678 PRIVATE (a_this)->sac_handler->end_document
02679 (PRIVATE (a_this)->sac_handler);
02680 }
02681
02682 return CR_OK;
02683 }
02684
02685 cr_parser_push_error
02686 (a_this, "could not recognize next production", CR_ERROR);
02687
02688 if (PRIVATE (a_this)->sac_handler
02689 && PRIVATE (a_this)->sac_handler->unrecoverable_error) {
02690 PRIVATE (a_this)->sac_handler->
02691 unrecoverable_error (PRIVATE (a_this)->sac_handler);
02692 }
02693
02694 cr_parser_dump_err_stack (a_this, TRUE);
02695
02696 return status;
02697
02698 error:
02699
02700 if (token) {
02701 cr_token_destroy (token);
02702 token = NULL;
02703 }
02704
02705 if (PRIVATE (a_this)->sac_handler
02706 && PRIVATE (a_this)->sac_handler->unrecoverable_error) {
02707 PRIVATE (a_this)->sac_handler->
02708 unrecoverable_error (PRIVATE (a_this)->sac_handler);
02709 }
02710
02711 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
02712
02713 return status;
02714 }
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730 CRParser *
02731 cr_parser_new (CRTknzr * a_tknzr)
02732 {
02733 CRParser *result = NULL;
02734 enum CRStatus status = CR_OK;
02735
02736 result = g_malloc0 (sizeof (CRParser));
02737
02738 PRIVATE (result) = g_malloc0 (sizeof (CRParserPriv));
02739
02740 if (a_tknzr) {
02741 status = cr_parser_set_tknzr (result, a_tknzr);
02742 }
02743
02744 g_return_val_if_fail (status == CR_OK, NULL);
02745
02746 return result;
02747 }
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760 CRParser *
02761 cr_parser_new_from_buf (guchar * a_buf,
02762 gulong a_len,
02763 enum CREncoding a_enc,
02764 gboolean a_free_buf)
02765 {
02766 CRParser *result = NULL;
02767 CRInput *input = NULL;
02768
02769 g_return_val_if_fail (a_buf && a_len, NULL);
02770
02771 input = cr_input_new_from_buf (a_buf, a_len, a_enc, a_free_buf);
02772 g_return_val_if_fail (input, NULL);
02773
02774 result = cr_parser_new_from_input (input);
02775 if (!result) {
02776 cr_input_destroy (input);
02777 input = NULL;
02778 return NULL;
02779 }
02780 return result;
02781 }
02782
02783 CRParser *
02784 cr_parser_new_from_input (CRInput * a_input)
02785 {
02786 CRParser *result = NULL;
02787 CRTknzr *tokenizer = NULL;
02788
02789 if (a_input) {
02790 tokenizer = cr_tknzr_new (a_input);
02791 g_return_val_if_fail (tokenizer, NULL);
02792 }
02793
02794 result = cr_parser_new (tokenizer);
02795 g_return_val_if_fail (result, NULL);
02796
02797 return result;
02798 }
02799
02800 CRParser *
02801 cr_parser_new_from_file (const guchar * a_file_uri, enum CREncoding a_enc)
02802 {
02803 CRParser *result = NULL;
02804 CRTknzr *tokenizer = NULL;
02805
02806 tokenizer = cr_tknzr_new_from_uri (a_file_uri, a_enc);
02807 if (!tokenizer) {
02808 cr_utils_trace_info ("Could not open input file");
02809 return NULL;
02810 }
02811
02812 result = cr_parser_new (tokenizer);
02813 g_return_val_if_fail (result, NULL);
02814 return result;
02815 }
02816
02817
02818
02819
02820
02821
02822
02823 enum CRStatus
02824 cr_parser_set_sac_handler (CRParser * a_this, CRDocHandler * a_handler)
02825 {
02826 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
02827
02828 if (PRIVATE (a_this)->sac_handler) {
02829 cr_doc_handler_unref (PRIVATE (a_this)->sac_handler);
02830 }
02831
02832 PRIVATE (a_this)->sac_handler = a_handler;
02833 cr_doc_handler_ref (a_handler);
02834
02835 return CR_OK;
02836 }
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846 enum CRStatus
02847 cr_parser_get_sac_handler (CRParser * a_this, CRDocHandler ** a_handler)
02848 {
02849 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
02850
02851 *a_handler = PRIVATE (a_this)->sac_handler;
02852
02853 return CR_OK;
02854 }
02855
02856
02857
02858
02859
02860
02861
02862 enum CRStatus
02863 cr_parser_set_default_sac_handler (CRParser * a_this)
02864 {
02865 CRDocHandler *default_sac_handler = NULL;
02866 enum CRStatus status = CR_ERROR;
02867
02868 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
02869
02870 default_sac_handler = cr_doc_handler_new ();
02871
02872 cr_doc_handler_set_default_sac_handler (default_sac_handler);
02873
02874 status = cr_parser_set_sac_handler (a_this, default_sac_handler);
02875
02876 if (status != CR_OK) {
02877 cr_doc_handler_destroy (default_sac_handler);
02878 default_sac_handler = NULL;
02879 }
02880
02881 return status;
02882 }
02883
02884 enum CRStatus
02885 cr_parser_set_use_core_grammar (CRParser * a_this,
02886 gboolean a_use_core_grammar)
02887 {
02888 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
02889
02890 PRIVATE (a_this)->use_core_grammar = a_use_core_grammar;
02891
02892 return CR_OK;
02893 }
02894
02895 enum CRStatus
02896 cr_parser_get_use_core_grammar (CRParser * a_this,
02897 gboolean * a_use_core_grammar)
02898 {
02899 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
02900
02901 *a_use_core_grammar = PRIVATE (a_this)->use_core_grammar;
02902
02903 return CR_OK;
02904 }
02905
02906
02907
02908
02909
02910
02911
02912
02913 enum CRStatus
02914 cr_parser_parse_file (CRParser * a_this,
02915 const guchar * a_file_uri, enum CREncoding a_enc)
02916 {
02917 enum CRStatus status = CR_ERROR;
02918 CRTknzr *tknzr = NULL;
02919
02920 g_return_val_if_fail (a_this && PRIVATE (a_this)
02921 && a_file_uri, CR_BAD_PARAM_ERROR);
02922
02923 tknzr = cr_tknzr_new_from_uri (a_file_uri, a_enc);
02924
02925 g_return_val_if_fail (tknzr != NULL, CR_ERROR);
02926
02927 status = cr_parser_set_tknzr (a_this, tknzr);
02928 g_return_val_if_fail (status == CR_OK, CR_ERROR);
02929
02930 status = cr_parser_parse (a_this);
02931
02932 return status;
02933 }
02934
02935
02936
02937
02938
02939
02940 enum CRStatus
02941 cr_parser_parse_expr (CRParser * a_this, CRTerm ** a_expr)
02942 {
02943 enum CRStatus status = CR_ERROR;
02944 CRInputPos init_pos;
02945 CRTerm *expr = NULL,
02946 *expr2 = NULL;
02947 guchar next_byte = 0;
02948 gulong nb_terms = 0;
02949
02950 g_return_val_if_fail (a_this && PRIVATE (a_this)
02951 && a_expr, CR_BAD_PARAM_ERROR);
02952
02953 RECORD_INITIAL_POS (a_this, &init_pos);
02954
02955 status = cr_parser_parse_term (a_this, &expr);
02956
02957 CHECK_PARSING_STATUS (status, FALSE);
02958
02959 for (;;) {
02960 guchar operator = 0;
02961
02962 status = cr_tknzr_peek_byte (PRIVATE (a_this)->tknzr,
02963 1, &next_byte);
02964 if (status != CR_OK) {
02965 if (status == CR_END_OF_INPUT_ERROR) {
02966
02967
02968
02969
02970
02971
02972 status = CR_OK;
02973 break;
02974 } else {
02975 goto error;
02976 }
02977 }
02978
02979 if (next_byte == '/' || next_byte == ',') {
02980 READ_NEXT_BYTE (a_this, &operator);
02981 }
02982
02983 cr_parser_try_to_skip_spaces_and_comments (a_this);
02984
02985 status = cr_parser_parse_term (a_this, &expr2);
02986
02987 if (status != CR_OK || expr2 == NULL) {
02988 status = CR_OK;
02989 break;
02990 }
02991
02992 switch (operator) {
02993 case '/':
02994 expr2->the_operator = DIVIDE;
02995 break;
02996 case ',':
02997 expr2->the_operator = COMMA;
02998
02999 default:
03000 break;
03001 }
03002
03003 expr = cr_term_append_term (expr, expr2);
03004 expr2 = NULL;
03005 operator = 0;
03006 nb_terms++;
03007 }
03008
03009 if (status == CR_OK) {
03010 *a_expr = cr_term_append_term (*a_expr, expr);
03011 expr = NULL;
03012
03013 cr_parser_clear_errors (a_this);
03014 return CR_OK;
03015 }
03016
03017 error:
03018
03019 if (expr) {
03020 cr_term_destroy (expr);
03021 expr = NULL;
03022 }
03023
03024 if (expr2) {
03025 cr_term_destroy (expr2);
03026 expr2 = NULL;
03027 }
03028
03029 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
03030
03031 return status;
03032 }
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042
03043 enum CRStatus
03044 cr_parser_parse_prio (CRParser * a_this, CRString ** a_prio)
03045 {
03046 enum CRStatus status = CR_ERROR;
03047 CRInputPos init_pos;
03048 CRToken *token = NULL;
03049
03050 g_return_val_if_fail (a_this && PRIVATE (a_this)
03051 && a_prio
03052 && *a_prio == NULL, CR_BAD_PARAM_ERROR);
03053
03054 RECORD_INITIAL_POS (a_this, &init_pos);
03055
03056 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
03057 if (status == CR_END_OF_INPUT_ERROR) {
03058 goto error;
03059 }
03060 ENSURE_PARSING_COND (status == CR_OK
03061 && token && token->type == IMPORTANT_SYM_TK);
03062
03063 cr_parser_try_to_skip_spaces_and_comments (a_this);
03064 *a_prio = cr_string_new_from_string ("!important");
03065 cr_token_destroy (token);
03066 token = NULL;
03067 return CR_OK;
03068
03069 error:
03070 if (token) {
03071 cr_token_destroy (token);
03072 token = NULL;
03073 }
03074 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
03075
03076 return status;
03077 }
03078
03079
03080
03081
03082
03083
03084
03085
03086
03087
03088
03089
03090
03091
03092 enum CRStatus
03093 cr_parser_parse_declaration (CRParser * a_this,
03094 CRString ** a_property,
03095 CRTerm ** a_expr, gboolean * a_important)
03096 {
03097 enum CRStatus status = CR_ERROR;
03098 CRInputPos init_pos;
03099 guint32 cur_char = 0;
03100 CRTerm *expr = NULL;
03101 CRString *prio = NULL;
03102
03103 g_return_val_if_fail (a_this && PRIVATE (a_this)
03104 && a_property && a_expr
03105 && a_important, CR_BAD_PARAM_ERROR);
03106
03107 RECORD_INITIAL_POS (a_this, &init_pos);
03108
03109 status = cr_parser_parse_property (a_this, a_property);
03110
03111 if (status == CR_END_OF_INPUT_ERROR)
03112 goto error;
03113
03114 CHECK_PARSING_STATUS_ERR
03115 (a_this, status, FALSE,
03116 "while parsing declaration: next property is malformed",
03117 CR_SYNTAX_ERROR);
03118
03119 READ_NEXT_CHAR (a_this, &cur_char);
03120
03121 if (cur_char != ':') {
03122 status = CR_PARSING_ERROR;
03123 cr_parser_push_error
03124 (a_this,
03125 "while parsing declaration: this char must be ':'",
03126 CR_SYNTAX_ERROR);
03127 goto error;
03128 }
03129
03130 cr_parser_try_to_skip_spaces_and_comments (a_this);
03131
03132 status = cr_parser_parse_expr (a_this, &expr);
03133
03134 CHECK_PARSING_STATUS_ERR
03135 (a_this, status, FALSE,
03136 "while parsing declaration: next expression is malformed",
03137 CR_SYNTAX_ERROR);
03138
03139 cr_parser_try_to_skip_spaces_and_comments (a_this);
03140 status = cr_parser_parse_prio (a_this, &prio);
03141 if (prio) {
03142 cr_string_destroy (prio);
03143 prio = NULL;
03144 *a_important = TRUE;
03145 } else {
03146 *a_important = FALSE;
03147 }
03148 if (*a_expr) {
03149 cr_term_append_term (*a_expr, expr);
03150 expr = NULL;
03151 } else {
03152 *a_expr = expr;
03153 expr = NULL;
03154 }
03155
03156 cr_parser_clear_errors (a_this);
03157 return CR_OK;
03158
03159 error:
03160
03161 if (expr) {
03162 cr_term_destroy (expr);
03163 expr = NULL;
03164 }
03165
03166 if (*a_property) {
03167 cr_string_destroy (*a_property);
03168 *a_property = NULL;
03169 }
03170
03171 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
03172
03173 return status;
03174 }
03175
03176
03177
03178
03179
03180
03181
03182
03183 enum CRStatus
03184 cr_parser_parse_statement_core (CRParser * a_this)
03185 {
03186 CRToken *token = NULL;
03187 CRInputPos init_pos;
03188 enum CRStatus status = CR_ERROR;
03189
03190 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
03191
03192 RECORD_INITIAL_POS (a_this, &init_pos);
03193
03194 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
03195
03196 ENSURE_PARSING_COND (status == CR_OK && token);
03197
03198 switch (token->type) {
03199 case ATKEYWORD_TK:
03200 case IMPORT_SYM_TK:
03201 case PAGE_SYM_TK:
03202 case MEDIA_SYM_TK:
03203 case FONT_FACE_SYM_TK:
03204 case CHARSET_SYM_TK:
03205 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
03206 token = NULL;
03207 status = cr_parser_parse_atrule_core (a_this);
03208 CHECK_PARSING_STATUS (status, TRUE);
03209 break;
03210
03211 default:
03212 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
03213 token = NULL;
03214 status = cr_parser_parse_ruleset_core (a_this);
03215 cr_parser_clear_errors (a_this);
03216 CHECK_PARSING_STATUS (status, TRUE);
03217 }
03218
03219 return CR_OK;
03220
03221 error:
03222 if (token) {
03223 cr_token_destroy (token);
03224 token = NULL;
03225 }
03226
03227 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
03228
03229 return status;
03230 }
03231
03232
03233
03234
03235
03236
03237
03238
03239
03240
03241
03242
03243
03244 enum CRStatus
03245 cr_parser_parse_ruleset (CRParser * a_this)
03246 {
03247 enum CRStatus status = CR_OK;
03248 CRInputPos init_pos;
03249 guint32 cur_char = 0,
03250 next_char = 0;
03251 CRString *property = NULL;
03252 CRTerm *expr = NULL;
03253 CRSimpleSel *simple_sels = NULL;
03254 CRSelector *selector = NULL;
03255 gboolean start_selector = FALSE,
03256 is_important = FALSE;
03257
03258 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
03259
03260 RECORD_INITIAL_POS (a_this, &init_pos);
03261
03262 status = cr_parser_parse_selector (a_this, &selector);
03263 CHECK_PARSING_STATUS (status, FALSE);
03264
03265 READ_NEXT_CHAR (a_this, &cur_char);
03266
03267 ENSURE_PARSING_COND_ERR
03268 (a_this, cur_char == '{',
03269 "while parsing rulset: current char should be '{'",
03270 CR_SYNTAX_ERROR);
03271
03272 if (PRIVATE (a_this)->sac_handler
03273 && PRIVATE (a_this)->sac_handler->start_selector) {
03274
03275
03276
03277
03278 if (selector) {
03279 cr_selector_ref (selector);
03280 }
03281
03282 PRIVATE (a_this)->sac_handler->start_selector
03283 (PRIVATE (a_this)->sac_handler, selector);
03284 start_selector = TRUE;
03285 }
03286
03287 cr_parser_try_to_skip_spaces_and_comments (a_this);
03288
03289 PRIVATE (a_this)->state = TRY_PARSE_RULESET_STATE;
03290
03291 status = cr_parser_parse_declaration (a_this, &property,
03292 &expr,
03293 &is_important);
03294 if (expr) {
03295 cr_term_ref (expr);
03296 }
03297 if (status == CR_OK
03298 && PRIVATE (a_this)->sac_handler
03299 && PRIVATE (a_this)->sac_handler->property) {
03300 PRIVATE (a_this)->sac_handler->property
03301 (PRIVATE (a_this)->sac_handler, property, expr,
03302 is_important);
03303 }
03304 if (status == CR_OK) {
03305
03306
03307
03308
03309
03310 if (property) {
03311 cr_string_destroy (property);
03312 property = NULL;
03313 }
03314 if (expr) {
03315 cr_term_unref (expr);
03316 expr = NULL;
03317 }
03318 } else {
03319 guint32 c = 0 ;
03320
03321
03322
03323
03324
03325 status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr, &c) ;
03326 if (status == CR_OK && c == '}') {
03327 status = CR_OK ;
03328 goto end_of_ruleset ;
03329 }
03330 }
03331 CHECK_PARSING_STATUS_ERR
03332 (a_this, status, FALSE,
03333 "while parsing ruleset: next construction should be a declaration",
03334 CR_SYNTAX_ERROR);
03335
03336 for (;;) {
03337 PEEK_NEXT_CHAR (a_this, &next_char);
03338 if (next_char != ';')
03339 break;
03340
03341
03342 READ_NEXT_CHAR (a_this, &cur_char);
03343
03344 cr_parser_try_to_skip_spaces_and_comments (a_this);
03345
03346 status = cr_parser_parse_declaration (a_this, &property,
03347 &expr, &is_important);
03348
03349 if (expr) {
03350 cr_term_ref (expr);
03351 }
03352 if (status == CR_OK
03353 && PRIVATE (a_this)->sac_handler
03354 && PRIVATE (a_this)->sac_handler->property) {
03355 PRIVATE (a_this)->sac_handler->property
03356 (PRIVATE (a_this)->sac_handler,
03357 property, expr, is_important);
03358 }
03359 if (property) {
03360 cr_string_destroy (property);
03361 property = NULL;
03362 }
03363 if (expr) {
03364 cr_term_unref (expr);
03365 expr = NULL;
03366 }
03367 }
03368
03369 end_of_ruleset:
03370 cr_parser_try_to_skip_spaces_and_comments (a_this);
03371 READ_NEXT_CHAR (a_this, &cur_char);
03372 ENSURE_PARSING_COND_ERR
03373 (a_this, cur_char == '}',
03374 "while parsing rulset: current char must be a '}'",
03375 CR_SYNTAX_ERROR);
03376
03377 if (PRIVATE (a_this)->sac_handler
03378 && PRIVATE (a_this)->sac_handler->end_selector) {
03379 PRIVATE (a_this)->sac_handler->end_selector
03380 (PRIVATE (a_this)->sac_handler, selector);
03381 start_selector = FALSE;
03382 }
03383
03384 if (expr) {
03385 cr_term_unref (expr);
03386 expr = NULL;
03387 }
03388
03389 if (simple_sels) {
03390 cr_simple_sel_destroy (simple_sels);
03391 simple_sels = NULL;
03392 }
03393
03394 if (selector) {
03395 cr_selector_unref (selector);
03396 selector = NULL;
03397 }
03398
03399 cr_parser_clear_errors (a_this);
03400 PRIVATE (a_this)->state = RULESET_PARSED_STATE;
03401
03402 return CR_OK;
03403
03404 error:
03405 if (start_selector == TRUE
03406 && PRIVATE (a_this)->sac_handler
03407 && PRIVATE (a_this)->sac_handler->error) {
03408 PRIVATE (a_this)->sac_handler->error
03409 (PRIVATE (a_this)->sac_handler);
03410 }
03411 if (expr) {
03412 cr_term_unref (expr);
03413 expr = NULL;
03414 }
03415 if (simple_sels) {
03416 cr_simple_sel_destroy (simple_sels);
03417 simple_sels = NULL;
03418 }
03419 if (property) {
03420 cr_string_destroy (property);
03421 }
03422 if (selector) {
03423 cr_selector_unref (selector);
03424 selector = NULL;
03425 }
03426
03427 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
03428
03429 return status;
03430 }
03431
03432
03433
03434
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444
03445
03446
03447
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457 enum CRStatus
03458 cr_parser_parse_import (CRParser * a_this,
03459 GList ** a_media_list,
03460 CRString ** a_import_string,
03461 CRParsingLocation *a_location)
03462 {
03463 enum CRStatus status = CR_OK;
03464 CRInputPos init_pos;
03465 guint32 cur_char = 0,
03466 next_char = 0;
03467 CRString *medium = NULL;
03468
03469 g_return_val_if_fail (a_this
03470 && a_import_string
03471 && (*a_import_string == NULL),
03472 CR_BAD_PARAM_ERROR);
03473
03474 RECORD_INITIAL_POS (a_this, &init_pos);
03475
03476 if (BYTE (a_this, 1, NULL) == '@'
03477 && BYTE (a_this, 2, NULL) == 'i'
03478 && BYTE (a_this, 3, NULL) == 'm'
03479 && BYTE (a_this, 4, NULL) == 'p'
03480 && BYTE (a_this, 5, NULL) == 'o'
03481 && BYTE (a_this, 6, NULL) == 'r'
03482 && BYTE (a_this, 7, NULL) == 't') {
03483 SKIP_CHARS (a_this, 1);
03484 if (a_location) {
03485 cr_parser_get_parsing_location
03486 (a_this, a_location) ;
03487 }
03488 SKIP_CHARS (a_this, 6);
03489 status = CR_OK;
03490 } else {
03491 status = CR_PARSING_ERROR;
03492 goto error;
03493 }
03494
03495 cr_parser_try_to_skip_spaces_and_comments (a_this);
03496
03497 PRIVATE (a_this)->state = TRY_PARSE_IMPORT_STATE;
03498
03499 PEEK_NEXT_CHAR (a_this, &next_char);
03500
03501 if (next_char == '"' || next_char == '\'') {
03502 status = cr_parser_parse_string (a_this, a_import_string);
03503
03504 CHECK_PARSING_STATUS (status, FALSE);
03505 } else {
03506 status = cr_parser_parse_uri (a_this, a_import_string);
03507
03508 CHECK_PARSING_STATUS (status, FALSE);
03509 }
03510
03511 cr_parser_try_to_skip_spaces_and_comments (a_this);
03512
03513 status = cr_parser_parse_ident (a_this, &medium);
03514
03515 if (status == CR_OK && medium) {
03516 *a_media_list = g_list_append (*a_media_list, medium);
03517 medium = NULL;
03518 }
03519
03520 cr_parser_try_to_skip_spaces_and_comments (a_this);
03521
03522 for (; status == CR_OK;) {
03523 if ((status = cr_tknzr_peek_char (PRIVATE (a_this)->tknzr,
03524 &next_char)) != CR_OK) {
03525 if (status == CR_END_OF_INPUT_ERROR) {
03526 status = CR_OK;
03527 goto okay;
03528 }
03529 goto error;
03530 }
03531
03532 if (next_char == ',') {
03533 READ_NEXT_CHAR (a_this, &cur_char);
03534 } else {
03535 break;
03536 }
03537
03538 cr_parser_try_to_skip_spaces_and_comments (a_this);
03539
03540 status = cr_parser_parse_ident (a_this, &medium);
03541
03542 cr_parser_try_to_skip_spaces_and_comments (a_this);
03543
03544 if ((status == CR_OK) && medium) {
03545 *a_media_list = g_list_append (*a_media_list, medium);
03546
03547 medium = NULL;
03548 }
03549
03550 CHECK_PARSING_STATUS (status, FALSE);
03551 cr_parser_try_to_skip_spaces_and_comments (a_this);
03552 }
03553 cr_parser_try_to_skip_spaces_and_comments (a_this);
03554 READ_NEXT_CHAR (a_this, &cur_char);
03555 ENSURE_PARSING_COND (cur_char == ';');
03556 cr_parser_try_to_skip_spaces_and_comments (a_this);
03557 okay:
03558 cr_parser_clear_errors (a_this);
03559 PRIVATE (a_this)->state = IMPORT_PARSED_STATE;
03560
03561 return CR_OK;
03562
03563 error:
03564
03565 if (*a_media_list) {
03566 GList *cur = NULL;
03567
03568
03569
03570
03571
03572
03573
03574
03575
03576
03577
03578 for (cur = *a_media_list; cur; cur = cur->next) {
03579 if (cur->data) {
03580 cr_string_destroy (cur->data);
03581 }
03582 }
03583
03584 g_list_free (*a_media_list);
03585 *a_media_list = NULL;
03586 }
03587
03588 if (*a_import_string) {
03589 cr_string_destroy (*a_import_string);
03590 *a_import_string = NULL;
03591 }
03592
03593 if (medium) {
03594 cr_string_destroy (medium);
03595 medium = NULL;
03596 }
03597
03598 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
03599
03600 return status;
03601 }
03602
03603
03604
03605
03606
03607
03608
03609
03610
03611
03612
03613
03614
03615 enum CRStatus
03616 cr_parser_parse_media (CRParser * a_this)
03617 {
03618 enum CRStatus status = CR_OK;
03619 CRInputPos init_pos;
03620 CRToken *token = NULL;
03621 guint32 next_char = 0,
03622 cur_char = 0;
03623 CRString *medium = NULL;
03624 GList *media_list = NULL;
03625 CRParsingLocation location = {0} ;
03626
03627 g_return_val_if_fail (a_this
03628 && PRIVATE (a_this),
03629 CR_BAD_PARAM_ERROR);
03630
03631 RECORD_INITIAL_POS (a_this, &init_pos);
03632
03633 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
03634 &token);
03635 ENSURE_PARSING_COND (status == CR_OK
03636 && token
03637 && token->type == MEDIA_SYM_TK);
03638 cr_parsing_location_copy (&location, &token->location) ;
03639 cr_token_destroy (token);
03640 token = NULL;
03641
03642 cr_parser_try_to_skip_spaces_and_comments (a_this);
03643
03644 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
03645 ENSURE_PARSING_COND (status == CR_OK
03646 && token && token->type == IDENT_TK);
03647
03648 medium = token->u.str;
03649 token->u.str = NULL;
03650 cr_token_destroy (token);
03651 token = NULL;
03652
03653 if (medium) {
03654 media_list = g_list_append (media_list, medium);
03655 medium = NULL;
03656 }
03657
03658 for (; status == CR_OK;) {
03659 cr_parser_try_to_skip_spaces_and_comments (a_this);
03660 PEEK_NEXT_CHAR (a_this, &next_char);
03661
03662 if (next_char == ',') {
03663 READ_NEXT_CHAR (a_this, &cur_char);
03664 } else {
03665 break;
03666 }
03667
03668 cr_parser_try_to_skip_spaces_and_comments (a_this);
03669
03670 status = cr_parser_parse_ident (a_this, &medium);
03671
03672 CHECK_PARSING_STATUS (status, FALSE);
03673
03674 if (medium) {
03675 media_list = g_list_append (media_list, medium);
03676 medium = NULL;
03677 }
03678 }
03679
03680 READ_NEXT_CHAR (a_this, &cur_char);
03681
03682 ENSURE_PARSING_COND (cur_char == '{');
03683
03684
03685
03686
03687 if (PRIVATE (a_this)->sac_handler
03688 && PRIVATE (a_this)->sac_handler->start_media) {
03689 PRIVATE (a_this)->sac_handler->start_media
03690 (PRIVATE (a_this)->sac_handler, media_list,
03691 &location);
03692 }
03693
03694 cr_parser_try_to_skip_spaces_and_comments (a_this);
03695
03696 PRIVATE (a_this)->state = TRY_PARSE_MEDIA_STATE;
03697
03698 for (; status == CR_OK;) {
03699 status = cr_parser_parse_ruleset (a_this);
03700 cr_parser_try_to_skip_spaces_and_comments (a_this);
03701 }
03702
03703 READ_NEXT_CHAR (a_this, &cur_char);
03704
03705 ENSURE_PARSING_COND (cur_char == '}');
03706
03707
03708
03709
03710 if (PRIVATE (a_this)->sac_handler
03711 && PRIVATE (a_this)->sac_handler->end_media) {
03712 PRIVATE (a_this)->sac_handler->end_media
03713 (PRIVATE (a_this)->sac_handler, media_list);
03714 }
03715
03716 cr_parser_try_to_skip_spaces_and_comments (a_this);
03717
03718
03719
03720
03721
03722 if (medium) {
03723 cr_string_destroy (medium);
03724 medium = NULL;
03725 }
03726
03727 if (media_list) {
03728 GList *cur = NULL;
03729
03730 for (cur = media_list; cur; cur = cur->next) {
03731 cr_string_destroy (cur->data);
03732 }
03733
03734 g_list_free (media_list);
03735 media_list = NULL;
03736 }
03737
03738 cr_parser_clear_errors (a_this);
03739 PRIVATE (a_this)->state = MEDIA_PARSED_STATE;
03740
03741 return CR_OK;
03742
03743 error:
03744
03745 if (token) {
03746 cr_token_destroy (token);
03747 token = NULL;
03748 }
03749
03750 if (medium) {
03751 cr_string_destroy (medium);
03752 medium = NULL;
03753 }
03754
03755 if (media_list) {
03756 GList *cur = NULL;
03757
03758 for (cur = media_list; cur; cur = cur->next) {
03759 cr_string_destroy (cur->data);
03760 }
03761
03762 g_list_free (media_list);
03763 media_list = NULL;
03764 }
03765
03766 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
03767
03768 return status;
03769 }
03770
03771
03772
03773
03774
03775
03776
03777
03778
03779
03780
03781
03782 enum CRStatus
03783 cr_parser_parse_page (CRParser * a_this)
03784 {
03785 enum CRStatus status = CR_OK;
03786 CRInputPos init_pos;
03787 CRToken *token = NULL;
03788 CRTerm *css_expression = NULL;
03789 CRString *page_selector = NULL,
03790 *page_pseudo_class = NULL,
03791 *property = NULL;
03792 gboolean important = TRUE;
03793 CRParsingLocation location = {0} ;
03794
03795 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
03796
03797 RECORD_INITIAL_POS (a_this, &init_pos);
03798
03799 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
03800 &token) ;
03801 ENSURE_PARSING_COND (status == CR_OK
03802 && token
03803 && token->type == PAGE_SYM_TK);
03804
03805 cr_parsing_location_copy (&location, &token->location) ;
03806 cr_token_destroy (token);
03807 token = NULL;
03808
03809 cr_parser_try_to_skip_spaces_and_comments (a_this);
03810
03811 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
03812 ENSURE_PARSING_COND (status == CR_OK && token);
03813
03814 if (token->type == IDENT_TK) {
03815 page_selector = token->u.str;
03816 token->u.str = NULL;
03817 cr_token_destroy (token);
03818 token = NULL;
03819 } else {
03820 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
03821 token = NULL;
03822 }
03823
03824
03825
03826
03827 cr_parser_try_to_skip_spaces_and_comments (a_this);
03828 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
03829 ENSURE_PARSING_COND (status == CR_OK && token);
03830
03831 if (token->type == DELIM_TK && token->u.unichar == ':') {
03832 cr_token_destroy (token);
03833 token = NULL;
03834 status = cr_parser_parse_ident (a_this, &page_pseudo_class);
03835 CHECK_PARSING_STATUS (status, FALSE);
03836 } else {
03837 cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token);
03838 token = NULL;
03839 }
03840
03841
03842
03843
03844
03845 cr_parser_try_to_skip_spaces_and_comments (a_this);
03846
03847 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
03848
03849 ENSURE_PARSING_COND (status == CR_OK && token
03850 && token->type == CBO_TK);
03851
03852 cr_token_destroy (token);
03853 token = NULL;
03854
03855
03856
03857
03858 if (PRIVATE (a_this)->sac_handler
03859 && PRIVATE (a_this)->sac_handler->start_page) {
03860 PRIVATE (a_this)->sac_handler->start_page
03861 (PRIVATE (a_this)->sac_handler,
03862 page_selector, page_pseudo_class,
03863 &location);
03864 }
03865 cr_parser_try_to_skip_spaces_and_comments (a_this);
03866
03867 PRIVATE (a_this)->state = TRY_PARSE_PAGE_STATE;
03868
03869 status = cr_parser_parse_declaration (a_this, &property,
03870 &css_expression,
03871 &important);
03872 ENSURE_PARSING_COND (status == CR_OK);
03873
03874
03875
03876
03877 if (PRIVATE (a_this)->sac_handler
03878 && PRIVATE (a_this)->sac_handler->property) {
03879 if (css_expression)
03880 cr_term_ref (css_expression);
03881
03882 PRIVATE (a_this)->sac_handler->property
03883 (PRIVATE (a_this)->sac_handler,
03884 property, css_expression, important);
03885 }
03886
03887
03888
03889
03890 if (property) {
03891 cr_string_destroy (property);
03892 property = NULL;
03893 }
03894 if (css_expression) {
03895 cr_term_unref (css_expression);
03896 css_expression = NULL;
03897 }
03898
03899 for (;;) {
03900
03901 if (token) {
03902 cr_token_destroy (token);
03903 token = NULL;
03904 }
03905 status = cr_tknzr_get_next_token
03906 (PRIVATE (a_this)->tknzr, &token);
03907
03908 ENSURE_PARSING_COND (status == CR_OK && token);
03909
03910 if (token->type != SEMICOLON_TK) {
03911 cr_tknzr_unget_token
03912 (PRIVATE (a_this)->tknzr,
03913 token);
03914 token = NULL ;
03915 break;
03916 }
03917
03918 cr_token_destroy (token);
03919 token = NULL;
03920 cr_parser_try_to_skip_spaces_and_comments (a_this);
03921
03922 status = cr_parser_parse_declaration (a_this, &property,
03923 &css_expression,
03924 &important);
03925 if (status != CR_OK)
03926 break ;
03927
03928
03929
03930
03931 if (PRIVATE (a_this)->sac_handler
03932 && PRIVATE (a_this)->sac_handler->property) {
03933 cr_term_ref (css_expression);
03934 PRIVATE (a_this)->sac_handler->property
03935 (PRIVATE (a_this)->sac_handler,
03936 property, css_expression, important);
03937 }
03938
03939
03940
03941
03942 if (property) {
03943 cr_string_destroy (property);
03944 property = NULL;
03945 }
03946 if (css_expression) {
03947 cr_term_unref (css_expression);
03948 css_expression = NULL;
03949 }
03950 }
03951 cr_parser_try_to_skip_spaces_and_comments
03952 (a_this) ;
03953 if (token) {
03954 cr_token_destroy (token) ;
03955 token = NULL ;
03956 }
03957
03958 status = cr_tknzr_get_next_token
03959 (PRIVATE (a_this)->tknzr, &token);
03960 ENSURE_PARSING_COND (status == CR_OK
03961 && token
03962 && token->type == CBC_TK) ;
03963 cr_token_destroy (token) ;
03964 token = NULL ;
03965
03966
03967
03968 if (PRIVATE (a_this)->sac_handler
03969 && PRIVATE (a_this)->sac_handler->end_page) {
03970 PRIVATE (a_this)->sac_handler->end_page
03971 (PRIVATE (a_this)->sac_handler,
03972 page_selector, page_pseudo_class);
03973 }
03974
03975 if (page_selector) {
03976 cr_string_destroy (page_selector);
03977 page_selector = NULL;
03978 }
03979
03980 if (page_pseudo_class) {
03981 cr_string_destroy (page_pseudo_class);
03982 page_pseudo_class = NULL;
03983 }
03984
03985 cr_parser_try_to_skip_spaces_and_comments (a_this);
03986
03987
03988
03989 cr_parser_clear_errors (a_this);
03990 PRIVATE (a_this)->state = PAGE_PARSED_STATE;
03991
03992 return CR_OK;
03993
03994 error:
03995 if (token) {
03996 cr_token_destroy (token);
03997 token = NULL;
03998 }
03999 if (page_selector) {
04000 cr_string_destroy (page_selector);
04001 page_selector = NULL;
04002 }
04003 if (page_pseudo_class) {
04004 cr_string_destroy (page_pseudo_class);
04005 page_pseudo_class = NULL;
04006 }
04007 if (property) {
04008 cr_string_destroy (property);
04009 property = NULL;
04010 }
04011 if (css_expression) {
04012 cr_term_destroy (css_expression);
04013 css_expression = NULL;
04014 }
04015 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
04016 return status;
04017 }
04018
04019
04020
04021
04022
04023
04024
04025
04026
04027
04028
04029
04030
04031 enum CRStatus
04032 cr_parser_parse_charset (CRParser * a_this, CRString ** a_value,
04033 CRParsingLocation *a_charset_sym_location)
04034 {
04035 enum CRStatus status = CR_OK;
04036 CRInputPos init_pos;
04037 CRToken *token = NULL;
04038 CRString *charset_str = NULL;
04039
04040 g_return_val_if_fail (a_this && a_value
04041 && (*a_value == NULL),
04042 CR_BAD_PARAM_ERROR);
04043
04044 RECORD_INITIAL_POS (a_this, &init_pos);
04045
04046 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
04047
04048 ENSURE_PARSING_COND (status == CR_OK
04049 && token && token->type == CHARSET_SYM_TK);
04050 if (a_charset_sym_location) {
04051 cr_parsing_location_copy (a_charset_sym_location,
04052 &token->location) ;
04053 }
04054 cr_token_destroy (token);
04055 token = NULL;
04056
04057 PRIVATE (a_this)->state = TRY_PARSE_CHARSET_STATE;
04058
04059 cr_parser_try_to_skip_spaces_and_comments (a_this);
04060
04061 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
04062 ENSURE_PARSING_COND (status == CR_OK
04063 && token && token->type == STRING_TK);
04064 charset_str = token->u.str;
04065 token->u.str = NULL;
04066 cr_token_destroy (token);
04067 token = NULL;
04068
04069 cr_parser_try_to_skip_spaces_and_comments (a_this);
04070
04071 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
04072
04073 ENSURE_PARSING_COND (status == CR_OK
04074 && token && token->type == SEMICOLON_TK);
04075 cr_token_destroy (token);
04076 token = NULL;
04077
04078 if (charset_str) {
04079 *a_value = charset_str;
04080 charset_str = NULL;
04081 }
04082
04083 PRIVATE (a_this)->state = CHARSET_PARSED_STATE;
04084 return CR_OK;
04085
04086 error:
04087
04088 if (token) {
04089 cr_token_destroy (token);
04090 token = NULL;
04091 }
04092
04093 if (*a_value) {
04094 cr_string_destroy (*a_value);
04095 *a_value = NULL;
04096 }
04097
04098 if (charset_str) {
04099 cr_string_destroy (charset_str);
04100 charset_str = NULL;
04101 }
04102
04103 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
04104
04105 return status;
04106 }
04107
04108
04109
04110
04111
04112
04113
04114
04115
04116
04117
04118 enum CRStatus
04119 cr_parser_parse_font_face (CRParser * a_this)
04120 {
04121 enum CRStatus status = CR_ERROR;
04122 CRInputPos init_pos;
04123 CRString *property = NULL;
04124 CRTerm *css_expression = NULL;
04125 CRToken *token = NULL;
04126 gboolean important = FALSE;
04127 guint32 next_char = 0,
04128 cur_char = 0;
04129 CRParsingLocation location = {0} ;
04130
04131 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
04132
04133 RECORD_INITIAL_POS (a_this, &init_pos);
04134
04135 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr, &token);
04136 ENSURE_PARSING_COND (status == CR_OK
04137 && token
04138 && token->type == FONT_FACE_SYM_TK);
04139
04140 cr_parser_try_to_skip_spaces_and_comments (a_this);
04141 if (token) {
04142 cr_parsing_location_copy (&location,
04143 &token->location) ;
04144 cr_token_destroy (token);
04145 token = NULL;
04146 }
04147 status = cr_tknzr_get_next_token (PRIVATE (a_this)->tknzr,
04148 &token);
04149 ENSURE_PARSING_COND (status == CR_OK && token
04150 && token->type == CBO_TK);
04151 if (token) {
04152 cr_token_destroy (token);
04153 token = NULL;
04154 }
04155
04156
04157
04158 if (PRIVATE (a_this)->sac_handler
04159 && PRIVATE (a_this)->sac_handler->start_font_face) {
04160 PRIVATE (a_this)->sac_handler->start_font_face
04161 (PRIVATE (a_this)->sac_handler, &location);
04162 }
04163 PRIVATE (a_this)->state = TRY_PARSE_FONT_FACE_STATE;
04164
04165
04166
04167 cr_parser_try_to_skip_spaces_and_comments (a_this);
04168 status = cr_parser_parse_declaration (a_this, &property,
04169 &css_expression, &important);
04170 if (status == CR_OK) {
04171
04172
04173
04174 cr_term_ref (css_expression);
04175 if (PRIVATE (a_this)->sac_handler &&
04176 PRIVATE (a_this)->sac_handler->property) {
04177 PRIVATE (a_this)->sac_handler->property
04178 (PRIVATE (a_this)->sac_handler,
04179 property, css_expression, important);
04180 }
04181 ENSURE_PARSING_COND (css_expression && property);
04182 }
04183
04184 if (property) {
04185 cr_string_destroy (property);
04186 property = NULL;
04187 }
04188 if (css_expression) {
04189 cr_term_unref (css_expression);
04190 css_expression = NULL;
04191 }
04192 for (;;) {
04193 PEEK_NEXT_CHAR (a_this, &next_char);
04194 if (next_char == ';') {
04195 READ_NEXT_CHAR (a_this, &cur_char);
04196 } else {
04197 break;
04198 }
04199 cr_parser_try_to_skip_spaces_and_comments (a_this);
04200 status = cr_parser_parse_declaration (a_this,
04201 &property,
04202 &css_expression,
04203 &important);
04204 if (status != CR_OK)
04205 break;
04206
04207
04208
04209 cr_term_ref (css_expression);
04210 if (PRIVATE (a_this)->sac_handler->property) {
04211 PRIVATE (a_this)->sac_handler->property
04212 (PRIVATE (a_this)->sac_handler,
04213 property, css_expression, important);
04214 }
04215
04216
04217
04218
04219 if (property) {
04220 cr_string_destroy (property);
04221 property = NULL;
04222 }
04223 if (css_expression) {
04224 cr_term_unref (css_expression);
04225 css_expression = NULL;
04226 }
04227 }
04228 cr_parser_try_to_skip_spaces_and_comments (a_this);
04229 READ_NEXT_CHAR (a_this, &cur_char);
04230 ENSURE_PARSING_COND (cur_char == '}');
04231
04232
04233
04234 if (PRIVATE (a_this)->sac_handler->end_font_face) {
04235 PRIVATE (a_this)->sac_handler->end_font_face
04236 (PRIVATE (a_this)->sac_handler);
04237 }
04238 cr_parser_try_to_skip_spaces_and_comments (a_this);
04239
04240 if (token) {
04241 cr_token_destroy (token);
04242 token = NULL;
04243 }
04244 cr_parser_clear_errors (a_this);
04245 PRIVATE (a_this)->state = FONT_FACE_PARSED_STATE;
04246 return CR_OK;
04247
04248 error:
04249 if (token) {
04250 cr_token_destroy (token);
04251 token = NULL;
04252 }
04253 if (property) {
04254 cr_string_destroy (property);
04255 property = NULL;
04256 }
04257 if (css_expression) {
04258 cr_term_destroy (css_expression);
04259 css_expression = NULL;
04260 }
04261 cr_tknzr_set_cur_pos (PRIVATE (a_this)->tknzr, &init_pos);
04262 return status;
04263 }
04264
04265
04266
04267
04268
04269
04270
04271
04272 enum CRStatus
04273 cr_parser_parse (CRParser * a_this)
04274 {
04275 enum CRStatus status = CR_ERROR;
04276
04277 g_return_val_if_fail (a_this && PRIVATE (a_this)
04278 && PRIVATE (a_this)->tknzr, CR_BAD_PARAM_ERROR);
04279
04280 if (PRIVATE (a_this)->use_core_grammar == FALSE) {
04281 status = cr_parser_parse_stylesheet (a_this);
04282 } else {
04283 status = cr_parser_parse_stylesheet_core (a_this);
04284 }
04285
04286 return status;
04287 }
04288
04289 enum CRStatus
04290 cr_parser_set_tknzr (CRParser * a_this, CRTknzr * a_tknzr)
04291 {
04292 g_return_val_if_fail (a_this && PRIVATE (a_this), CR_BAD_PARAM_ERROR);
04293
04294 if (PRIVATE (a_this)->tknzr) {
04295 cr_tknzr_unref (PRIVATE (a_this)->tknzr);
04296 }
04297
04298 PRIVATE (a_this)->tknzr = a_tknzr;
04299
04300 if (a_tknzr)
04301 cr_tknzr_ref (a_tknzr);
04302
04303 return CR_OK;
04304 }
04305
04306
04307
04308
04309
04310
04311
04312
04313 enum CRStatus
04314 cr_parser_get_tknzr (CRParser * a_this, CRTknzr ** a_tknzr)
04315 {
04316 g_return_val_if_fail (a_this && PRIVATE (a_this)
04317 && a_tknzr, CR_BAD_PARAM_ERROR);
04318
04319 *a_tknzr = PRIVATE (a_this)->tknzr;
04320 return CR_OK;
04321 }
04322
04323
04324
04325
04326
04327
04328
04329
04330 enum CRStatus
04331 cr_parser_get_parsing_location (CRParser *a_this,
04332 CRParsingLocation *a_loc)
04333 {
04334 g_return_val_if_fail (a_this
04335 && PRIVATE (a_this)
04336 && a_loc, CR_BAD_PARAM_ERROR) ;
04337
04338 return cr_tknzr_get_parsing_location
04339 (PRIVATE (a_this)->tknzr, a_loc) ;
04340 }
04341
04342
04343
04344
04345
04346
04347
04348
04349
04350 enum CRStatus
04351 cr_parser_parse_buf (CRParser * a_this,
04352 const guchar * a_buf,
04353 gulong a_len, enum CREncoding a_enc)
04354 {
04355 enum CRStatus status = CR_ERROR;
04356 CRTknzr *tknzr = NULL;
04357
04358 g_return_val_if_fail (a_this && PRIVATE (a_this)
04359 && a_buf, CR_BAD_PARAM_ERROR);
04360
04361 tknzr = cr_tknzr_new_from_buf ((guchar*)a_buf, a_len, a_enc, FALSE);
04362
04363 g_return_val_if_fail (tknzr != NULL, CR_ERROR);
04364
04365 status = cr_parser_set_tknzr (a_this, tknzr);
04366 g_return_val_if_fail (status == CR_OK, CR_ERROR);
04367
04368 status = cr_parser_parse (a_this);
04369
04370 return status;
04371 }
04372
04373
04374
04375
04376
04377
04378
04379 void
04380 cr_parser_destroy (CRParser * a_this)
04381 {
04382 g_return_if_fail (a_this && PRIVATE (a_this));
04383
04384 if (PRIVATE (a_this)->tknzr) {
04385 if (cr_tknzr_unref (PRIVATE (a_this)->tknzr) == TRUE)
04386 PRIVATE (a_this)->tknzr = NULL;
04387 }
04388
04389 if (PRIVATE (a_this)->sac_handler) {
04390 cr_doc_handler_unref (PRIVATE (a_this)->sac_handler);
04391 PRIVATE (a_this)->sac_handler = NULL;
04392 }
04393
04394 if (PRIVATE (a_this)->err_stack) {
04395 cr_parser_clear_errors (a_this);
04396 PRIVATE (a_this)->err_stack = NULL;
04397 }
04398
04399 if (PRIVATE (a_this)) {
04400 g_free (PRIVATE (a_this));
04401 PRIVATE (a_this) = NULL;
04402 }
04403
04404 if (a_this) {
04405 g_free (a_this);
04406 a_this = NULL;
04407 }
04408 }