habaki 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +3 -0
  3. data/ext/katana/extconf.rb +20 -0
  4. data/ext/katana/rb_katana.c +280 -0
  5. data/ext/katana/rb_katana.h +102 -0
  6. data/ext/katana/rb_katana_array.c +144 -0
  7. data/ext/katana/rb_katana_declaration.c +389 -0
  8. data/ext/katana/rb_katana_rule.c +461 -0
  9. data/ext/katana/rb_katana_selector.c +559 -0
  10. data/ext/katana/src/foundation.c +237 -0
  11. data/ext/katana/src/foundation.h +120 -0
  12. data/ext/katana/src/katana.h +590 -0
  13. data/ext/katana/src/katana.lex.c +4104 -0
  14. data/ext/katana/src/katana.lex.h +592 -0
  15. data/ext/katana/src/katana.tab.c +4422 -0
  16. data/ext/katana/src/katana.tab.h +262 -0
  17. data/ext/katana/src/parser.c +1563 -0
  18. data/ext/katana/src/parser.h +237 -0
  19. data/ext/katana/src/selector.c +659 -0
  20. data/ext/katana/src/selector.h +54 -0
  21. data/ext/katana/src/tokenizer.c +300 -0
  22. data/ext/katana/src/tokenizer.h +41 -0
  23. data/lib/habaki/charset_rule.rb +25 -0
  24. data/lib/habaki/declaration.rb +53 -0
  25. data/lib/habaki/declarations.rb +346 -0
  26. data/lib/habaki/error.rb +43 -0
  27. data/lib/habaki/font_face_rule.rb +24 -0
  28. data/lib/habaki/formal_syntax.rb +464 -0
  29. data/lib/habaki/formatter.rb +99 -0
  30. data/lib/habaki/import_rule.rb +34 -0
  31. data/lib/habaki/media_rule.rb +173 -0
  32. data/lib/habaki/namespace_rule.rb +31 -0
  33. data/lib/habaki/node.rb +52 -0
  34. data/lib/habaki/page_rule.rb +24 -0
  35. data/lib/habaki/qualified_name.rb +29 -0
  36. data/lib/habaki/rule.rb +48 -0
  37. data/lib/habaki/rules.rb +225 -0
  38. data/lib/habaki/selector.rb +98 -0
  39. data/lib/habaki/selectors.rb +49 -0
  40. data/lib/habaki/style_rule.rb +35 -0
  41. data/lib/habaki/stylesheet.rb +158 -0
  42. data/lib/habaki/sub_selector.rb +234 -0
  43. data/lib/habaki/sub_selectors.rb +42 -0
  44. data/lib/habaki/supports_rule.rb +65 -0
  45. data/lib/habaki/value.rb +321 -0
  46. data/lib/habaki/values.rb +86 -0
  47. data/lib/habaki/visitor/element.rb +50 -0
  48. data/lib/habaki/visitor/media.rb +22 -0
  49. data/lib/habaki/visitor/nokogiri_element.rb +56 -0
  50. data/lib/habaki.rb +39 -0
  51. metadata +190 -0
