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