xref: /OK3568_Linux_fs/u-boot/scripts/dtc/dtc-parser.y (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * This program is free software; you can redistribute it and/or
6*4882a593Smuzhiyun  * modify it under the terms of the GNU General Public License as
7*4882a593Smuzhiyun  * published by the Free Software Foundation; either version 2 of the
8*4882a593Smuzhiyun  * License, or (at your option) any later version.
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  *  This program is distributed in the hope that it will be useful,
11*4882a593Smuzhiyun  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12*4882a593Smuzhiyun  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13*4882a593Smuzhiyun  *  General Public License for more details.
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  *  You should have received a copy of the GNU General Public License
16*4882a593Smuzhiyun  *  along with this program; if not, write to the Free Software
17*4882a593Smuzhiyun  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18*4882a593Smuzhiyun  *                                                                   USA
19*4882a593Smuzhiyun  */
20*4882a593Smuzhiyun %{
21*4882a593Smuzhiyun #include <stdio.h>
22*4882a593Smuzhiyun #include <inttypes.h>
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #include "dtc.h"
25*4882a593Smuzhiyun #include "srcpos.h"
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun extern int yylex(void);
28*4882a593Smuzhiyun extern void yyerror(char const *s);
29*4882a593Smuzhiyun #define ERROR(loc, ...) \
30*4882a593Smuzhiyun 	do { \
31*4882a593Smuzhiyun 		srcpos_error((loc), "Error", __VA_ARGS__); \
32*4882a593Smuzhiyun 		treesource_error = true; \
33*4882a593Smuzhiyun 	} while (0)
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun extern struct dt_info *parser_output;
36*4882a593Smuzhiyun extern bool treesource_error;
37*4882a593Smuzhiyun %}
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun %union {
40*4882a593Smuzhiyun 	char *propnodename;
41*4882a593Smuzhiyun 	char *labelref;
42*4882a593Smuzhiyun 	uint8_t byte;
43*4882a593Smuzhiyun 	struct data data;
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	struct {
46*4882a593Smuzhiyun 		struct data	data;
47*4882a593Smuzhiyun 		int		bits;
48*4882a593Smuzhiyun 	} array;
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	struct property *prop;
51*4882a593Smuzhiyun 	struct property *proplist;
52*4882a593Smuzhiyun 	struct node *node;
53*4882a593Smuzhiyun 	struct node *nodelist;
54*4882a593Smuzhiyun 	struct reserve_info *re;
55*4882a593Smuzhiyun 	uint64_t integer;
56*4882a593Smuzhiyun 	unsigned int flags;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun %token DT_V1
60*4882a593Smuzhiyun %token DT_PLUGIN
61*4882a593Smuzhiyun %token DT_MEMRESERVE
62*4882a593Smuzhiyun %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
63*4882a593Smuzhiyun %token DT_BITS
64*4882a593Smuzhiyun %token DT_DEL_PROP
65*4882a593Smuzhiyun %token DT_DEL_NODE
66*4882a593Smuzhiyun %token <propnodename> DT_PROPNODENAME
67*4882a593Smuzhiyun %token <integer> DT_LITERAL
68*4882a593Smuzhiyun %token <integer> DT_CHAR_LITERAL
69*4882a593Smuzhiyun %token <byte> DT_BYTE
70*4882a593Smuzhiyun %token <data> DT_STRING
71*4882a593Smuzhiyun %token <labelref> DT_LABEL
72*4882a593Smuzhiyun %token <labelref> DT_REF
73*4882a593Smuzhiyun %token DT_INCBIN
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun %type <data> propdata
76*4882a593Smuzhiyun %type <data> propdataprefix
77*4882a593Smuzhiyun %type <flags> header
78*4882a593Smuzhiyun %type <flags> headers
79*4882a593Smuzhiyun %type <re> memreserve
80*4882a593Smuzhiyun %type <re> memreserves
81*4882a593Smuzhiyun %type <array> arrayprefix
82*4882a593Smuzhiyun %type <data> bytestring
83*4882a593Smuzhiyun %type <prop> propdef
84*4882a593Smuzhiyun %type <proplist> proplist
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun %type <node> devicetree
87*4882a593Smuzhiyun %type <node> nodedef
88*4882a593Smuzhiyun %type <node> subnode
89*4882a593Smuzhiyun %type <nodelist> subnodes
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun %type <integer> integer_prim
92*4882a593Smuzhiyun %type <integer> integer_unary
93*4882a593Smuzhiyun %type <integer> integer_mul
94*4882a593Smuzhiyun %type <integer> integer_add
95*4882a593Smuzhiyun %type <integer> integer_shift
96*4882a593Smuzhiyun %type <integer> integer_rela
97*4882a593Smuzhiyun %type <integer> integer_eq
98*4882a593Smuzhiyun %type <integer> integer_bitand
99*4882a593Smuzhiyun %type <integer> integer_bitxor
100*4882a593Smuzhiyun %type <integer> integer_bitor
101*4882a593Smuzhiyun %type <integer> integer_and
102*4882a593Smuzhiyun %type <integer> integer_or
103*4882a593Smuzhiyun %type <integer> integer_trinary
104*4882a593Smuzhiyun %type <integer> integer_expr
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun %%
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun sourcefile:
109*4882a593Smuzhiyun 	  headers memreserves devicetree
110*4882a593Smuzhiyun 		{
111*4882a593Smuzhiyun 			parser_output = build_dt_info($1, $2, $3,
112*4882a593Smuzhiyun 			                              guess_boot_cpuid($3));
113*4882a593Smuzhiyun 		}
114*4882a593Smuzhiyun 	;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun header:
117*4882a593Smuzhiyun 	  DT_V1 ';'
118*4882a593Smuzhiyun 		{
119*4882a593Smuzhiyun 			$$ = DTSF_V1;
120*4882a593Smuzhiyun 		}
121*4882a593Smuzhiyun 	| DT_V1 ';' DT_PLUGIN ';'
122*4882a593Smuzhiyun 		{
123*4882a593Smuzhiyun 			$$ = DTSF_V1 | DTSF_PLUGIN;
124*4882a593Smuzhiyun 		}
125*4882a593Smuzhiyun 	;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun headers:
128*4882a593Smuzhiyun 	  header
129*4882a593Smuzhiyun 	| header headers
130*4882a593Smuzhiyun 		{
131*4882a593Smuzhiyun 			if ($2 != $1)
132*4882a593Smuzhiyun 				ERROR(&@2, "Header flags don't match earlier ones");
133*4882a593Smuzhiyun 			$$ = $1;
134*4882a593Smuzhiyun 		}
135*4882a593Smuzhiyun 	;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun memreserves:
138*4882a593Smuzhiyun 	  /* empty */
139*4882a593Smuzhiyun 		{
140*4882a593Smuzhiyun 			$$ = NULL;
141*4882a593Smuzhiyun 		}
142*4882a593Smuzhiyun 	| memreserve memreserves
143*4882a593Smuzhiyun 		{
144*4882a593Smuzhiyun 			$$ = chain_reserve_entry($1, $2);
145*4882a593Smuzhiyun 		}
146*4882a593Smuzhiyun 	;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun memreserve:
149*4882a593Smuzhiyun 	  DT_MEMRESERVE integer_prim integer_prim ';'
150*4882a593Smuzhiyun 		{
151*4882a593Smuzhiyun 			$$ = build_reserve_entry($2, $3);
152*4882a593Smuzhiyun 		}
153*4882a593Smuzhiyun 	| DT_LABEL memreserve
154*4882a593Smuzhiyun 		{
155*4882a593Smuzhiyun 			add_label(&$2->labels, $1);
156*4882a593Smuzhiyun 			$$ = $2;
157*4882a593Smuzhiyun 		}
158*4882a593Smuzhiyun 	;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun devicetree:
161*4882a593Smuzhiyun 	  '/' nodedef
162*4882a593Smuzhiyun 		{
163*4882a593Smuzhiyun 			$$ = name_node($2, "");
164*4882a593Smuzhiyun 		}
165*4882a593Smuzhiyun 	| devicetree '/' nodedef
166*4882a593Smuzhiyun 		{
167*4882a593Smuzhiyun 			$$ = merge_nodes($1, $3);
168*4882a593Smuzhiyun 		}
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	| devicetree DT_LABEL DT_REF nodedef
171*4882a593Smuzhiyun 		{
172*4882a593Smuzhiyun 			struct node *target = get_node_by_ref($1, $3);
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 			if (target) {
175*4882a593Smuzhiyun 				add_label(&target->labels, $2);
176*4882a593Smuzhiyun 				merge_nodes(target, $4);
177*4882a593Smuzhiyun 			} else
178*4882a593Smuzhiyun 				ERROR(&@3, "Label or path %s not found", $3);
179*4882a593Smuzhiyun 			$$ = $1;
180*4882a593Smuzhiyun 		}
181*4882a593Smuzhiyun 	| devicetree DT_REF nodedef
182*4882a593Smuzhiyun 		{
183*4882a593Smuzhiyun 			struct node *target = get_node_by_ref($1, $2);
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 			if (target) {
186*4882a593Smuzhiyun 				merge_nodes(target, $3);
187*4882a593Smuzhiyun 			} else {
188*4882a593Smuzhiyun 				/*
189*4882a593Smuzhiyun 				 * We rely on the rule being always:
190*4882a593Smuzhiyun 				 *   versioninfo plugindecl memreserves devicetree
191*4882a593Smuzhiyun 				 * so $-1 is what we want (plugindecl)
192*4882a593Smuzhiyun 				 */
193*4882a593Smuzhiyun 				if ($<flags>-1 & DTSF_PLUGIN)
194*4882a593Smuzhiyun 					add_orphan_node($1, $3, $2);
195*4882a593Smuzhiyun 				else
196*4882a593Smuzhiyun 					ERROR(&@2, "Label or path %s not found", $2);
197*4882a593Smuzhiyun 			}
198*4882a593Smuzhiyun 			$$ = $1;
199*4882a593Smuzhiyun 		}
200*4882a593Smuzhiyun 	| devicetree DT_DEL_NODE DT_REF ';'
201*4882a593Smuzhiyun 		{
202*4882a593Smuzhiyun 			struct node *target = get_node_by_ref($1, $3);
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 			if (target)
205*4882a593Smuzhiyun 				delete_node(target);
206*4882a593Smuzhiyun 			else
207*4882a593Smuzhiyun 				ERROR(&@3, "Label or path %s not found", $3);
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 			$$ = $1;
211*4882a593Smuzhiyun 		}
212*4882a593Smuzhiyun 	| /* empty */
213*4882a593Smuzhiyun 		{
214*4882a593Smuzhiyun 			/* build empty node */
215*4882a593Smuzhiyun 			$$ = name_node(build_node(NULL, NULL), "");
216*4882a593Smuzhiyun 		}
217*4882a593Smuzhiyun 	;
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun nodedef:
220*4882a593Smuzhiyun 	  '{' proplist subnodes '}' ';'
221*4882a593Smuzhiyun 		{
222*4882a593Smuzhiyun 			$$ = build_node($2, $3);
223*4882a593Smuzhiyun 		}
224*4882a593Smuzhiyun 	;
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun proplist:
227*4882a593Smuzhiyun 	  /* empty */
228*4882a593Smuzhiyun 		{
229*4882a593Smuzhiyun 			$$ = NULL;
230*4882a593Smuzhiyun 		}
231*4882a593Smuzhiyun 	| proplist propdef
232*4882a593Smuzhiyun 		{
233*4882a593Smuzhiyun 			$$ = chain_property($2, $1);
234*4882a593Smuzhiyun 		}
235*4882a593Smuzhiyun 	;
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun propdef:
238*4882a593Smuzhiyun 	  DT_PROPNODENAME '=' propdata ';'
239*4882a593Smuzhiyun 		{
240*4882a593Smuzhiyun 			$$ = build_property($1, $3);
241*4882a593Smuzhiyun 		}
242*4882a593Smuzhiyun 	| DT_PROPNODENAME ';'
243*4882a593Smuzhiyun 		{
244*4882a593Smuzhiyun 			$$ = build_property($1, empty_data);
245*4882a593Smuzhiyun 		}
246*4882a593Smuzhiyun 	| DT_DEL_PROP DT_PROPNODENAME ';'
247*4882a593Smuzhiyun 		{
248*4882a593Smuzhiyun 			$$ = build_property_delete($2);
249*4882a593Smuzhiyun 		}
250*4882a593Smuzhiyun 	| DT_LABEL propdef
251*4882a593Smuzhiyun 		{
252*4882a593Smuzhiyun 			add_label(&$2->labels, $1);
253*4882a593Smuzhiyun 			$$ = $2;
254*4882a593Smuzhiyun 		}
255*4882a593Smuzhiyun 	;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun propdata:
258*4882a593Smuzhiyun 	  propdataprefix DT_STRING
259*4882a593Smuzhiyun 		{
260*4882a593Smuzhiyun 			$$ = data_merge($1, $2);
261*4882a593Smuzhiyun 		}
262*4882a593Smuzhiyun 	| propdataprefix arrayprefix '>'
263*4882a593Smuzhiyun 		{
264*4882a593Smuzhiyun 			$$ = data_merge($1, $2.data);
265*4882a593Smuzhiyun 		}
266*4882a593Smuzhiyun 	| propdataprefix '[' bytestring ']'
267*4882a593Smuzhiyun 		{
268*4882a593Smuzhiyun 			$$ = data_merge($1, $3);
269*4882a593Smuzhiyun 		}
270*4882a593Smuzhiyun 	| propdataprefix DT_REF
271*4882a593Smuzhiyun 		{
272*4882a593Smuzhiyun 			$$ = data_add_marker($1, REF_PATH, $2);
273*4882a593Smuzhiyun 		}
274*4882a593Smuzhiyun 	| propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
275*4882a593Smuzhiyun 		{
276*4882a593Smuzhiyun 			FILE *f = srcfile_relative_open($4.val, NULL);
277*4882a593Smuzhiyun 			struct data d;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 			if ($6 != 0)
280*4882a593Smuzhiyun 				if (fseek(f, $6, SEEK_SET) != 0)
281*4882a593Smuzhiyun 					die("Couldn't seek to offset %llu in \"%s\": %s",
282*4882a593Smuzhiyun 					    (unsigned long long)$6, $4.val,
283*4882a593Smuzhiyun 					    strerror(errno));
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 			d = data_copy_file(f, $8);
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 			$$ = data_merge($1, d);
288*4882a593Smuzhiyun 			fclose(f);
289*4882a593Smuzhiyun 		}
290*4882a593Smuzhiyun 	| propdataprefix DT_INCBIN '(' DT_STRING ')'
291*4882a593Smuzhiyun 		{
292*4882a593Smuzhiyun 			FILE *f = srcfile_relative_open($4.val, NULL);
293*4882a593Smuzhiyun 			struct data d = empty_data;
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 			d = data_copy_file(f, -1);
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 			$$ = data_merge($1, d);
298*4882a593Smuzhiyun 			fclose(f);
299*4882a593Smuzhiyun 		}
300*4882a593Smuzhiyun 	| propdata DT_LABEL
301*4882a593Smuzhiyun 		{
302*4882a593Smuzhiyun 			$$ = data_add_marker($1, LABEL, $2);
303*4882a593Smuzhiyun 		}
304*4882a593Smuzhiyun 	;
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun propdataprefix:
307*4882a593Smuzhiyun 	  /* empty */
308*4882a593Smuzhiyun 		{
309*4882a593Smuzhiyun 			$$ = empty_data;
310*4882a593Smuzhiyun 		}
311*4882a593Smuzhiyun 	| propdata ','
312*4882a593Smuzhiyun 		{
313*4882a593Smuzhiyun 			$$ = $1;
314*4882a593Smuzhiyun 		}
315*4882a593Smuzhiyun 	| propdataprefix DT_LABEL
316*4882a593Smuzhiyun 		{
317*4882a593Smuzhiyun 			$$ = data_add_marker($1, LABEL, $2);
318*4882a593Smuzhiyun 		}
319*4882a593Smuzhiyun 	;
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun arrayprefix:
322*4882a593Smuzhiyun 	DT_BITS DT_LITERAL '<'
323*4882a593Smuzhiyun 		{
324*4882a593Smuzhiyun 			unsigned long long bits;
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 			bits = $2;
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 			if ((bits !=  8) && (bits != 16) &&
329*4882a593Smuzhiyun 			    (bits != 32) && (bits != 64)) {
330*4882a593Smuzhiyun 				ERROR(&@2, "Array elements must be"
331*4882a593Smuzhiyun 				      " 8, 16, 32 or 64-bits");
332*4882a593Smuzhiyun 				bits = 32;
333*4882a593Smuzhiyun 			}
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 			$$.data = empty_data;
336*4882a593Smuzhiyun 			$$.bits = bits;
337*4882a593Smuzhiyun 		}
338*4882a593Smuzhiyun 	| '<'
339*4882a593Smuzhiyun 		{
340*4882a593Smuzhiyun 			$$.data = empty_data;
341*4882a593Smuzhiyun 			$$.bits = 32;
342*4882a593Smuzhiyun 		}
343*4882a593Smuzhiyun 	| arrayprefix integer_prim
344*4882a593Smuzhiyun 		{
345*4882a593Smuzhiyun 			if ($1.bits < 64) {
346*4882a593Smuzhiyun 				uint64_t mask = (1ULL << $1.bits) - 1;
347*4882a593Smuzhiyun 				/*
348*4882a593Smuzhiyun 				 * Bits above mask must either be all zero
349*4882a593Smuzhiyun 				 * (positive within range of mask) or all one
350*4882a593Smuzhiyun 				 * (negative and sign-extended). The second
351*4882a593Smuzhiyun 				 * condition is true if when we set all bits
352*4882a593Smuzhiyun 				 * within the mask to one (i.e. | in the
353*4882a593Smuzhiyun 				 * mask), all bits are one.
354*4882a593Smuzhiyun 				 */
355*4882a593Smuzhiyun 				if (($2 > mask) && (($2 | mask) != -1ULL))
356*4882a593Smuzhiyun 					ERROR(&@2, "Value out of range for"
357*4882a593Smuzhiyun 					      " %d-bit array element", $1.bits);
358*4882a593Smuzhiyun 			}
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 			$$.data = data_append_integer($1.data, $2, $1.bits);
361*4882a593Smuzhiyun 		}
362*4882a593Smuzhiyun 	| arrayprefix DT_REF
363*4882a593Smuzhiyun 		{
364*4882a593Smuzhiyun 			uint64_t val = ~0ULL >> (64 - $1.bits);
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 			if ($1.bits == 32)
367*4882a593Smuzhiyun 				$1.data = data_add_marker($1.data,
368*4882a593Smuzhiyun 							  REF_PHANDLE,
369*4882a593Smuzhiyun 							  $2);
370*4882a593Smuzhiyun 			else
371*4882a593Smuzhiyun 				ERROR(&@2, "References are only allowed in "
372*4882a593Smuzhiyun 					    "arrays with 32-bit elements.");
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 			$$.data = data_append_integer($1.data, val, $1.bits);
375*4882a593Smuzhiyun 		}
376*4882a593Smuzhiyun 	| arrayprefix DT_LABEL
377*4882a593Smuzhiyun 		{
378*4882a593Smuzhiyun 			$$.data = data_add_marker($1.data, LABEL, $2);
379*4882a593Smuzhiyun 		}
380*4882a593Smuzhiyun 	;
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun integer_prim:
383*4882a593Smuzhiyun 	  DT_LITERAL
384*4882a593Smuzhiyun 	| DT_CHAR_LITERAL
385*4882a593Smuzhiyun 	| '(' integer_expr ')'
386*4882a593Smuzhiyun 		{
387*4882a593Smuzhiyun 			$$ = $2;
388*4882a593Smuzhiyun 		}
389*4882a593Smuzhiyun 	;
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun integer_expr:
392*4882a593Smuzhiyun 	integer_trinary
393*4882a593Smuzhiyun 	;
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun integer_trinary:
396*4882a593Smuzhiyun 	  integer_or
397*4882a593Smuzhiyun 	| integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
398*4882a593Smuzhiyun 	;
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun integer_or:
401*4882a593Smuzhiyun 	  integer_and
402*4882a593Smuzhiyun 	| integer_or DT_OR integer_and { $$ = $1 || $3; }
403*4882a593Smuzhiyun 	;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun integer_and:
406*4882a593Smuzhiyun 	  integer_bitor
407*4882a593Smuzhiyun 	| integer_and DT_AND integer_bitor { $$ = $1 && $3; }
408*4882a593Smuzhiyun 	;
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun integer_bitor:
411*4882a593Smuzhiyun 	  integer_bitxor
412*4882a593Smuzhiyun 	| integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
413*4882a593Smuzhiyun 	;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun integer_bitxor:
416*4882a593Smuzhiyun 	  integer_bitand
417*4882a593Smuzhiyun 	| integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
418*4882a593Smuzhiyun 	;
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun integer_bitand:
421*4882a593Smuzhiyun 	  integer_eq
422*4882a593Smuzhiyun 	| integer_bitand '&' integer_eq { $$ = $1 & $3; }
423*4882a593Smuzhiyun 	;
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun integer_eq:
426*4882a593Smuzhiyun 	  integer_rela
427*4882a593Smuzhiyun 	| integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
428*4882a593Smuzhiyun 	| integer_eq DT_NE integer_rela { $$ = $1 != $3; }
429*4882a593Smuzhiyun 	;
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun integer_rela:
432*4882a593Smuzhiyun 	  integer_shift
433*4882a593Smuzhiyun 	| integer_rela '<' integer_shift { $$ = $1 < $3; }
434*4882a593Smuzhiyun 	| integer_rela '>' integer_shift { $$ = $1 > $3; }
435*4882a593Smuzhiyun 	| integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
436*4882a593Smuzhiyun 	| integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
437*4882a593Smuzhiyun 	;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun integer_shift:
440*4882a593Smuzhiyun 	  integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
441*4882a593Smuzhiyun 	| integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
442*4882a593Smuzhiyun 	| integer_add
443*4882a593Smuzhiyun 	;
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun integer_add:
446*4882a593Smuzhiyun 	  integer_add '+' integer_mul { $$ = $1 + $3; }
447*4882a593Smuzhiyun 	| integer_add '-' integer_mul { $$ = $1 - $3; }
448*4882a593Smuzhiyun 	| integer_mul
449*4882a593Smuzhiyun 	;
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun integer_mul:
452*4882a593Smuzhiyun 	  integer_mul '*' integer_unary { $$ = $1 * $3; }
453*4882a593Smuzhiyun 	| integer_mul '/' integer_unary
454*4882a593Smuzhiyun 		{
455*4882a593Smuzhiyun 			if ($3 != 0) {
456*4882a593Smuzhiyun 				$$ = $1 / $3;
457*4882a593Smuzhiyun 			} else {
458*4882a593Smuzhiyun 				ERROR(&@$, "Division by zero");
459*4882a593Smuzhiyun 				$$ = 0;
460*4882a593Smuzhiyun 			}
461*4882a593Smuzhiyun 		}
462*4882a593Smuzhiyun 	| integer_mul '%' integer_unary
463*4882a593Smuzhiyun 		{
464*4882a593Smuzhiyun 			if ($3 != 0) {
465*4882a593Smuzhiyun 				$$ = $1 % $3;
466*4882a593Smuzhiyun 			} else {
467*4882a593Smuzhiyun 				ERROR(&@$, "Division by zero");
468*4882a593Smuzhiyun 				$$ = 0;
469*4882a593Smuzhiyun 			}
470*4882a593Smuzhiyun 		}
471*4882a593Smuzhiyun 	| integer_unary
472*4882a593Smuzhiyun 	;
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun integer_unary:
475*4882a593Smuzhiyun 	  integer_prim
476*4882a593Smuzhiyun 	| '-' integer_unary { $$ = -$2; }
477*4882a593Smuzhiyun 	| '~' integer_unary { $$ = ~$2; }
478*4882a593Smuzhiyun 	| '!' integer_unary { $$ = !$2; }
479*4882a593Smuzhiyun 	;
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun bytestring:
482*4882a593Smuzhiyun 	  /* empty */
483*4882a593Smuzhiyun 		{
484*4882a593Smuzhiyun 			$$ = empty_data;
485*4882a593Smuzhiyun 		}
486*4882a593Smuzhiyun 	| bytestring DT_BYTE
487*4882a593Smuzhiyun 		{
488*4882a593Smuzhiyun 			$$ = data_append_byte($1, $2);
489*4882a593Smuzhiyun 		}
490*4882a593Smuzhiyun 	| bytestring DT_LABEL
491*4882a593Smuzhiyun 		{
492*4882a593Smuzhiyun 			$$ = data_add_marker($1, LABEL, $2);
493*4882a593Smuzhiyun 		}
494*4882a593Smuzhiyun 	;
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun subnodes:
497*4882a593Smuzhiyun 	  /* empty */
498*4882a593Smuzhiyun 		{
499*4882a593Smuzhiyun 			$$ = NULL;
500*4882a593Smuzhiyun 		}
501*4882a593Smuzhiyun 	| subnode subnodes
502*4882a593Smuzhiyun 		{
503*4882a593Smuzhiyun 			$$ = chain_node($1, $2);
504*4882a593Smuzhiyun 		}
505*4882a593Smuzhiyun 	| subnode propdef
506*4882a593Smuzhiyun 		{
507*4882a593Smuzhiyun 			ERROR(&@2, "Properties must precede subnodes");
508*4882a593Smuzhiyun 			YYERROR;
509*4882a593Smuzhiyun 		}
510*4882a593Smuzhiyun 	;
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun subnode:
513*4882a593Smuzhiyun 	  DT_PROPNODENAME nodedef
514*4882a593Smuzhiyun 		{
515*4882a593Smuzhiyun 			$$ = name_node($2, $1);
516*4882a593Smuzhiyun 		}
517*4882a593Smuzhiyun 	| DT_DEL_NODE DT_PROPNODENAME ';'
518*4882a593Smuzhiyun 		{
519*4882a593Smuzhiyun 			$$ = name_node(build_node_delete(), $2);
520*4882a593Smuzhiyun 		}
521*4882a593Smuzhiyun 	| DT_LABEL subnode
522*4882a593Smuzhiyun 		{
523*4882a593Smuzhiyun 			add_label(&$2->labels, $1);
524*4882a593Smuzhiyun 			$$ = $2;
525*4882a593Smuzhiyun 		}
526*4882a593Smuzhiyun 	;
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun %%
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun void yyerror(char const *s)
531*4882a593Smuzhiyun {
532*4882a593Smuzhiyun 	ERROR(&yylloc, "%s", s);
533*4882a593Smuzhiyun }
534