@@ -0,0 +1,1563 @@
1
+ /**
2
+ * Copyright (c) 2015 QFish <im@qfi.sh>
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ * THE SOFTWARE.
21
+ */
22
+
23
+ #include <assert.h>
24
+ #include <ctype.h>
25
+ #include <stdarg.h>
26
+ #include <stdlib.h>
27
+ #include <string.h>
28
+ #include <strings.h>
29
+
30
+ #include "katana.h"
31
+ #include "selector.h"
32
+ #include "katana.tab.h"
33
+ #include "parser.h"
34
+ #include "tokenizer.h"
35
+
36
+ #include "foundation.h"
37
+
38
+ //#undef assert
39
+ //#define assert(x)
40
+
41
+ #define breakpoint
42
+ #define KATANA_PARSER_STRING(literal) { literal, sizeof(literal) - 1 }
43
+
44
+
45
+ typedef void (*KatanaArrayDeallocator)(KatanaParser* parser, void* e);
46
+
47
+ #undef katana_destroy_array
48
+ #define katana_destroy_array(parser, callback, e) \
49
+ katana_destroy_array_using_deallocator((parser), \
50
+ (KatanaArrayDeallocator)(&(callback)), (e))
51
+
52
+
53
+ void katana_destroy_stylesheet(KatanaParser* parser, KatanaStylesheet* e);
54
+ void katana_destroy_rule(KatanaParser* parser, KatanaRule* e);
55
+ void katana_destroy_font_face_rule(KatanaParser* parser, KatanaFontFaceRule* e);
56
+ void katana_destroy_import_rule(KatanaParser* parser, KatanaImportRule* e);
57
+ void katana_destroy_media_rule(KatanaParser* parser, KatanaMediaRule* e);
58
+ void katana_destroy_namespace_rule(KatanaParser* parser, KatanaNamespaceRule* e);
59
+ void katana_destroy_supports_rule(KatanaParser* parser, KatanaSupportsRule* e);
60
+ void katana_destroy_page_rule(KatanaParser* parser, KatanaPageRule* e);
61
+ void katana_destroy_media_query(KatanaParser* parser, KatanaMediaQuery* e);
62
+ void katana_destroy_media_query_exp(KatanaParser* parser, KatanaMediaQueryExp* e);
63
+ void katana_destroy_keyframes_rule(KatanaParser* parser, KatanaKeyframesRule* e);
64
+ void katana_destroy_keyframe(KatanaParser* parser, KatanaKeyframe* e);
65
+ void katana_destroy_media_list(KatanaParser* parser, KatanaArray* e);
66
+ void katana_destroy_rule_list(KatanaParser* parser, KatanaArray* e);
67
+ void katana_destroy_style_rule(KatanaParser* parser, KatanaStyleRule* e);
68
+ void katana_destroy_qualified_name(KatanaParser* parser, KatanaQualifiedName* e);
69
+ void katana_destroy_selector(KatanaParser* parser, KatanaSelector* e);
70
+ void katana_destroy_rare_data(KatanaParser* parser, KatanaSelectorRareData* e);
71
+ void katana_destroy_declaration(KatanaParser* parser, KatanaDeclaration* e);
72
+ void katana_destroy_value(KatanaParser* parser, KatanaValue* e);
73
+ void katana_destroy_function(KatanaParser* parser, KatanaValueFunction* e);
74
+
75
+ void katana_destroy_array_using_deallocator(KatanaParser* parser,
76
+ KatanaArrayDeallocator deallocator, KatanaArray* array);
77
+
78
+
79
+
80
+ extern int katanaparse(void* scanner, struct KatanaInternalParser * parser);
81
+
82
+ static KatanaOutput* katana_parse_with_options(const KatanaOptions* options,
83
+ yyconst char* bytes,
84
+ size_t len,
85
+ KatanaParserMode mode);
86
+
87
+ static KatanaOutput* katana_parse_fragment(const char* prefix,
88
+ size_t pre_len,
89
+ const char* string,
90
+ size_t str_len,
91
+ KatanaParserMode mode);
92
+
93
+ static const char* katana_stringify_value_list(KatanaParser* parser, KatanaArray* value_list);
94
+ static const char* katana_stringify_value(KatanaParser* parser, KatanaValue* value);
95
+
96
+ static void* malloc_wrapper(void* unused, size_t size) {
97
+ return malloc(size);
98
+ }
99
+
100
+ static void free_wrapper(void* unused, void* ptr) {
101
+ free(ptr);
102
+ }
103
+
104
+ const KatanaOptions kKatanaDefaultOptions = {
105
+ &malloc_wrapper,
106
+ &free_wrapper,
107
+ NULL
108
+ };
109
+
110
+ static void output_init(KatanaParser* parser, KatanaParserMode mode)
111
+ {
112
+ KatanaOutput* output = katana_parser_allocate(parser, sizeof(KatanaOutput));
113
+ output->stylesheet = katana_new_stylesheet(parser);
114
+ output->declarations = NULL;
115
+ output->selectors = NULL;
116
+ output->mode = mode;
117
+ katana_array_init(parser, 0, &output->errors);
118
+ parser->output = output;
119
+ }
120
+
121
+ static void set_position(KatanaParser* parser, KatanaSourcePosition *position)
122
+ {
123
+ yyscan_t *scanner = *parser->scanner;
124
+ position->line = katanaget_lineno(scanner);
125
+ position->column = katanaget_column(scanner);
126
+ }
127
+
128
+ void katana_destroy_output(KatanaOutput* output)
129
+ {
130
+ if ( NULL == output )
131
+ return;
132
+
133
+ KatanaParser parser;
134
+ parser.options = &kKatanaDefaultOptions;
135
+ switch (output->mode) {
136
+ case KatanaParserModeStylesheet:
137
+ break;
138
+ case KatanaParserModeRule:
139
+ if ( NULL != output->rule ) {
140
+ katana_destroy_rule(&parser, output->rule);
141
+ }
142
+ break;
143
+ case KatanaParserModeKeyframeRule:
144
+ if ( NULL != output->keyframe ) {
145
+ katana_destroy_keyframe(&parser, output->keyframe);
146
+ }
147
+ break;
148
+ case KatanaParserModeKeyframeKeyList:
149
+ if ( NULL != output->keyframe_keys ) {
150
+ katana_destroy_array(&parser, katana_destroy_value, output->keyframe_keys);
151
+ katana_parser_deallocate(&parser, (void*) output->keyframe_keys);
152
+ output->keyframe_keys = NULL;
153
+ }
154
+ break;
155
+ case KatanaParserModeMediaList:
156
+ if ( NULL != output->medias ) {
157
+ katana_destroy_media_list(&parser, output->medias);
158
+ }
159
+ break;
160
+ case KatanaParserModeValue:
161
+ if ( NULL != output->values ) {
162
+ katana_destroy_array(&parser, katana_destroy_value, output->values);
163
+ katana_parser_deallocate(&parser, (void*) output->values);
164
+ output->values = NULL;
165
+ }
166
+ break;
167
+ case KatanaParserModeSelector:
168
+ if ( NULL != output->selectors ) {
169
+ katana_destroy_array(&parser, katana_destroy_selector, output->selectors);
170
+ katana_parser_deallocate(&parser, (void*) output->selectors);
171
+ output->selectors = NULL;
172
+ }
173
+ break;
174
+ case KatanaParserModeDeclarationList:
175
+ if ( NULL != output->declarations ) {
176
+ katana_destroy_array(&parser, katana_destroy_declaration, output->declarations);
177
+ katana_parser_deallocate(&parser, (void*) output->declarations);
178
+ output->declarations = NULL;
179
+ }
180
+ break;
181
+ }
182
+ katana_destroy_stylesheet(&parser, output->stylesheet);
183
+ katana_array_destroy(&parser, &output->errors);
184
+ katana_parser_deallocate(&parser, output);
185
+ }
186
+
187
+
188
+ static const KatanaParserString kKatanaParserModePrefixs[] = {
189
+ KATANA_PARSER_STRING(""),
190
+ KATANA_PARSER_STRING("@-internal-rule "), // 16
191
+ KATANA_PARSER_STRING("@-internal-keyframe-rule "), // 25
192
+ KATANA_PARSER_STRING("@-internal-keyframe-key-list "), // 29
193
+ KATANA_PARSER_STRING("@-internal-media-list "), // 22
194
+ KATANA_PARSER_STRING("@-internal-value "), // 17
195
+ KATANA_PARSER_STRING("@-internal-selector "), // 20
196
+ KATANA_PARSER_STRING("@-internal-decls "), // 17
197
+ };
198
+
199
+ KatanaOutput* katana_parse(const char* str, size_t len, KatanaParserMode mode)
200
+ {
201
+ switch (mode) {
202
+ case KatanaParserModeStylesheet:
203
+ return katana_parse_with_options(&kKatanaDefaultOptions, (yyconst char*)str, len, mode);
204
+ case KatanaParserModeRule:
205
+ case KatanaParserModeKeyframeRule:
206
+ case KatanaParserModeKeyframeKeyList:
207
+ case KatanaParserModeMediaList:
208
+ case KatanaParserModeValue:
209
+ case KatanaParserModeSelector:
210
+ case KatanaParserModeDeclarationList: {
211
+ KatanaParserString prefix = kKatanaParserModePrefixs[mode];
212
+ return katana_parse_fragment(prefix.data, prefix.length, str, len, mode);
213
+ }
214
+ default:
215
+ katana_print("Whoops, not support yet!");
216
+ return NULL;
217
+ }
218
+ }
219
+
220
+ KatanaOutput* katana_parse_in(FILE* fp)
221
+ {
222
+ assert(NULL != fp);
223
+ if ( NULL == fp )
224
+ return NULL;
225
+
226
+ yyscan_t scanner;
227
+ if (katanalex_init(&scanner)) {
228
+ katana_print("no scanning today!");
229
+ return NULL;
230
+ }
231
+
232
+ katanaset_in(fp, scanner);
233
+
234
+ KatanaParser parser;
235
+ parser.options = &kKatanaDefaultOptions;
236
+ parser.scanner = &scanner;
237
+ parser.default_namespace = kKatanaAsteriskString;
238
+ parser.parsed_declarations = katana_new_array(&parser);
239
+ #if KATANA_PARSER_DEBUG
240
+ parser.parsed_selectors = katana_new_array(&parser);
241
+ #endif // #if KATANA_PARSER_DEBUG
242
+ parser.position = katana_parser_allocate(&parser, sizeof(KatanaSourcePosition));
243
+ output_init(&parser, KatanaParserModeStylesheet);
244
+ katanaparse(scanner, &parser);
245
+ katanalex_destroy(scanner);
246
+ katana_parser_clear_declarations(&parser);
247
+ katana_parser_deallocate(&parser, parser.position);
248
+ #if KATANA_PARSER_DEBUG
249
+ katana_destroy_array(&parser, katana_destroy_selector, parser.parsed_selectors);
250
+ katana_parser_deallocate(&parser, parser.parsed_selectors);
251
+ #endif // #if KATANA_PARSER_DEBUG
252
+ parser.scanner = NULL;
253
+ KatanaOutput* output = parser.output;
254
+ return output;
255
+ }
256
+
257
+
258
+ static KatanaOutput* katana_parse_fragment(const char* prefix,
259
+ size_t pre_len,
260
+ const char* str,
261
+ size_t str_len,
262
+ KatanaParserMode mode) {
263
+ size_t len = pre_len + str_len + 1;
264
+ char * source = malloc_wrapper(NULL, len);
265
+ if ( source == NULL )
266
+ return NULL;
267
+ memcpy(source, prefix, pre_len);
268
+ memcpy(source+pre_len, str, str_len);
269
+ source[pre_len + str_len] = '\0';
270
+ KatanaOutput * output = katana_parse_with_options(&kKatanaDefaultOptions, (void*)source, len, mode);
271
+ free_wrapper(NULL, source);
272
+ return output;
273
+ }
274
+
275
+ static KatanaOutput* katana_parse_with_options(const KatanaOptions* options,
276
+ yyconst char* bytes,
277
+ size_t len,
278
+ KatanaParserMode mode) {
279
+ assert(NULL != bytes);
280
+ if ( NULL == bytes )
281
+ return NULL;
282
+
283
+ yyscan_t scanner;
284
+ if (katanalex_init(&scanner)) {
285
+ katana_print("no scanning today!");
286
+ return NULL;
287
+ }
288
+
289
+ katana_scan_bytes(bytes, len, scanner);
290
+
291
+ KatanaParser parser;
292
+ parser.options = options;
293
+ parser.scanner = &scanner;
294
+ parser.default_namespace = kKatanaAsteriskString;
295
+ parser.parsed_declarations = katana_new_array(&parser);
296
+ #if KATANA_PARSER_DEBUG
297
+ parser.parsed_selectors = katana_new_array(&parser);
298
+ #endif // #if KATANA_PARSER_DEBUG
299
+ parser.position = katana_parser_allocate(&parser, sizeof(KatanaSourcePosition));
300
+ output_init(&parser, mode);
301
+ katanaparse(scanner, &parser);
302
+ katanalex_destroy(scanner);
303
+ if ( KatanaParserModeDeclarationList != mode ) {
304
+ katana_parser_clear_declarations(&parser);
305
+ }
306
+ katana_parser_deallocate(&parser, parser.position);
307
+ #if KATANA_PARSER_DEBUG
308
+ katana_destroy_array(&parser, katana_destroy_selector, parser.parsed_selectors);
309
+ katana_parser_deallocate(&parser, parser.parsed_selectors);
310
+ #endif // #if KATANA_PARSER_DEBUG
311
+ parser.scanner = NULL;
312
+ KatanaOutput* output = parser.output;
313
+ return output;
314
+ }
315
+
316
+
317
+ void katana_parse_internal_rule(KatanaParser* parser, KatanaRule* e)
318
+ {
319
+ parser->output->rule = e;
320
+ }
321
+
322
+ void katana_parse_internal_keyframe_rule(KatanaParser* parser, KatanaKeyframe* e)
323
+ {
324
+ parser->output->keyframe = e;
325
+ }
326
+
327
+ void katana_parse_internal_keyframe_key_list(KatanaParser* parser, KatanaArray* e)
328
+ {
329
+ parser->output->keyframe_keys = e;
330
+ }
331
+
332
+ void katana_parse_internal_value(KatanaParser* parser, KatanaArray* e)
333
+ {
334
+ parser->output->values = e;
335
+ }
336
+
337
+ void katana_parse_internal_media_list(KatanaParser* parser, KatanaArray* e)
338
+ {
339
+ parser->output->medias = e;
340
+ }
341
+
342
+ void katana_parse_internal_supports_list(KatanaParser* parser, KatanaArray* e)
343
+ {
344
+ parser->output->supports = e;
345
+ }
346
+
347
+ void katana_parse_internal_declaration_list(KatanaParser* parser, bool e)
348
+ {
349
+ parser->output->declarations = parser->parsed_declarations;
350
+ }
351
+
352
+ void katana_parse_internal_selector(KatanaParser* parser, KatanaArray* e)
353
+ {
354
+ parser->output->selectors = e;
355
+ }
356
+
357
+
358
+ KatanaArray* katana_new_array(KatanaParser* parser) {
359
+ KatanaArray* array = katana_parser_allocate(parser, sizeof(KatanaArray));
360
+ katana_array_init(parser, 0, array);
361
+ return array;
362
+ }
363
+
364
+ void katana_destroy_array_using_deallocator(KatanaParser* parser,
365
+ KatanaArrayDeallocator callback, KatanaArray* array) {
366
+ //assert(NULL != array);
367
+ if ( NULL == array )
368
+ return;
369
+ for (size_t i = 0; i < array->length; ++i) {
370
+ callback(parser, array->data[i]);
371
+ }
372
+ katana_array_destroy(parser, array);
373
+ }
374
+
375
+
376
+ KatanaStylesheet* katana_new_stylesheet(KatanaParser* parser) {
377
+ KatanaStylesheet* stylesheet =
378
+ katana_parser_allocate(parser, sizeof(KatanaStylesheet));
379
+ stylesheet->encoding = NULL;
380
+ katana_array_init(parser, 0, &stylesheet->rules);
381
+ katana_array_init(parser, 0, &stylesheet->imports);
382
+ return stylesheet;
383
+ }
384
+
385
+ void katana_destroy_stylesheet(KatanaParser* parser, KatanaStylesheet* e)
386
+ {
387
+ assert(NULL != e);
388
+ if ( NULL == e )
389
+ return;
390
+
391
+ // free encoding
392
+ if ( e->encoding )
393
+ katana_parser_deallocate(parser, (void*) e->encoding);
394
+
395
+ // free imports
396
+ for (size_t i = 0; i < e->imports.length; ++i) {
397
+ katana_destroy_import_rule(parser, e->imports.data[i]);
398
+ }
399
+ katana_parser_deallocate(parser, (void*) e->imports.data);
400
+
401
+ // free rules
402
+ for (size_t i = 0; i < e->rules.length; ++i) {
403
+ katana_destroy_rule(parser, e->rules.data[i]);
404
+ }
405
+ katana_parser_deallocate(parser, (void*) e->rules.data);
406
+
407
+ // free e
408
+ katana_parser_deallocate(parser, (void*) e);
409
+ }
410
+
411
+ void katana_destroy_rule(KatanaParser* parser, KatanaRule* rule)
412
+ {
413
+ switch (rule->type) {
414
+ case KatanaRuleStyle:
415
+ katana_destroy_style_rule(parser, (KatanaStyleRule*)rule);
416
+ break;
417
+ case KatanaRuleImport:
418
+ katana_destroy_import_rule(parser, (KatanaImportRule*)rule);
419
+ break;
420
+ case KatanaRuleFontFace:
421
+ katana_destroy_font_face_rule(parser, (KatanaFontFaceRule*)rule);
422
+ break;
423
+ case KatanaRuleKeyframes:
424
+ katana_destroy_keyframes_rule(parser, (KatanaKeyframesRule*)rule);
425
+ break;
426
+ case KatanaRuleMedia:
427
+ katana_destroy_media_rule(parser, (KatanaMediaRule*)rule);
428
+ break;
429
+ case KatanaRuleNamespace:
430
+ katana_destroy_namespace_rule(parser, (KatanaNamespaceRule*) rule);
431
+ break;
432
+ case KatanaRuleSupports:
433
+ katana_destroy_supports_rule(parser, (KatanaSupportsRule*) rule);
434
+ break;
435
+ case KatanaRulePage:
436
+ katana_destroy_page_rule(parser, (KatanaPageRule*)rule);
437
+ break;
438
+ default:
439
+ break;
440
+ }
441
+ }
442
+
443
+ void katana_destroy_rule_list(KatanaParser* parser, KatanaArray* rules)
444
+ {
445
+ katana_destroy_array(parser, katana_destroy_rule, rules);
446
+ katana_parser_deallocate(parser, (void*) rules);
447
+ }
448
+
449
+
450
+ KatanaRule* katana_new_style_rule(KatanaParser* parser, KatanaArray* selectors)
451
+ {
452
+ assert(NULL != selectors);
453
+ if ( NULL == selectors )
454
+ return NULL;
455
+
456
+ KatanaStyleRule* rule = katana_parser_allocate(parser, sizeof(KatanaStyleRule));
457
+ rule->base.name = "style";
458
+ rule->base.type = KatanaRuleStyle;
459
+ rule->selectors = selectors;
460
+ // Do not check parser->parsed_declarations, when we encounter something like `selectors {}`, treat it as valid.
461
+ rule->declarations = parser->parsed_declarations;
462
+ katana_parser_reset_declarations(parser);
463
+
464
+ return (KatanaRule*)rule;
465
+ }
466
+
467
+ void katana_destroy_style_rule(KatanaParser* parser, KatanaStyleRule* e)
468
+ {
469
+ assert(e->selectors->length);
470
+
471
+ katana_destroy_array(parser, katana_destroy_selector, e->selectors);
472
+ katana_parser_deallocate(parser, (void*) e->selectors);
473
+
474
+ katana_destroy_array(parser, katana_destroy_declaration, e->declarations);
475
+ katana_parser_deallocate(parser, (void*) e->declarations);
476
+
477
+ // katana_parser_deallocate(parser, (void*) e->base.name);
478
+ katana_parser_deallocate(parser, (void*) e);
479
+ }
480
+
481
+
482
+ KatanaRule* katana_new_namespace_rule(KatanaParser* parser, KatanaParserString* prefix, KatanaParserString* uri)
483
+ {
484
+ KatanaNamespaceRule* rule = katana_parser_allocate(parser, sizeof(KatanaNamespaceRule));
485
+
486
+ rule->base.name = "namespace";
487
+ rule->base.type = KatanaRuleNamespace;
488
+
489
+ rule->prefix = prefix == NULL ? NULL : katana_string_to_characters(parser, prefix);
490
+ rule->uri = uri == NULL ? NULL : katana_string_to_characters(parser, uri);
491
+
492
+ katana_parser_reset_declarations(parser);
493
+
494
+ return (KatanaRule*)rule;
495
+ }
496
+
497
+ void katana_destroy_namespace_rule(KatanaParser* parser, KatanaNamespaceRule* e)
498
+ {
499
+ katana_parser_deallocate(parser, (void*) e->prefix);
500
+ katana_parser_deallocate(parser, (void*) e->uri);
501
+ katana_parser_deallocate(parser, (void*) e);
502
+ }
503
+
504
+ KatanaRule* katana_new_page_rule(KatanaParser* parser)
505
+ {
506
+ KatanaPageRule* rule = katana_parser_allocate(parser, sizeof(KatanaPageRule));
507
+ rule->base.name = "page";
508
+ rule->base.type = KatanaRulePage;
509
+ rule->declarations = parser->parsed_declarations;
510
+
511
+ katana_parser_reset_declarations(parser);
512
+
513
+ return (KatanaRule*)rule;
514
+ }
515
+
516
+ void katana_destroy_page_rule(KatanaParser* parser, KatanaPageRule* e)
517
+ {
518
+ katana_destroy_array(parser, katana_destroy_declaration, e->declarations);
519
+ katana_parser_deallocate(parser, (void*) e->declarations);
520
+ // katana_parser_deallocate(parser, (void*) e->base.name);
521
+ katana_parser_deallocate(parser, (void*) e);
522
+ }
523
+
524
+ KatanaRule* katana_new_font_face(KatanaParser* parser)
525
+ {
526
+ KatanaFontFaceRule* rule = katana_parser_allocate(parser, sizeof(KatanaFontFaceRule));
527
+ rule->base.name = "font-face";
528
+ rule->base.type = KatanaRuleFontFace;
529
+ rule->declarations = parser->parsed_declarations;
530
+
531
+ katana_parser_reset_declarations(parser);
532
+
533
+ return (KatanaRule*)rule;
534
+ }
535
+
536
+ void katana_destroy_font_face_rule(KatanaParser* parser, KatanaFontFaceRule* e)
537
+ {
538
+ katana_destroy_array(parser, katana_destroy_declaration, e->declarations);
539
+ katana_parser_deallocate(parser, (void*) e->declarations);
540
+ // katana_parser_deallocate(parser, (void*) e->base.name);
541
+ katana_parser_deallocate(parser, (void*) e);
542
+ }
543
+
544
+
545
+ KatanaRule* katana_new_keyframes_rule(KatanaParser* parser, KatanaParserString* name, KatanaArray* keyframes, bool isPrefixed)
546
+ {
547
+ KatanaKeyframesRule * rule = katana_parser_allocate(parser, sizeof(KatanaKeyframesRule));
548
+ rule->base.name = "keyframes";
549
+ rule->base.type = KatanaRuleKeyframes;
550
+ rule->name = katana_string_to_characters(parser, name);
551
+ rule->keyframes = keyframes;
552
+ return (KatanaRule*)rule;
553
+ }
554
+
555
+ void katana_destroy_keyframes_rule(KatanaParser* parser, KatanaKeyframesRule * e)
556
+ {
557
+ katana_parser_clear_keyframes(parser, e->keyframes);
558
+ katana_parser_deallocate(parser, (void*) e->name);
559
+ katana_parser_deallocate(parser, (void*) e);
560
+ }
561
+
562
+ KatanaKeyframe* katana_new_keyframe(KatanaParser* parser, KatanaArray* selectors)
563
+ {
564
+ KatanaKeyframe* keyframe = katana_parser_allocate(parser, sizeof(KatanaKeyframe));
565
+ keyframe->selectors = selectors;
566
+ keyframe->declarations = parser->parsed_declarations;
567
+ katana_parser_reset_declarations(parser);
568
+ return keyframe;
569
+ }
570
+
571
+ void katana_destroy_keyframe(KatanaParser* parser, KatanaKeyframe* e)
572
+ {
573
+ katana_destroy_array(parser, katana_destroy_value, e->selectors);
574
+ katana_parser_deallocate(parser, (void*) e->selectors);
575
+
576
+ katana_destroy_array(parser, katana_destroy_declaration, e->declarations);
577
+ katana_parser_deallocate(parser, (void*) e->declarations);
578
+
579
+ katana_parser_deallocate(parser, (void*) e);
580
+ }
581
+
582
+ KatanaArray* katana_new_Keyframe_list(KatanaParser* parser)
583
+ {
584
+ return katana_new_array(parser);
585
+ }
586
+
587
+ void katana_keyframe_rule_list_add(KatanaParser* parser, KatanaKeyframe* keyframe, KatanaArray* list)
588
+ {
589
+ assert(keyframe);
590
+ katana_array_add(parser, keyframe, list);
591
+ }
592
+
593
+ void katana_parser_clear_keyframes(KatanaParser* parser, KatanaArray* keyframes)
594
+ {
595
+ katana_destroy_array(parser, katana_destroy_keyframe, keyframes);
596
+ katana_parser_deallocate(parser, (void*) keyframes);
597
+ }
598
+
599
+
600
+ void katana_set_charset(KatanaParser* parser, KatanaParserString* encoding)
601
+ {
602
+ KatanaCharsetRule* rule = katana_parser_allocate(parser, sizeof(KatanaCharsetRule));
603
+ rule->base.name = "charset";
604
+ rule->base.type = KatanaRuleCharset;
605
+ rule->encoding = katana_string_to_characters(parser, encoding);
606
+ katana_add_rule(parser, (KatanaRule*)rule);
607
+ }
608
+
609
+
610
+ KatanaRule* katana_new_import_rule(KatanaParser* parser, KatanaParserString* href, KatanaArray* media)
611
+ {
612
+ KatanaImportRule* rule = katana_parser_allocate(parser, sizeof(KatanaImportRule));
613
+ rule->base.name = "import";
614
+ rule->base.type = KatanaRuleImport;
615
+ rule->href = katana_string_to_characters(parser, href);
616
+ rule->medias = media;
617
+ return (KatanaRule*)rule;
618
+ }
619
+
620
+ void katana_destroy_import_rule(KatanaParser* parser, KatanaImportRule* e)
621
+ {
622
+ katana_destroy_array(parser, katana_destroy_media_query, e->medias);
623
+ katana_parser_deallocate(parser, (void*) e->medias);
624
+ // katana_parser_deallocate(parser, (void*) e->base.name);
625
+ katana_parser_deallocate(parser, (void*) e->href);
626
+ katana_parser_deallocate(parser, (void*) e);
627
+ }
628
+
629
+
630
+ KatanaValue* katana_new_value(KatanaParser* parser)
631
+ {
632
+ KatanaValue *val = katana_parser_allocate(parser, sizeof(KatanaValue));
633
+ val->iValue = 0;
634
+ val->fValue = 0.0;
635
+ val->string = NULL;
636
+ val->raw = NULL;
637
+ return val;
638
+ }
639
+
640
+ void katana_destroy_value(KatanaParser* parser, KatanaValue* e)
641
+ {
642
+ switch (e->unit) {
643
+ case KATANA_VALUE_URI:
644
+ case KATANA_VALUE_IDENT:
645
+ case KATANA_VALUE_STRING:
646
+ case KATANA_VALUE_DIMENSION:
647
+ case KATANA_VALUE_UNICODE_RANGE:
648
+ case KATANA_VALUE_PARSER_HEXCOLOR:
649
+ {
650
+ katana_parser_deallocate(parser, (void*) e->string);
651
+ }
652
+ break;
653
+ case KATANA_VALUE_PARSER_LIST:
654
+ {
655
+ katana_destroy_array(parser, katana_destroy_value, e->list);
656
+ katana_parser_deallocate(parser, (void*) e->list);
657
+ }
658
+ break;
659
+ case KATANA_VALUE_PARSER_FUNCTION:
660
+ {
661
+ katana_destroy_function(parser, e->function);
662
+ }
663
+ break;
664
+ case KATANA_VALUE_NUMBER:
665
+ case KATANA_VALUE_PERCENTAGE:
666
+ case KATANA_VALUE_PX:
667
+ case KATANA_VALUE_CM:
668
+ case KATANA_VALUE_MM:
669
+ case KATANA_VALUE_IN:
670
+ case KATANA_VALUE_PT:
671
+ case KATANA_VALUE_PC:
672
+ case KATANA_VALUE_DEG:
673
+ case KATANA_VALUE_RAD:
674
+ case KATANA_VALUE_GRAD:
675
+ case KATANA_VALUE_TURN:
676
+ case KATANA_VALUE_MS:
677
+ case KATANA_VALUE_S:
678
+ case KATANA_VALUE_HZ:
679
+ case KATANA_VALUE_KHZ:
680
+ case KATANA_VALUE_EMS:
681
+ case KATANA_VALUE_PARSER_Q_EMS:
682
+ case KATANA_VALUE_EXS:
683
+ case KATANA_VALUE_REMS:
684
+ case KATANA_VALUE_CHS:
685
+ case KATANA_VALUE_VW:
686
+ case KATANA_VALUE_VH:
687
+ case KATANA_VALUE_VMIN:
688
+ case KATANA_VALUE_VMAX:
689
+ case KATANA_VALUE_DPPX:
690
+ case KATANA_VALUE_DPI:
691
+ case KATANA_VALUE_DPCM:
692
+ case KATANA_VALUE_FR:
693
+ katana_parser_deallocate(parser, (void*) e->raw);
694
+ break;
695
+ default:
696
+ break;
697
+ }
698
+
699
+ katana_parser_deallocate(parser, (void*) e);
700
+ }
701
+
702
+ KatanaValueFunction* katana_new_function(KatanaParser* parser, KatanaParserString* name, KatanaArray* args)
703
+ {
704
+ KatanaValueFunction* func = katana_parser_allocate(parser, sizeof(KatanaValueFunction));
705
+ func->name = katana_string_to_characters(parser, name);
706
+ func->args = args;
707
+ return func;
708
+ }
709
+
710
+ void katana_destroy_function(KatanaParser* parser, KatanaValueFunction* e)
711
+ {
712
+ katana_destroy_array(parser, katana_destroy_value, e->args);
713
+ katana_parser_deallocate(parser, (void*) e->args);
714
+ katana_parser_deallocate(parser, (void*) e->name);
715
+ katana_parser_deallocate(parser, (void*) e);
716
+ }
717
+
718
+ KatanaValue* katana_new_number_value(KatanaParser* parser, int sign, KatanaParserNumber* value, KatanaValueUnit unit)
719
+ {
720
+ KatanaValue* v = katana_new_value(parser);
721
+ v->isInt = false;
722
+ v->fValue = sign * value->val;
723
+ v->unit = unit;
724
+ if ( 1 == sign ) {
725
+ v->raw = katana_string_to_characters(parser, &value->raw);
726
+ } else {
727
+ v->raw = katana_string_to_characters_with_prefix_char(parser, &value->raw, '-');
728
+ }
729
+ return v;
730
+ }
731
+
732
+ KatanaValue* katana_new_dimension_value(KatanaParser* parser, KatanaParserNumber* value, KatanaValueUnit unit)
733
+ {
734
+ KatanaValue* v = katana_new_value(parser);
735
+ v->isInt = false;
736
+ v->fValue = value->val;
737
+ v->raw = katana_string_to_characters(parser, &value->raw);
738
+ v->unit = unit;
739
+ return v;
740
+ }
741
+
742
+ KatanaValue* katana_new_operator_value(KatanaParser* parser, int value)
743
+ {
744
+ KatanaValue* v = katana_new_value(parser);
745
+ v->isInt = false;
746
+ v->unit = KATANA_VALUE_PARSER_OPERATOR;
747
+ v->iValue = value;
748
+ return v;
749
+ }
750
+
751
+ KatanaValue* katana_new_ident_value(KatanaParser* parser, KatanaParserString* value)
752
+ {
753
+ KatanaValue* v = katana_new_value(parser);
754
+ v->isInt = false;
755
+ v->unit = KATANA_VALUE_IDENT;
756
+ v->string = katana_string_to_characters(parser, value);
757
+ return v;
758
+ }
759
+
760
+ KatanaValue* katana_new_function_value(KatanaParser* parser, KatanaParserString* name, KatanaArray* args)
761
+ {
762
+ KatanaValueFunction* func = katana_new_function(parser, name, args);
763
+ KatanaValue* value = katana_new_value(parser);
764
+ value->unit = KATANA_VALUE_PARSER_FUNCTION;
765
+ value->function = func;
766
+ return value;
767
+ }
768
+
769
+ KatanaValue* katana_new_list_value(KatanaParser* parser, KatanaArray* list)
770
+ {
771
+ KatanaValue* value = katana_new_value(parser);
772
+ value->unit = KATANA_VALUE_PARSER_LIST;
773
+ value->list = list;
774
+ return value;
775
+ }
776
+
777
+ void katana_value_set_string(KatanaParser* parser, KatanaValue* value, KatanaParserString* string)
778
+ {
779
+ value->string = katana_string_to_characters(parser, string);
780
+ }
781
+
782
+ void katana_value_set_sign(KatanaParser* parser, KatanaValue* value, int sign)
783
+ {
784
+ value->fValue *= sign;
785
+
786
+ if ( sign < 0 ) {
787
+ const char* raw = value->raw;
788
+ size_t len = strlen(raw);
789
+ char* new_str = katana_parser_allocate(parser, sizeof(char) * (len + 2));
790
+ strcpy(new_str + 1, raw);
791
+ new_str[0] = '-';
792
+ new_str[len + 1] = '\0';
793
+ value->raw = new_str;
794
+ katana_parser_deallocate(parser, (void*) raw);
795
+ }
796
+ }
797
+
798
+
799
+ KatanaArray* katana_new_value_list(KatanaParser* parser)
800
+ {
801
+ return katana_new_array(parser);
802
+ }
803
+
804
+ void katana_value_list_insert(KatanaParser* parser, KatanaValue* value, int index, KatanaArray* list)
805
+ {
806
+ assert(NULL != value);
807
+ if ( value == NULL)
808
+ return;
809
+ katana_array_insert_at(parser, value, index, list);
810
+ }
811
+
812
+ void katana_value_list_add(KatanaParser* parser, KatanaValue* value, KatanaArray* list)
813
+ {
814
+ assert(NULL != value);
815
+ if ( value == NULL)
816
+ return;
817
+ katana_array_add(parser, value, list);
818
+ }
819
+
820
+ void katana_value_list_steal_values(KatanaParser* parser, KatanaArray* values, KatanaArray* list)
821
+ {
822
+ assert(NULL != values && values->length);
823
+ if ( values == NULL || 0 == values->length )
824
+ return;
825
+ for (size_t i = 0; i < values->length; ++i)
826
+ katana_value_list_add(parser, values->data[i], list);
827
+ katana_parser_deallocate(parser, (void*) values);
828
+ }
829
+
830
+
831
+ KatanaDeclaration *katana_new_declaration(KatanaParser* parser, KatanaParserString* name, bool important, KatanaArray* values)
832
+ {
833
+ KatanaDeclaration * decl = katana_parser_allocate(parser, sizeof(KatanaDeclaration));
834
+
835
+ set_position(parser, &decl->position);
836
+
837
+ decl->property = katana_string_to_characters(parser, name);
838
+ decl->important = important;
839
+ decl->values = values;
840
+ decl->raw = katana_stringify_value_list(parser, values);
841
+
842
+ return decl;
843
+ }
844
+
845
+ bool katana_add_declaration(KatanaParser* parser, KatanaDeclaration *decl)
846
+ {
847
+ katana_array_add(parser, decl, parser->parsed_declarations);
848
+
849
+ return true;
850
+ }
851
+
852
+ void katana_destroy_declaration(KatanaParser* parser, KatanaDeclaration* e)
853
+ {
854
+ katana_destroy_array(parser, katana_destroy_value, e->values);
855
+ katana_parser_deallocate(parser, (void*) e->values);
856
+ katana_parser_deallocate(parser, (void*) e->raw);
857
+ katana_parser_deallocate(parser, (void*) e->property);
858
+ katana_parser_deallocate(parser, (void*) e);
859
+ }
860
+
861
+ void katana_parser_clear_declarations(KatanaParser* parser)
862
+ {
863
+ katana_destroy_array(parser, katana_destroy_declaration, parser->parsed_declarations);
864
+ katana_parser_deallocate(parser, (void*) parser->parsed_declarations);
865
+ parser->parsed_declarations = NULL;
866
+ }
867
+
868
+ void katana_parser_reset_declarations(KatanaParser* parser)
869
+ {
870
+ parser->parsed_declarations = katana_new_array(parser);
871
+ }
872
+
873
+ KatanaSupportsExp *katana_new_supports_exp(KatanaParser* parser, KatanaSupportsOperator op)
874
+ {
875
+ KatanaSupportsExp* exp = katana_parser_allocate(parser, sizeof(KatanaSupportsExp));
876
+ exp->op = op;
877
+ exp->exps = katana_new_array(parser);
878
+ exp->decl = NULL;
879
+ return exp;
880
+ }
881
+
882
+ void katana_supports_exp_list_add(KatanaParser* parser, KatanaSupportsExp* exp, KatanaArray* list)
883
+ {
884
+ //assert(NULL != exp);
885
+ if ( NULL == exp )
886
+ return;
887
+ katana_array_add(parser, exp, list);
888
+ }
889
+
890
+ KatanaRule* katana_new_supports_rule(KatanaParser* parser, KatanaSupportsExp* exp, KatanaArray* rules)
891
+ {
892
+ if ( exp == NULL || rules == NULL )
893
+ return NULL;
894
+
895
+ KatanaSupportsRule* rule = katana_parser_allocate(parser, sizeof(KatanaSupportsRule));
896
+ rule->base.name = "supports";
897
+ rule->base.type = KatanaRuleSupports;
898
+ rule->exp = exp;
899
+ rule->rules = rules;
900
+ return (KatanaRule*)rule;
901
+ }
902
+
903
+ void katana_destroy_supports_exp(KatanaParser* parser, KatanaSupportsExp* e);
904
+
905
+ void katana_destroy_supports_exp_list(KatanaParser* parser, KatanaArray* exps)
906
+ {
907
+ katana_destroy_array(parser, katana_destroy_supports_exp, exps);
908
+ katana_parser_deallocate(parser, (void*) exps);
909
+ }
910
+
911
+ void katana_destroy_supports_exp(KatanaParser* parser, KatanaSupportsExp* e)
912
+ {
913
+ // TODO
914
+ //if(e->decl)
915
+ // katana_destroy_declaration(parser, e->decl);
916
+ katana_destroy_supports_exp_list(parser, e->exps);
917
+ katana_parser_deallocate(parser, (void*) e);
918
+ }
919
+
920
+ void katana_destroy_supports_rule(KatanaParser* parser, KatanaSupportsRule* e)
921
+ {
922
+ katana_destroy_supports_exp(parser, e->exp);
923
+ katana_destroy_rule_list(parser, (void*) e->rules),
924
+ katana_parser_deallocate(parser, (void*) e);
925
+ }
926
+
927
+ KatanaRule* katana_new_media_rule(KatanaParser* parser, KatanaArray* medias, KatanaArray* rules)
928
+ {
929
+ if ( medias == NULL || rules == NULL )
930
+ return NULL;
931
+
932
+ KatanaMediaRule* rule = katana_parser_allocate(parser, sizeof(KatanaMediaRule));
933
+ rule->base.name = "media";
934
+ rule->base.type = KatanaRuleMedia;
935
+ rule->medias = medias;
936
+ rule->rules = rules;
937
+ return (KatanaRule*)rule;
938
+ }
939
+
940
+ void katana_destroy_media_rule(KatanaParser* parser, KatanaMediaRule* e)
941
+ {
942
+ katana_destroy_media_list(parser, (void*) e->medias);
943
+ katana_destroy_rule_list(parser, (void*) e->rules),
944
+ // katana_parser_deallocate(parser, (void*) e->base.name);
945
+ katana_parser_deallocate(parser, (void*) e);
946
+ }
947
+
948
+ KatanaArray* katana_new_media_list(KatanaParser* parser)
949
+ {
950
+ return katana_new_array(parser);
951
+ }
952
+
953
+ void katana_media_list_add(KatanaParser* parser, KatanaMediaQuery* media_query, KatanaArray* medias)
954
+ {
955
+ if ( NULL != media_query ) {
956
+ katana_array_add(parser, media_query, medias);
957
+ }
958
+ }
959
+
960
+ void katana_destroy_media_list(KatanaParser* parser, KatanaArray* medias)
961
+ {
962
+ katana_destroy_array(parser, katana_destroy_media_query, medias);
963
+ katana_parser_deallocate(parser, (void*) medias);
964
+ }
965
+
966
+
967
+ KatanaMediaQuery* katana_new_media_query(KatanaParser* parser, KatanaMediaQueryRestrictor r, KatanaParserString *type, KatanaArray* exps)
968
+ {
969
+ KatanaMediaQuery* media_query = katana_parser_allocate(parser, sizeof(KatanaMediaQuery));
970
+ media_query->restrictor = r;
971
+ media_query->type = type == NULL ? NULL : katana_string_to_characters(parser, type);
972
+ media_query->expressions = exps;
973
+ return media_query;
974
+ }
975
+
976
+ void katana_destroy_media_query(KatanaParser* parser, KatanaMediaQuery* e)
977
+ {
978
+ katana_destroy_array(parser, katana_destroy_media_query_exp, e->expressions);
979
+ katana_parser_deallocate(parser, (void*) e->expressions);
980
+ if ( NULL != e->type ) {
981
+ katana_parser_deallocate(parser, (void*) e->type);
982
+ }
983
+ katana_parser_deallocate(parser, (void*) e);
984
+ }
985
+
986
+
987
+ KatanaMediaQueryExp * katana_new_media_query_exp(KatanaParser* parser, KatanaParserString* feature, KatanaArray* values)
988
+ {
989
+ assert( NULL != feature );
990
+ if ( NULL == feature )
991
+ return NULL;
992
+
993
+ KatanaMediaQueryExp* exp = katana_parser_allocate(parser, sizeof(KatanaMediaQueryExp));
994
+ exp->feature = katana_string_to_characters(parser, feature);
995
+ exp->values = values;
996
+ exp->raw = katana_stringify_value_list(parser, values);
997
+ return exp;
998
+ }
999
+
1000
+ void katana_destroy_media_query_exp(KatanaParser* parser, KatanaMediaQueryExp* e)
1001
+ {
1002
+ if ( NULL != e->values ) {
1003
+ katana_destroy_array(parser, katana_destroy_value, e->values);
1004
+ katana_parser_deallocate(parser, e->values);
1005
+ }
1006
+ katana_parser_deallocate(parser, (void*) e->raw);
1007
+ katana_parser_deallocate(parser, (void*) e->feature);
1008
+ katana_parser_deallocate(parser, (void*) e);
1009
+ }
1010
+
1011
+
1012
+ void katana_media_query_exp_list_add(KatanaParser* parser, KatanaMediaQueryExp* exp, KatanaArray* list)
1013
+ {
1014
+ assert(NULL != exp);
1015
+ if ( NULL == exp )
1016
+ return;
1017
+ katana_array_add(parser, exp, list);
1018
+ }
1019
+
1020
+ KatanaArray* katana_new_media_query_exp_list(KatanaParser* parser)
1021
+ {
1022
+ return katana_new_array(parser);
1023
+ }
1024
+
1025
+
1026
+ KatanaArray* katana_new_rule_list(KatanaParser* parser)
1027
+ {
1028
+ return katana_new_array(parser);
1029
+ }
1030
+
1031
+ KatanaArray* katana_rule_list_add(KatanaParser* parser, KatanaRule* rule, KatanaArray* rule_list)
1032
+ {
1033
+ if ( NULL != rule ) {
1034
+ if ( NULL == rule_list )
1035
+ rule_list = katana_new_rule_list(parser);
1036
+ katana_array_add(parser, rule, rule_list);
1037
+ }
1038
+
1039
+ return rule_list;
1040
+ }
1041
+
1042
+
1043
+ void katana_start_declaration(KatanaParser* parser)
1044
+ {
1045
+ katana_parser_log(parser, "katana_start_declaration");
1046
+ }
1047
+
1048
+ void katana_end_declaration(KatanaParser* parser, bool flag, bool ended)
1049
+ {
1050
+ katana_parser_log(parser, "katana_end_declaration");
1051
+ }
1052
+
1053
+ void katana_set_current_declaration(KatanaParser* parser, KatanaParserString* tag)
1054
+ {
1055
+ katana_parser_log(parser, "katana_set_current_declaration");
1056
+ }
1057
+
1058
+
1059
+ void katana_start_selector(KatanaParser* parser)
1060
+ {
1061
+ katana_parser_log(parser, "katana_start_selector");
1062
+ }
1063
+
1064
+ void katana_end_selector(KatanaParser* parser)
1065
+ {
1066
+ katana_parser_log(parser, "katana_end_selector");
1067
+ }
1068
+
1069
+ KatanaQualifiedName * katana_new_qualified_name(KatanaParser* parser, KatanaParserString* prefix, KatanaParserString* local, KatanaParserString* uri)
1070
+ {
1071
+ KatanaQualifiedName* name = katana_parser_allocate(parser, sizeof(KatanaQualifiedName));
1072
+ name->prefix = prefix == NULL ? NULL : katana_string_to_characters(parser, prefix);
1073
+ name->local = local == NULL ? NULL : katana_string_to_characters(parser, local);
1074
+ name->uri = uri == NULL ? NULL : katana_string_to_characters(parser, uri);
1075
+ return name;
1076
+ }
1077
+
1078
+ void katana_destroy_qualified_name(KatanaParser* parser, KatanaQualifiedName* e)
1079
+ {
1080
+ katana_parser_deallocate(parser, (void*) e->local);
1081
+ katana_parser_deallocate(parser, (void*) e->prefix);
1082
+ katana_parser_deallocate(parser, (void*) e->uri);
1083
+ katana_parser_deallocate(parser, (void*) e);
1084
+ }
1085
+
1086
+ KatanaSelectorRareData* katana_new_rare_data(KatanaParser* parser)
1087
+ {
1088
+ KatanaSelectorRareData* data = katana_parser_allocate(parser, sizeof(KatanaSelectorRareData));
1089
+ data->value = NULL;
1090
+ data->attribute = NULL;
1091
+ data->argument = NULL;
1092
+ data->selectors = NULL;
1093
+ return data;
1094
+ }
1095
+
1096
+ void katana_destroy_rare_data(KatanaParser* parser, KatanaSelectorRareData* e)
1097
+ {
1098
+ if ( NULL != e->value )
1099
+ katana_parser_deallocate(parser, (void*) e->value);
1100
+
1101
+ if ( NULL != e->argument )
1102
+ katana_parser_deallocate(parser, (void*) e->argument);
1103
+
1104
+ if ( NULL != e->attribute )
1105
+ katana_destroy_qualified_name(parser, e->attribute);
1106
+
1107
+ if ( NULL != e->selectors ) {
1108
+ katana_destroy_array(parser, katana_destroy_selector, e->selectors);
1109
+ katana_parser_deallocate(parser, (void*) e->selectors);
1110
+ }
1111
+
1112
+ katana_parser_deallocate(parser, e);
1113
+ }
1114
+
1115
+ KatanaSelector* katana_new_selector(KatanaParser* parser)
1116
+ {
1117
+ KatanaSelector* selector = katana_parser_allocate(parser, sizeof(KatanaSelector));
1118
+
1119
+ set_position(parser, &selector->position);
1120
+
1121
+ selector->data = katana_new_rare_data(parser);
1122
+ selector->tag = NULL;
1123
+ selector->match = 0;
1124
+ selector->pseudo = KatanaPseudoNotParsed;
1125
+ selector->relation = 0;
1126
+ selector->specificity = 0;
1127
+ selector->tag = NULL;
1128
+ selector->tagHistory = NULL;
1129
+ #if KATANA_PARSER_DEBUG
1130
+ katana_array_add(parser, selector, parser->parsed_selectors);
1131
+ #endif // #if KATANA_PARSER_DEBUG
1132
+
1133
+ return selector;
1134
+ }
1135
+
1136
+ KatanaSelector* katana_sink_floating_selector(KatanaParser* parser, KatanaSelector* selector)
1137
+ {
1138
+ #if KATANA_PARSER_DEBUG
1139
+ katana_array_remove(parser, selector, parser->parsed_selectors);
1140
+ #endif // #if KATANA_PARSER_DEBUG
1141
+ return selector;
1142
+ }
1143
+
1144
+ void katana_destroy_one_selector(KatanaParser* parser, KatanaSelector* e)
1145
+ {
1146
+ katana_destroy_rare_data(parser, e->data);
1147
+
1148
+ if ( e->tag != NULL )
1149
+ katana_destroy_qualified_name(parser, e->tag);
1150
+
1151
+ katana_parser_deallocate(parser, e);
1152
+ }
1153
+
1154
+ void katana_destroy_selector(KatanaParser* parser, KatanaSelector* e)
1155
+ {
1156
+ KatanaSelector *p = e, *q;
1157
+ while ( p ) {
1158
+ q = p->tagHistory;
1159
+ katana_destroy_one_selector(parser, p);
1160
+ p = q;
1161
+ }
1162
+ }
1163
+
1164
+ KatanaSelector* katana_rewrite_specifier_with_element_name(KatanaParser* parser, KatanaParserString* tag, KatanaSelector* specifier)
1165
+ {
1166
+ // TODO: (@QFish) check if css3 support
1167
+ bool supported = true;
1168
+
1169
+ if ( supported ) {
1170
+ KatanaSelector* prepend = katana_new_selector(parser);
1171
+ prepend->tag = katana_new_qualified_name(parser, NULL, tag, &parser->default_namespace);
1172
+ prepend->match = KatanaSelectorMatchTag;
1173
+ prepend->tagHistory = katana_sink_floating_selector(parser, specifier);
1174
+ prepend->relation = KatanaSelectorRelationSubSelector;
1175
+ return prepend;
1176
+ }
1177
+
1178
+ return specifier;
1179
+ }
1180
+
1181
+ KatanaSelector* katana_rewrite_specifier_with_namespace_if_needed(KatanaParser* parser, KatanaSelector* specifiers)
1182
+ {
1183
+ // TODO: @(QFish) add logic
1184
+ return specifiers;
1185
+ }
1186
+
1187
+ KatanaSelector* katana_rewrite_specifiers(KatanaParser* parser, KatanaSelector* specifiers, KatanaSelector* newSpecifier)
1188
+ {
1189
+ if (katana_selector_crosses_tree_scopes(newSpecifier)) {
1190
+ // Unknown pseudo element always goes at the top of selector chain.
1191
+ katana_selector_append(parser, newSpecifier, katana_sink_floating_selector(parser, specifiers), KatanaSelectorRelationShadowPseudo);
1192
+ return newSpecifier;
1193
+ }
1194
+ if (katana_selector_is_content_pseudo_element(newSpecifier)) {
1195
+ katana_selector_append(parser, newSpecifier, katana_sink_floating_selector(parser, specifiers), KatanaSelectorRelationSubSelector);
1196
+ return newSpecifier;
1197
+ }
1198
+ if (katana_selector_crosses_tree_scopes(specifiers)) {
1199
+ // Specifiers for unknown pseudo element go right behind it in the chain.
1200
+ katana_selector_insert(parser, specifiers, katana_sink_floating_selector(parser, newSpecifier), KatanaSelectorRelationSubSelector, KatanaSelectorRelationShadowPseudo);
1201
+ return specifiers;
1202
+ }
1203
+ if (katana_selector_is_content_pseudo_element(specifiers)) {
1204
+ katana_selector_insert(parser, specifiers, katana_sink_floating_selector(parser, newSpecifier), KatanaSelectorRelationSubSelector, KatanaSelectorRelationSubSelector);
1205
+ return specifiers;
1206
+ }
1207
+
1208
+ katana_selector_append(parser, specifiers, katana_sink_floating_selector(parser, newSpecifier), KatanaSelectorRelationSubSelector);
1209
+ return specifiers;
1210
+ }
1211
+
1212
+ void katana_adopt_selector_list(KatanaParser* parser, KatanaArray* selectors, KatanaSelector* selector)
1213
+ {
1214
+ katana_parser_log(parser, "katana_adopt_selector_list");
1215
+ selector->data->selectors = selectors;
1216
+ }
1217
+
1218
+ void katana_selector_append(KatanaParser* parser, KatanaSelector* selector, KatanaSelector* new_selector, KatanaSelectorRelation relation)
1219
+ {
1220
+ katana_parser_log(parser, "katana_selector_append");
1221
+ KatanaSelector* end = selector;
1222
+ while (NULL != end->tagHistory)
1223
+ end = end->tagHistory;
1224
+ end->relation = relation;
1225
+ end->tagHistory = new_selector;
1226
+ }
1227
+
1228
+ void katana_selector_insert(KatanaParser* parser, KatanaSelector* selector, KatanaSelector* new_selector, KatanaSelectorRelation before, KatanaSelectorRelation after)
1229
+ {
1230
+ katana_parser_log(parser, "katana_selector_insert");
1231
+
1232
+ if (selector->tagHistory)
1233
+ new_selector->tagHistory = selector;
1234
+ selector->relation = before;
1235
+ new_selector->relation = after;
1236
+ selector->tagHistory = selector;
1237
+ }
1238
+
1239
+ void katana_selector_prepend_with_element_name(KatanaParser* parser, KatanaSelector* selector, KatanaParserString* tag)
1240
+ {
1241
+ katana_parser_log(parser, "katana_selector_prepend_with_element_name");
1242
+
1243
+ KatanaSelector* prev = katana_new_selector(parser);
1244
+ prev->tag = katana_new_qualified_name(parser, NULL, tag, &parser->default_namespace);
1245
+ selector->tagHistory = prev;
1246
+ selector->relation = KatanaSelectorRelationSubSelector;
1247
+ }
1248
+
1249
+ KatanaArray* katana_new_selector_list(KatanaParser* parser)
1250
+ {
1251
+ return katana_new_array(parser);
1252
+ }
1253
+
1254
+ KatanaArray* katana_reusable_selector_list(KatanaParser* parser)
1255
+ {
1256
+ return katana_new_array(parser);
1257
+ }
1258
+
1259
+ void katana_selector_list_shink(KatanaParser* parser, int capacity, KatanaArray* list)
1260
+ {
1261
+
1262
+ }
1263
+
1264
+ void katana_selector_list_add(KatanaParser* parser, KatanaSelector* selector, KatanaArray* list)
1265
+ {
1266
+ assert(NULL != selector);
1267
+ if ( NULL == selector )
1268
+ return;
1269
+
1270
+ katana_array_add(parser, selector, list);
1271
+ }
1272
+
1273
+ void katana_selector_set_value(KatanaParser* parser, KatanaSelector* selector, KatanaParserString* value)
1274
+ {
1275
+ selector->data->value = katana_string_to_characters(parser, value);
1276
+ }
1277
+
1278
+ void katana_selector_set_argument_with_number(KatanaParser* parser, KatanaSelector* selector, int sign, KatanaParserNumber* value)
1279
+ {
1280
+ if ( 1 == sign ) {
1281
+ selector->data->argument = katana_string_to_characters(parser, &value->raw);
1282
+ } else {
1283
+ selector->data->argument = katana_string_to_characters_with_prefix_char(parser, &value->raw, '-');
1284
+ }
1285
+ }
1286
+
1287
+ void katana_selector_set_argument(KatanaParser* parser, KatanaSelector* selector, KatanaParserString* argument)
1288
+ {
1289
+ selector->data->argument = katana_string_to_characters(parser, argument);
1290
+ }
1291
+
1292
+ bool katana_parse_attribute_match_type(KatanaParser* parser, KatanaAttributeMatchType type, KatanaParserString* attr)
1293
+ {
1294
+ return true;
1295
+ }
1296
+
1297
+ bool katana_selector_is_simple(KatanaParser* parser, KatanaSelector* selector)
1298
+ {
1299
+ if (NULL != selector->data->selectors)
1300
+ return false;
1301
+
1302
+ if (NULL == selector->tagHistory)
1303
+ return true;
1304
+ // TODO: @(QFish) check more.
1305
+ return false;
1306
+ }
1307
+
1308
+
1309
+ void katana_add_rule(KatanaParser* parser, KatanaRule* rule)
1310
+ {
1311
+ assert( NULL != rule );
1312
+ if ( NULL == rule )
1313
+ return;
1314
+
1315
+ switch ( rule->type ) {
1316
+ case KatanaRuleImport:
1317
+ katana_array_add(parser, rule, &parser->output->stylesheet->imports);
1318
+ break;
1319
+ default:
1320
+ katana_array_add(parser, rule, &parser->output->stylesheet->rules);
1321
+ break;
1322
+ }
1323
+ }
1324
+
1325
+ void katana_start_rule(KatanaParser* parser)
1326
+ {
1327
+ katana_parser_log(parser, "katana_start_rule");
1328
+ }
1329
+
1330
+ void katana_end_rule(KatanaParser* parser, bool ended)
1331
+ {
1332
+ katana_parser_log(parser, "katana_end_rule");
1333
+ }
1334
+
1335
+ void katana_start_rule_header(KatanaParser* parser, KatanaRuleType type)
1336
+ {
1337
+ katana_parser_log(parser, "katana_start_rule_header");
1338
+ }
1339
+
1340
+ void katana_end_rule_header(KatanaParser* parser)
1341
+ {
1342
+ katana_parser_log(parser, "katana_end_rule_header");
1343
+ }
1344
+
1345
+ void katana_end_invalid_rule_header(KatanaParser* parser)
1346
+ {
1347
+ katana_parser_log(parser, "katana_end_invalid_rule_header");
1348
+ }
1349
+
1350
+ void katana_start_rule_body(KatanaParser* parser)
1351
+ {
1352
+ katana_parser_log(parser, "katana_start_rule_body");
1353
+ }
1354
+
1355
+
1356
+ bool katana_string_is_function(KatanaParserString* string)
1357
+ {
1358
+ return string && (string->length > 0) && (string->data[string->length - 1] == '(');
1359
+ }
1360
+
1361
+ void katana_string_clear(KatanaParser* parser, KatanaParserString* string)
1362
+ {
1363
+ printf("==%s==\n", string->data);
1364
+ katana_parser_deallocate(parser, (void*) string->data);
1365
+ katana_parser_deallocate(parser, (void*) string);
1366
+ }
1367
+
1368
+
1369
+ void katanaerror(YYLTYPE* yyloc, void* scanner, struct KatanaInternalParser * parser, char* error)
1370
+ {
1371
+ #ifdef KATANA_PARSER_DEBUG
1372
+ #if KATANA_PARSER_DEBUG
1373
+ katana_print("[Error] %d.%d - %d.%d: %s at %s\n",
1374
+ yyloc->first_line,
1375
+ yyloc->first_column,
1376
+ yyloc->last_line,
1377
+ yyloc->last_column,
1378
+ error,
1379
+ katanaget_text(parser->scanner));
1380
+
1381
+ YYSTYPE * s = katanaget_lval(parser->scanner);
1382
+
1383
+ // struct yy_buffer_state state = katana_get_previous_state(parser->scanner);
1384
+ // s, (*yy_buffer_stack[0]).yy_ch_buf);
1385
+ //
1386
+ // katana_print("%s", s->);
1387
+ #endif // #if KATANA_PARSER_DEBUG
1388
+ #endif // #ifdef KATANA_PARSER_DEBUG
1389
+
1390
+ KatanaError *e = (KatanaError *)malloc(sizeof(KatanaError));
1391
+ e->type = KatanaParseError;
1392
+ e->first_line = yyloc->first_line;
1393
+ e->first_column = yyloc->first_column;
1394
+ e->last_line = yyloc->last_line;
1395
+ e->last_column = yyloc->last_column;
1396
+ snprintf(e->message, KATANA_ERROR_MESSAGE_SIZE, "%s at %s", error,
1397
+ katanaget_text(*parser->scanner));
1398
+ katana_array_add(parser, e, &(parser->output->errors));
1399
+
1400
+ }
1401
+
1402
+ void katana_parser_log(KatanaParser* parser, const char * format, ...)
1403
+ {
1404
+ #ifdef KATANA_PARSER_LOG_ENABLE
1405
+ #if KATANA_PARSER_LOG_ENABLE
1406
+ va_list args;
1407
+ va_start(args, format);
1408
+ printf(" -> ");
1409
+ vprintf(format, args);
1410
+ printf("\n");
1411
+ va_end(args);
1412
+ fflush(stdout);
1413
+ #endif // #if KATANA_PARSER_LOG_ENABLE
1414
+ #endif // #ifdef KATANA_PARSER_LOG_ENABLE
1415
+ }
1416
+
1417
+ void katana_parser_resume_error_logging()
1418
+ {
1419
+
1420
+ }
1421
+
1422
+ void katana_parser_report_error(KatanaParser* parser, KatanaSourcePosition* pos, const char* format, ...)
1423
+ {
1424
+ #ifdef KATANA_PARSER_DEBUG
1425
+ #if KATANA_PARSER_DEBUG
1426
+ printf("[ERROR] %d.%d - %d.%d : ", pos->line, pos->column, katanaget_lineno(*parser->scanner), katanaget_column(*parser->scanner) );
1427
+ va_list args;
1428
+ va_start(args, format);
1429
+ vprintf(format, args);
1430
+ va_end(args);
1431
+ printf("\n");
1432
+ fflush(stdout);
1433
+ #endif // #if KATANA_PARSER_DEBUG
1434
+ #endif // #ifdef KATANA_PARSER_DEBUG
1435
+ }
1436
+
1437
+ KatanaSourcePosition* katana_parser_current_location(KatanaParser* parser, YYLTYPE* yylloc)
1438
+ {
1439
+ parser->position->line = katanaget_lineno(*parser->scanner);
1440
+ parser->position->column = katanaget_column(*parser->scanner);
1441
+ return parser->position;
1442
+ }
1443
+
1444
+
1445
+ void katana_print(const char * format, ...)
1446
+ {
1447
+ va_list args;
1448
+ va_start(args, format);
1449
+ vprintf(format, args);
1450
+ printf("\n");
1451
+ va_end(args);
1452
+ fflush(stdout);
1453
+ }
1454
+
1455
+ static const char* katana_stringify_value_list(KatanaParser* parser, KatanaArray* values)
1456
+ {
1457
+ if (NULL == values)
1458
+ return NULL;
1459
+ KatanaParserString * buffer = katana_parser_allocate(parser, sizeof(KatanaParserString));
1460
+ katana_string_init(parser, buffer);
1461
+ for (size_t i = 0; i < values->length; ++i) {
1462
+ KatanaValue* value = values->data[i];
1463
+ const char* value_str = katana_stringify_value(parser, value);
1464
+ katana_string_append_characters(parser, value_str, buffer);
1465
+ katana_parser_deallocate(parser, (void*) value_str);
1466
+ value_str = NULL;
1467
+ if ( i < values->length - 1 ) {
1468
+ if ( value->unit != KATANA_VALUE_PARSER_OPERATOR ) {
1469
+ if ( i < values->length - 2 ) {
1470
+ value = values->data[i+1];
1471
+ if ( value->unit != KATANA_VALUE_PARSER_OPERATOR ) {
1472
+ katana_string_append_characters(parser, " ", buffer);
1473
+ }
1474
+ } else {
1475
+ katana_string_append_characters(parser, " ", buffer);
1476
+ }
1477
+ }
1478
+ }
1479
+ }
1480
+ const char * str = katana_string_to_characters(parser, (KatanaParserString*)buffer);
1481
+ katana_parser_deallocate(parser, buffer->data);
1482
+ katana_parser_deallocate(parser, (void*) buffer);
1483
+ return str;
1484
+ }
1485
+
1486
+ static const char* katana_stringify_value(KatanaParser* parser, KatanaValue* value)
1487
+ {
1488
+ // TODO: @(QFish) Handle this more gracefully X).
1489
+ char str[256];
1490
+
1491
+ switch (value->unit) {
1492
+ case KATANA_VALUE_NUMBER:
1493
+ case KATANA_VALUE_PERCENTAGE:
1494
+ case KATANA_VALUE_EMS:
1495
+ case KATANA_VALUE_EXS:
1496
+ case KATANA_VALUE_REMS:
1497
+ case KATANA_VALUE_CHS:
1498
+ case KATANA_VALUE_PX:
1499
+ case KATANA_VALUE_CM:
1500
+ case KATANA_VALUE_DPPX:
1501
+ case KATANA_VALUE_DPI:
1502
+ case KATANA_VALUE_DPCM:
1503
+ case KATANA_VALUE_MM:
1504
+ case KATANA_VALUE_IN:
1505
+ case KATANA_VALUE_PT:
1506
+ case KATANA_VALUE_PC:
1507
+ case KATANA_VALUE_DEG:
1508
+ case KATANA_VALUE_RAD:
1509
+ case KATANA_VALUE_GRAD:
1510
+ case KATANA_VALUE_MS:
1511
+ case KATANA_VALUE_S:
1512
+ case KATANA_VALUE_HZ:
1513
+ case KATANA_VALUE_KHZ:
1514
+ case KATANA_VALUE_TURN:
1515
+ case KATANA_VALUE_VW:
1516
+ case KATANA_VALUE_VH:
1517
+ case KATANA_VALUE_VMIN:
1518
+ case KATANA_VALUE_VMAX:
1519
+ snprintf(str, sizeof(str), "%s", value->raw);
1520
+ break;
1521
+ case KATANA_VALUE_IDENT:
1522
+ snprintf(str, sizeof(str), "%s", value->string);
1523
+ break;
1524
+ case KATANA_VALUE_STRING:
1525
+ // FIXME: @(QFish) Do we need double quote or not ?
1526
+ // snprintf(str, sizeof(str), "\"%s\"", value->string);
1527
+ snprintf(str, sizeof(str), "%s", value->string);
1528
+ break;
1529
+ case KATANA_VALUE_PARSER_FUNCTION:
1530
+ {
1531
+ const char* args_str = katana_stringify_value_list(parser, value->function->args);
1532
+ snprintf(str, sizeof(str), "%s%s)", value->function->name, args_str);
1533
+ katana_parser_deallocate(parser, (void*) args_str);
1534
+ break;
1535
+ }
1536
+ case KATANA_VALUE_PARSER_OPERATOR:
1537
+ if (value->iValue != '=') {
1538
+ snprintf(str, sizeof(str), " %c ", value->iValue);
1539
+ } else {
1540
+ snprintf(str, sizeof(str), " %c", value->iValue);
1541
+ }
1542
+ break;
1543
+ case KATANA_VALUE_PARSER_LIST:
1544
+ return katana_stringify_value_list(parser, value->list);
1545
+ break;
1546
+ case KATANA_VALUE_PARSER_HEXCOLOR:
1547
+ snprintf(str, sizeof(str), "#%s", value->string);
1548
+ break;
1549
+ case KATANA_VALUE_URI:
1550
+ snprintf(str, sizeof(str), "url(%s)", value->string);
1551
+ break;
1552
+ default:
1553
+ snprintf(str, sizeof(str), "%s", value->raw);
1554
+ // katana_print("KATANA: Unknown Value unit.");
1555
+ break;
1556
+ }
1557
+
1558
+ size_t len = strlen(str);
1559
+ char* dest = katana_parser_allocate(parser, len+1);
1560
+ strcpy(dest, str);
1561
+ dest[len] = '\0';
1562
+ return dest;
1563
+ }