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