habaki 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }