]> mj.ucw.cz Git - leo.git/blob - css-parse.y
Low-level parts of text rotation
[leo.git] / css-parse.y
1 /*
2  *      Hic Est Leo -- MapCSS Parser
3  *
4  *      (c) 2014 Martin Mares <mj@ucw.cz>
5  */
6
7 %{
8 #include <ucw/lib.h>
9 #include <ucw/mempool.h>
10
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include "leo.h"
15 #include "css.h"
16
17 static void *css_alloc(size_t n)
18 {
19   return mp_alloc_zero(css_this->pool, n);
20 }
21
22 static struct css_path *css_new_path(void)
23 {
24   struct css_path *p = css_alloc(sizeof(struct css_path));
25   clist_init(&p->conditions);
26   p->layer = STYLE_LAYER_DEFAULT;
27   return p;
28 }
29
30 static void css_add_to_val_list(struct style_prop *list, struct style_prop *elt)
31 {
32   struct style_val_list_entry *e = css_alloc(sizeof(*e));
33   clist_add_tail(list->val.list, &e->n);
34   e->val = *elt;
35 }
36
37 %}
38
39 %union {
40   char *s;
41   struct css_rule *rule;
42   struct css_selector *selector;
43   struct css_path *path;
44   struct css_condition *condition;
45   struct css_action *action;
46   struct style_prop prop;
47   enum css_cond_op cond_op;
48 }
49
50 %token LE GE NE CC
51 %token <s> NUMBER IDENT QUOTED RGB
52
53 %type <s> ident_or_quoted
54 %type <rule> rule rule_start rule_selectors rule_start_actions rule_actions
55 %type <selector> selector selector_start
56 %type <path> path path_start path_conditions
57 %type <condition> condition
58 %type <action> action
59 %type <prop> prop_value prop_value_single prop_value_list
60 %type <cond_op> binary_op
61
62 %%
63
64 input:
65     /* empty */
66   | input rule { clist_add_tail(&css_this->rules, &$2->n); }
67   ;
68
69 rule_start:
70     /* empty */
71     {
72       $$ = css_alloc(sizeof(struct css_rule));
73       clist_init(&$$->selectors);
74       clist_init(&$$->actions);
75     }
76   ;
77
78 rule_selectors:
79     rule_start selector
80     {
81       clist_add_tail(&$1->selectors, &$2->n);
82       $$ = $1;
83     }
84   | rule_selectors ',' selector
85     {
86       clist_add_tail(&$1->selectors, &$3->n);
87       $$ = $1;
88     }
89   ;
90
91 rule_start_actions:
92     rule_start
93   | rule_selectors
94   ;
95
96 rule_actions:
97     rule_start_actions '{'
98     {
99       $$ = $1;
100     }
101   | rule_actions action ';'
102     {
103       $$ = $1;
104       clist_add_tail(&$$->actions, &$2->n);
105     }
106   ;
107
108 rule: rule_actions '}' ;
109
110 selector_start:
111     /* empty */
112     {
113       $$ = css_alloc(sizeof(struct css_selector));
114       clist_init(&$$->path);
115     }
116   ;
117
118 selector:
119     selector_start path
120     {
121       clist_add_tail(&$1->path, &$2->n);
122       $$ = $1;
123     }
124   | selector path
125     {
126       // FIXME: Descendant operator
127       clist_add_tail(&$1->path, &$2->n);
128       $$ = $1;
129     }
130   ;
131
132 path_start:
133     IDENT
134     {
135       $$ = css_new_path();
136       if (!strcmp($1, "node"))
137         $$->type = CSS_TYPE_NODE;
138       else if (!strcmp($1, "way"))
139         $$->type = CSS_TYPE_WAY;
140       else if (!strcmp($1, "relation"))
141         $$->type = CSS_TYPE_RELATION;
142       else if (!strcmp($1, "area"))
143         $$->type = CSS_TYPE_AREA;
144       else if (!strcmp($1, "meta"))
145         $$->type = CSS_TYPE_META;
146       else
147         die("Invalid selector %s", $1);
148     }
149   | '*'
150     {
151       $$ = css_new_path();
152       $$->type = CSS_TYPE_ANY;
153     }
154   ;
155
156 path_conditions:
157     path_start
158   | path_conditions '[' condition ']'
159     {
160       $$ = $1;
161       clist_add_tail(&$$->conditions, &$3->n);
162     }
163   ;
164
165 path:
166     path_conditions
167   | path ':' IDENT
168     {
169       // So far, no modifiers are supported, so a rule with modifiers never matches
170       $$ = $1;
171       $$->modifiers |= PATH_MOD_NEVER;
172     }
173   | path CC IDENT
174     {
175       // Layer
176       $$ = $1;
177       $$->layer = style_layer_encode($3);
178     }
179   | path CC '*'
180     {
181       // All layers
182       $$ = $1;
183       $$->layer = STYLE_LAYER_ALL;
184     }
185   ;
186
187 condition:
188     ident_or_quoted binary_op ident_or_quoted
189     {
190       $$ = css_alloc(sizeof(struct css_condition));
191       $$->op = $2;
192       $$->key = osm_key_encode($1);
193       $$->val = osm_val_encode($3);
194     }
195   | ident_or_quoted
196     {
197       $$ = css_alloc(sizeof(struct css_condition));
198       $$->op = COND_OP_IS_SET;
199       $$->key = osm_key_encode($1);
200     }
201   | '!' ident_or_quoted
202     {
203       $$ = css_alloc(sizeof(struct css_condition));
204       $$->op = COND_OP_IS_UNSET;
205       $$->key = osm_key_encode($2);
206     }
207   | ident_or_quoted '?'
208     {
209       $$ = css_alloc(sizeof(struct css_condition));
210       $$->op = COND_OP_IS_TRUE;
211       $$->key = osm_key_encode($1);
212     }
213   | ident_or_quoted '?' '!'
214     {
215       $$ = css_alloc(sizeof(struct css_condition));
216       $$->op = COND_OP_IS_FALSE;
217       $$->key = osm_key_encode($1);
218     }
219   ;
220
221 binary_op:
222     '=' { $$ = COND_OP_EQ; }
223   | '<' { $$ = COND_OP_LT; }
224   | '>' { $$ = COND_OP_GT; }
225   | LE  { $$ = COND_OP_LE; }
226   | GE  { $$ = COND_OP_GE; }
227   | NE  { $$ = COND_OP_NE; }
228   ;
229
230 action:
231     ident_or_quoted ':' prop_value
232       {
233         $$ = css_alloc(sizeof(struct css_action));
234         $$->prop = $3;
235         $$->prop.key = style_prop_encode($1);
236       }
237   ;
238
239 prop_value:
240     prop_value_single
241   | prop_value_list
242   ;
243
244 prop_value_single:
245     IDENT
246       {
247         $$.type = PROP_TYPE_IDENT;
248         $$.val.id = osm_val_encode($1);
249       }
250   | QUOTED
251       {
252         $$.type = PROP_TYPE_STRING;
253         $$.val.id = osm_val_encode($1);
254       }
255   | NUMBER
256       {
257         $$.type = PROP_TYPE_NUMBER;
258         $$.val.number = atof($1);
259       }
260   | RGB
261       {
262         $$.type = PROP_TYPE_COLOR;
263         $$.val.color = css_rgb_to_color($1);
264       }
265   ;
266
267 prop_value_list:
268     prop_value_single ',' prop_value_single
269       {
270         $$.type = PROP_TYPE_LIST;
271         $$.val.list = css_alloc(sizeof(clist));
272         clist_init($$.val.list);
273         css_add_to_val_list(&$$, &$1);
274         css_add_to_val_list(&$$, &$3);
275       }
276   | prop_value_list ',' prop_value_single
277       {
278         $$ = $1;
279         css_add_to_val_list(&$$, &$3);
280       }
281   ;
282
283 ident_or_quoted: IDENT | QUOTED ;
284
285 %%
286
287 struct css_sheet *css_this;
288
289 struct css_sheet *css_load(char *filename)
290 {
291   struct mempool *mp = mp_new(4096);
292   struct css_sheet *ss = mp_alloc_zero(mp, sizeof(*ss));
293   ss->pool = mp;
294   clist_init(&ss->rules);
295   ss->filename = mp_strdup(mp, filename);
296
297   css_this = ss;
298   css_lex_open();
299   css_parse();
300
301   css_lex_close();
302   css_this = NULL;
303   return ss;
304 }