|
|
1.1 root 1: %{
2: #include "draw_dag.h"
3: #include "dag.h"
4: #define MIN_RANK_SEP 4
5:
6: static pair_t* nodelist;
7: static DAG_edge_t* this_edge;
8: static boolean is_ordered = false;
9:
10: int Syntax_error;
11: DAG_node_t Reset_node,Default_node,Proto_node;
12: DAG_edge_t Reset_edge,Default_edge;
13: static boolean set_pointsize,set_label,set_shape,set_color,set_xsize,set_ysize;
14:
15: static void teardown (pair_t *e) {
16: pair_t *f;
17: while (e) {
18: f = e->next;
19: delete e;
20: e = f;
21: }
22: }
23:
24: static void init_proto() {
25: Proto_node = Default_node;
26: set_pointsize = set_label = set_shape = set_color = set_xsize = set_ysize = false;
27: }
28:
29: static void apply_proto(DAG_node_t *np) {
30: /* label setting has precedence over size! */
31: if (set_pointsize) np->setpointsize(Proto_node.pointsize);
32: if (set_label) np->setlabel(Proto_node.label.type,Proto_node.label.value);
33: if (set_shape) np->setshape(Proto_node.shape.type,Proto_node.shape.value);
34: if (set_color) np->setcolor(Proto_node.color);
35: if (set_xsize) np->setxsize(Proto_node.xsize);
36: if (set_ysize) np->setysize(Proto_node.ysize);
37: np->autosize();
38: }
39:
40: static void install_proto() {
41: Proto_node.autosize();
42: for (pair_t* p = nodelist; p; p = p->next)
43: apply_proto(Node[p->node]);
44: }
45:
46: /* append list1 to list2 */
47: static DAG_edge_t* append(DAG_edge_t *list1, DAG_edge_t *list2) {
48: if (!list2) panic("null list2");
49: DAG_edge_t *e,*f;
50: e = list2;
51: while (f = e->nextof()) e = f;
52: e->next = (edge_t*) list1;
53: return list2;
54: }
55:
56: /* create a new set of same rank nodes within the Options struct */
57: static int* &newset() {
58: const int hunksize = 16;
59: if (!Options.same_nodes)
60: Options.same_nodes = new int*[hunksize];
61: else if (!(Options.n_same_nodes % hunksize))
62: Options.same_nodes = (int**)realloc((char*)Options.same_nodes,
63: (Options.n_same_nodes + hunksize + 1)*sizeof(int*));
64: Options.same_nodes[Options.n_same_nodes] = 0;
65: return(Options.same_nodes[Options.n_same_nodes++]);
66: }
67:
68: /* take the union of same rank nodes */
69: overload set_union;
70: static void set_union (int* &ptr, pair_t *nlist) {
71: pair_t *e;
72: int olen = 0, nlen = 0;
73: for (e = nlist; e; e = e->next) nlen++;
74: if (!nlen) return;
75: if (ptr) {
76: while (ptr[olen++] >= 0);
77: ptr = (int*)realloc((char*)ptr,(nlen+olen)*sizeof(int));
78: }
79: else ptr = new int[nlen + 1];
80:
81: for (e = nlist; e; e = e->next)
82: ptr[olen++] = e->node;
83: ptr[olen] = -1;
84: }
85:
86: static void set_union(int* &ptr, DAG_edge_t *elist) {
87: pair_t *p = 0;
88: while (elist) {
89: p = new pair_t(elist->node,p);
90: elist = elist->nextof();
91: }
92: set_union(ptr,p);
93: teardown(p);
94: }
95:
96: static void make_invis_edge(int fromnode,int tonode) {
97: DAG_edge_t *e = new DAG_edge_t();
98: e->ink = invis_ink;
99: e->node = tonode;
100: e->next = Edge[fromnode];
101: Edge[fromnode] = e;
102: }
103:
104: static void enter_edgelist(int tailnode, DAG_edge_t* elist) {
105: DAG_edge_t *e;
106: if (is_ordered) {
107: set_union(newset(),elist);
108: for (e = elist; e->nextof(); e = e->nextof())
109: make_invis_edge(e->node,e->nextof()->node);
110: is_ordered = false;
111: }
112: Edge[tailnode] = append(Edge[tailnode],elist);
113: }
114:
115: static void enter_backedgelist(int headnode, DAG_edge_t* elist) {
116: DAG_edge_t *e = elist;
117: while (e) {
118: DAG_edge_t *f = e->nextof();
119: e->next = 0;
120: e->flipped = true;
121: int tailnode = e->node;
122: e->node = headnode;
123: Edge[tailnode] = append(Edge[tailnode],e);
124: e = f;
125: }
126: }
127:
128: static void enter_pathlist(int tailnode, DAG_edge_t* elist) {
129: DAG_edge_t *e,*f;
130: e = elist;
131: while (e) {
132: f = e;
133: e = e->nextof();
134: f->next = Edge[tailnode];
135: Edge[tailnode] = f;
136: tailnode = f->node;
137: }
138: is_ordered = false;
139: }
140:
141: static void enter_backpathlist(int headnode, DAG_edge_t *elist) {
142: DAG_edge_t *e = elist;
143: while (e) {
144: DAG_edge_t *f = e->nextof();
145: e->next = 0;
146: e->flipped = true;
147: int tailnode = e->node;
148: e->node = headnode;
149: Edge[tailnode] = append(Edge[tailnode],e);
150: e = f;
151: headnode = tailnode;
152: }
153: }
154:
155: %}
156: %union {
157: char *s;
158: int i;
159: pair_t *p; // for node lists
160: DAG_edge_t *e; // for edge lists
161: }
162: %token <i> AS BACKEDGE BACKPATH COLOR DASHED DOTTED DRAW EDGE EDGES EQUALLY
163: %token <i> EXACTLY FROM HEIGHT INVIS LABEL MAXIMUM MINIMUM NODES ORDERED
164: %token <i> PATH POINTSIZE RANK RANKS SAME SEPARATE SOLID TO WEIGHT WIDTH
165: %token <s> STRING DESC
166: %type <i> nitem eitem inkval nname intval tailnode
167: %type <e> head_list head tohead
168: %type <p> nlist
169: %%
170: program : stmtlist
171: {make_drawing();}
172: | error
173: ;
174:
175: stmtlist : stmtlist stmt
176: | /*empty*/
177: ;
178:
179: stmt : drawstmt
180: | edgestmt
181: | ctlstmt
182: ;
183:
184: drawstmt : DRAW nlist {init_proto(); nodelist = $2;} ndesc ';'
185: {install_proto(); teardown($2);}
186: | DRAW NODES {init_proto(); nodelist = 0;} ndesc ';'
187: {apply_proto(&Default_node);}
188: | DRAW EDGES {this_edge = &Default_edge;} edesc ';'
189: ;
190:
191: nlist : nlist nname
192: {$$ = new pair_t($2,$1);}
193: | nlist ',' nname
194: {$$ = new pair_t($3,$1);}
195: | nname
196: {$$ = new pair_t($1,(pair_t*)0);}
197: ;
198:
199:
200: ndesc : nitem
201: | ndesc nitem
202: ;
203:
204: nitem : WIDTH STRING
205: {
206: Proto_node.setxsize((int)(Resolution*atof($2)));
207: set_xsize = true;
208: }
209:
210: | HEIGHT STRING
211: {
212: Proto_node.setysize((int)(Resolution*atof($2)));
213: set_ysize = true;
214: }
215: | POINTSIZE intval
216: {
217: Proto_node.setpointsize($2);
218: set_pointsize = true;
219: }
220: | LABEL STRING
221: {
222: Proto_node.setlabel(STRING,$2);
223: set_label = true;
224: }
225: | LABEL DESC
226: {
227: Proto_node.setlabel(DESC,$2);
228: set_label = true;
229: }
230: | AS DESC
231: {
232: Proto_node.setshape(DESC,$2);
233: set_shape = true;
234: }
235: | AS STRING
236: {
237: Proto_node.setshape(STRING,$2);
238: set_shape = true;
239: }
240: | COLOR STRING
241: {
242: Proto_node.setcolor($2);
243: set_color = true;
244: }
245: ;
246:
247: edgestmt : ORDERED {is_ordered = true;} plainedgestmt
248: | plainedgestmt
249: ;
250:
251: plainedgestmt : nname ';'
252: | nname head_list ';'
253: {enter_edgelist($1,$2);}
254: | EDGE tailnode head_list ';'
255: {enter_edgelist($2,$3);}
256: | BACKEDGE tailnode head_list ';'
257: {enter_backedgelist($2,$3);}
258: | PATH tailnode head_list ';'
259: {enter_pathlist($2,$3);}
260: | BACKPATH tailnode head_list ';'
261: {enter_backpathlist($2,$3);}
262: | ';' /* empty statement */
263: ;
264:
265: tailnode : nname
266: | FROM nname
267: {$$ = $2;}
268:
269: head_list : tohead
270: | head_list tohead
271: {$$ = append($2,$1);}
272: | head_list ',' tohead
273: {$$ = append($3,$1);}
274: ;
275:
276: tohead : head
277: | TO head
278: {$$ = $2;}
279: ;
280:
281: head : nname
282: {
283: this_edge = new DAG_edge_t();
284: *this_edge = Default_edge;
285: this_edge->node = $1;
286: }
287: edesc
288: {$$ = this_edge;}
289: | nname
290: {
291: this_edge = new DAG_edge_t();
292: *this_edge = Default_edge;
293: this_edge->node = $1;
294: $$ = this_edge;
295: }
296: ;
297:
298: edesc : eitem
299: | edesc eitem
300: ;
301:
302: eitem : WEIGHT intval
303: {this_edge->setweight($2);}
304: | LABEL DESC
305: {this_edge->setlabel(DESC,newstring($2));}
306: | LABEL STRING
307: {this_edge->setlabel(STRING,newstring($2));}
308: | POINTSIZE intval
309: {this_edge->setpointsize($2);}
310: | COLOR STRING
311: {this_edge->setcolor(newstring($2));}
312: | inkval
313: {this_edge->setink($1);}
314: ;
315:
316: ctlstmt : SEPARATE seplist ';'
317: | MINIMUM RANK nlist ';'
318: {set_union(Options.source_nodes,$3);teardown($3);}
319: | MAXIMUM RANK nlist ';'
320: {set_union(Options.sink_nodes,$3);teardown($3);}
321: | SAME RANK nlist ';'
322: {set_union(newset(),$3);teardown($3);}
323: ;
324:
325: seplist : seplist sepitem
326: | /* empty */
327: ;
328:
329: sepitem : NODES STRING
330: {
331: Options.nodesep = max(1,round(Resolution*atof($2)));
332: }
333: | RANKS STRING EXACTLY
334: {
335: Options.ranksep = max(MIN_RANK_SEP,round(Resolution*atof($2)));
336: Options.rankadjust = 2;
337: }
338:
339: | RANKS STRING EQUALLY
340: {
341: Options.ranksep = max(MIN_RANK_SEP,round(Resolution*atof($2)));
342: Options.rankadjust = 1;
343: }
344: | RANKS EQUALLY
345: {
346: Options.rankadjust = 1;
347: }
348: | RANKS STRING
349: {
350: Options.ranksep = max(MIN_RANK_SEP,round(Resolution*atof($2)));
351: }
352: ;
353:
354: inkval : SOLID
355: {$$ = solid_ink;}
356: | DASHED
357: {$$ = dashed_ink;}
358: | DOTTED
359: {$$ = dotted_ink;}
360: | INVIS
361: {$$ = invis_ink;}
362: ;
363:
364: nname : STRING
365: {$$ = node_lookup($1);}
366: ;
367:
368: intval : STRING
369: {$$ = atoi($1);}
370: ;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.