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