Graphviz 13.0.0~dev.20241220.2304
Loading...
Searching...
No Matches
grammar.y
Go to the documentation of this file.
1
5/*************************************************************************
6 * Copyright (c) 2011 AT&T Intellectual Property
7 * All rights reserved. This program and the accompanying materials
8 * are made available under the terms of the Eclipse Public License v1.0
9 * which accompanies this distribution, and is available at
10 * https://www.eclipse.org/legal/epl-v10.html
11 *
12 * Contributors: Details at https://graphviz.org
13 *************************************************************************/
14
15%require "3.0"
16
17 /* By default, Bison emits a parser using symbols prefixed with "yy". Graphviz
18 * contains multiple Bison-generated parsers, so we alter this prefix to avoid
19 * symbol clashes.
20 */
21%define api.prefix {aag}
22%code requires {
23#include <cghdr.h>
24#include <util/agxbuf.h>
25
26struct gstack_s;
27
28struct aagextra_s {
29 int dummy; /* struct must not be empty */
30 /* Common */
31 /* Parser */
32 /* Lexer */
33};
34
35}
36
37%{
38
39#include <stdbool.h>
40#include <stdio.h>
41#include <cghdr.h>
42#include <stdlib.h>
43#include <util/alloc.h>
44#include <util/streq.h>
45#include <util/unreachable.h>
46
47extern void aagerror(const char*);
48
49static const char Key[] = "key";
50static int SubgraphDepth = 0;
51
52typedef union s { /* possible items in generic list */
53 Agnode_t *n;
55 Agedge_t *e;
56 Agsym_t *asym; /* bound attribute */
57 char *name; /* unbound attribute */
58 struct item_s *list; /* list-of-lists (for edgestmt) */
59} val_t;
60
61typedef struct item_s { /* generic list */
62 int tag; /* T_node, T_subgraph, T_edge, T_attr */
63 val_t u; /* primary element */
64 char *str; /* secondary value - port or attr value */
65 struct item_s *next;
66} item;
67
68typedef struct list_s { /* maintain head and tail ptrs for fast append */
69 item *first;
70 item *last;
71} list_t;
72
73typedef struct gstack_s {
74 Agraph_t *g;
77 struct gstack_s *down;
78} gstack_t;
79
80/* functions */
81static void appendnode(char *name, char *port, char *sport);
82static void attrstmt(int tkind, char *macroname);
83static void startgraph(char *name, bool directed, bool strict);
84static void getedgeitems(void);
85static void newedge(Agnode_t *t, char *tport, Agnode_t *h, char *hport, char *key);
86static void edgerhs(Agnode_t *n, char *tport, item *hlist, char *key);
87static void appendattr(char *name, char *value);
88static void bindattrs(int kind);
89static void applyattrs(void *obj);
90static void endgraph(void);
91static void endnode(void);
92static void endedge(void);
93static void freestack(void);
94static char* concat(char*, char*);
95static char* concatPort(char*, char*);
96
97static void opensubg(char *name);
98static void closesubg(void);
99
100/* global */
101static Agraph_t *G; /* top level graph */
102static Agdisc_t *Disc; /* discipline passed to agread or agconcat */
103static gstack_t *S;
104
105%}
106
107%union {
108 int i;
109 char *str;
110 struct Agnode_s *n;
111}
112
114 /* T_list, T_attr are internal tags, not really tokens */
115%token T_list T_attr
116%token <str> T_atom T_qatom
117
118%type <i> optstrict graphtype rcompound attrtype
119%type <str> optsubghdr optgraphname optmacroname atom qatom
120
121
122%%
123
124graph : hdr body {freestack(); endgraph();}
125 | error {if (G) {freestack(); endgraph(); agclose(G); G = Ag_G_global = NULL;}}
126 | /* empty */
127 ;
128
129body : '{' optstmtlist '}' ;
130
131hdr : optstrict graphtype optgraphname {startgraph($3,$2 != 0,$1 != 0);}
132 ;
133
134optgraphname: atom {$$=$1;} | /* empty */ {$$=0;} ;
135
136optstrict : T_strict {$$=1;} | /* empty */ {$$=0;} ;
137
138graphtype : T_graph {$$ = 0;} | T_digraph {$$ = 1;} ;
139
140optstmtlist : stmtlist | /* empty */ ;
141
142stmtlist : stmtlist stmt | stmt ;
143
144optsemi : ';' | ;
145
146stmt : attrstmt optsemi
147 | compound optsemi
148 ;
149
150compound : simple rcompound optattr
151 {if ($2) endedge(); else endnode();}
152 ;
153
154simple : nodelist | subgraph ;
155
157 | /* empty */ {$$ = 0;}
158 ;
159
160
161nodelist : node | nodelist ',' node ;
162
164 | atom ':' atom {appendnode($1,$3,NULL);}
165 | atom ':' atom ':' atom {appendnode($1,$3,$5);}
166 ;
167
168attrstmt : attrtype optmacroname attrlist {attrstmt($1,$2);}
170 ;
171
172attrtype : T_graph {$$ = T_graph;}
175 ;
176
177optmacroname : atom '=' {$$ = $1;}
178 | /* empty */ {$$ = NULL; }
179 ;
180
181optattr : attrlist | /* empty */ ;
182
183attrlist : optattr '[' optattrdefs ']' ;
184
185optattrdefs : optattrdefs attrdefs
186 | /* empty */ ;
187
188attrdefs : attrassignment optseparator
189 ;
190
191attrassignment : atom '=' atom {appendattr($1,$3);}
192 ;
193
194graphattrdefs : attrassignment
195 ;
196
197subgraph : optsubghdr {opensubg($1);} body {closesubg();}
198 ;
199
200optsubghdr : T_subgraph atom {$$=$2;}
202 | /* empty */ {$$=NULL;}
203 ;
204
205optseparator : ';' | ',' | /*empty*/ ;
206
207atom : T_atom {$$ = $1;}
208 | qatom {$$ = $1;}
209 ;
210
213 ;
214%%
215
216static item *newitem(int tag, void *p0, char *p1)
217{
218 item *rv = gv_alloc(sizeof(item));
219 rv->tag = tag;
220 rv->u.name = p0;
221 rv->str = p1;
222 return rv;
223}
224
225static item *cons_node(Agnode_t *n, char *port)
226 { return newitem(T_node,n,port); }
227
228static item *cons_attr(char *name, char *value)
229 { return newitem(T_atom,name,value); }
230
231static item *cons_list(item *list)
232 { return newitem(T_list,list,NULL); }
233
234static item *cons_subg(Agraph_t *subg)
235 { return newitem(T_subgraph,subg,NULL); }
236
237static gstack_t *push(gstack_t *s, Agraph_t *subg) {
238 gstack_t *rv = gv_alloc(sizeof(gstack_t));
239 rv->down = s;
240 rv->g = subg;
241 return rv;
242}
243
245{
246 gstack_t *rv;
247 rv = s->down;
248 free(s);
249 return rv;
250}
251
252static void delete_items(item *ilist)
253{
254 item *p,*pn;
255
256 for (p = ilist; p; p = pn) {
257 pn = p->next;
258 if (p->tag == T_list) delete_items(p->u.list);
259 if (p->tag == T_atom) agstrfree(G,p->str);
260 free(p);
261 }
262}
263
264static void deletelist(list_t *list)
265{
266 delete_items(list->first);
267 list->first = list->last = NULL;
268}
269
270static void listapp(list_t *list, item *v)
271{
272 if (list->last) list->last->next = v;
273 list->last = v;
274 if (list->first == NULL) list->first = v;
275}
276
277
278/* attrs */
279static void appendattr(char *name, char *value)
280{
281 item *v;
282
283 assert(value != NULL);
284 v = cons_attr(name,value);
285 listapp(&S->attrlist, v);
286}
287
288static void bindattrs(int kind)
289{
290 item *aptr;
291 char *name;
292
293 for (aptr = S->attrlist.first; aptr; aptr = aptr->next) {
294 assert(aptr->tag == T_atom); /* signifies unbound attr */
295 name = aptr->u.name;
296 if (kind == AGEDGE && streq(name,Key)) continue;
297 if ((aptr->u.asym = agattr(S->g,kind,name,NULL)) == NULL)
298 aptr->u.asym = agattr(S->g,kind,name,"");
299 aptr->tag = T_attr; /* signifies bound attr */
300 agstrfree(G,name);
301 }
302}
303
304/* attach node/edge specific attributes */
305static void applyattrs(void *obj)
306{
307 item *aptr;
308
309 for (aptr = S->attrlist.first; aptr; aptr = aptr->next) {
310 if (aptr->tag == T_attr) {
311 if (aptr->u.asym) {
312 agxset(obj,aptr->u.asym,aptr->str);
313 }
314 }
315 else {
316 assert(AGTYPE(obj) == AGINEDGE || AGTYPE(obj) == AGOUTEDGE);
317 assert(aptr->tag == T_atom);
318 assert(streq(aptr->u.name,Key));
319 }
320 }
321}
322
323static void nomacros(void)
324{
325 agwarningf("attribute macros not implemented");
326}
327
328/* attrstmt:
329 * First argument is always attrtype, so switch covers all cases.
330 * This function is used to handle default attribute value assignment.
331 */
332static void attrstmt(int tkind, char *macroname)
333{
334 item *aptr;
335 int kind = 0;
336 Agsym_t* sym;
337
338 /* creating a macro def */
339 if (macroname) nomacros();
340 /* invoking a macro def */
341 for (aptr = S->attrlist.first; aptr; aptr = aptr->next)
342 if (aptr->str == NULL) nomacros();
343
344 switch(tkind) {
345 case T_graph: kind = AGRAPH; break;
346 case T_node: kind = AGNODE; break;
347 case T_edge: kind = AGEDGE; break;
348 default: UNREACHABLE();
349 }
350 bindattrs(kind); /* set up defaults for new attributes */
351 for (aptr = S->attrlist.first; aptr; aptr = aptr->next) {
352 /* If the tag is still T_atom, aptr->u.asym has not been set */
353 if (aptr->tag == T_atom) continue;
354 if (!aptr->u.asym->fixed || S->g != G)
355 sym = agattr(S->g,kind,aptr->u.asym->name,aptr->str);
356 else
357 sym = aptr->u.asym;
358 if (S->g == G)
359 sym->print = true;
360 }
361 deletelist(&S->attrlist);
362}
363
364/* nodes */
365
366static void appendnode(char *name, char *port, char *sport)
367{
368 item *elt;
369
370 if (sport) {
371 port = concatPort (port, sport);
372 }
373 elt = cons_node(agnode(S->g, name, 1), port);
374 listapp(&S->nodelist, elt);
375 agstrfree(G,name);
376}
377
378/* apply current optional attrs to nodelist and clean up lists */
379/* what's bad is that this could also be endsubg. also, you can't
380clean up S->subg in closesubg() because S->subg might be needed
381to construct edges. these are the sort of notes you write to yourself
382in the future. */
383static void endnode(void)
384{
385 item *ptr;
386
388 for (ptr = S->nodelist.first; ptr; ptr = ptr->next)
389 applyattrs(ptr->u.n);
390 deletelist(&S->nodelist);
391 deletelist(&S->attrlist);
392 deletelist(&S->edgelist);
393 S->subg = 0; /* notice a pattern here? :-( */
394}
395
396/* edges - store up node/subg lists until optional edge key can be seen */
397
398static void getedgeitems(void)
399{
400 item *v = 0;
401
402 if (S->nodelist.first) {
403 v = cons_list(S->nodelist.first);
404 S->nodelist.first = S->nodelist.last = NULL;
405 }
406 else {if (S->subg) v = cons_subg(S->subg); S->subg = 0;}
407 /* else nil append */
408 if (v) listapp(&S->edgelist, v);
409}
410
411static void endedge(void)
412{
413 char *key;
414 item *aptr,*tptr,*p;
415
416 Agnode_t *t;
417 Agraph_t *subg;
418
420
421 /* look for "key" pseudo-attribute */
422 key = NULL;
423 for (aptr = S->attrlist.first; aptr; aptr = aptr->next) {
424 if (aptr->tag == T_atom && streq(aptr->u.name,Key))
425 key = aptr->str;
426 }
427
428 /* can make edges with node lists or subgraphs */
429 for (p = S->edgelist.first; p->next; p = p->next) {
430 if (p->tag == T_subgraph) {
431 subg = p->u.subg;
432 for (t = agfstnode(subg); t; t = agnxtnode(subg,t))
433 edgerhs(agsubnode(S->g, t, 0), NULL, p->next, key);
434 }
435 else {
436 for (tptr = p->u.list; tptr; tptr = tptr->next)
437 edgerhs(tptr->u.n,tptr->str,p->next,key);
438 }
439 }
440 deletelist(&S->nodelist);
441 deletelist(&S->edgelist);
442 deletelist(&S->attrlist);
443 S->subg = 0;
444}
445
446/* concat:
447 */
448static char*
449concat (char* s1, char* s2)
450{
451 char* s;
452 char buf[BUFSIZ];
453 char* sym;
454 size_t len = strlen(s1) + strlen(s2) + 1;
455
456 if (len <= BUFSIZ) sym = buf;
457 else sym = gv_alloc(len);
458 strcpy(sym,s1);
459 strcat(sym,s2);
460 s = agstrdup (G,sym);
461 agstrfree (G,s1);
462 agstrfree (G,s2);
463 if (sym != buf) free (sym);
464 return s;
465}
466
467static char*
468concatPort (char* s1, char* s2)
469{
470 agxbuf buf = {0};
471
472 agxbprint(&buf, "%s:%s", s1, s2);
473 char *s = agstrdup(G, agxbuse(&buf));
474 agstrfree (G,s1);
475 agstrfree (G,s2);
476 agxbfree(&buf);
477 return s;
478}
479
480
481static void edgerhs(Agnode_t *tail, char *tport, item *hlist, char *key)
482{
483 Agnode_t *head;
484 Agraph_t *subg;
485 item *hptr;
486
487 if (hlist->tag == T_subgraph) {
488 subg = hlist->u.subg;
489 for (head = agfstnode(subg); head; head = agnxtnode(subg,head))
490 newedge(tail, tport, agsubnode(S->g, head, 0), NULL, key);
491 }
492 else {
493 for (hptr = hlist->u.list; hptr; hptr = hptr->next)
494 newedge(tail, tport, agsubnode(S->g, hptr->u.n, 0), hptr->str, key);
495 }
496}
497
498static void mkport(Agedge_t *e, char *name, char *val)
499{
500 Agsym_t *attr;
501 if (val) {
502 if ((attr = agattr(S->g,AGEDGE,name,NULL)) == NULL)
503 attr = agattr(S->g,AGEDGE,name,"");
504 agxset(e,attr,val);
505 }
506}
507
508static void newedge(Agnode_t *t, char *tport, Agnode_t *h, char *hport, char *key)
509{
510 Agedge_t *e;
511
512 e = agedge(S->g, t, h, key, 1);
513 if (e) { /* can fail if graph is strict and t==h */
514 char *tp = tport;
515 char *hp = hport;
516 if (agtail(e) != aghead(e) && aghead(e) == t) {
517 /* could happen with an undirected edge */
518 char *temp;
519 temp = tp; tp = hp; hp = temp;
520 }
521 mkport(e,TAILPORT_ID,tp);
522 mkport(e,HEADPORT_ID,hp);
523 applyattrs(e);
524 }
525}
526
527/* graphs and subgraphs */
528
529
530static void startgraph(char *name, bool directed, bool strict)
531{
532 if (G == NULL) {
533 SubgraphDepth = 0;
534 Agdesc_t req = {.directed = directed, .strict = strict, .maingraph = true};
535 Ag_G_global = G = agopen(name,req,Disc);
536 }
537 else {
538 Ag_G_global = G;
539 }
540 S = push(S,G);
541 agstrfree(NULL,name);
542}
543
544static void endgraph(void)
545{
546 aglexeof();
548}
549
550static void opensubg(char *name)
551{
552 if (++SubgraphDepth >= YYMAXDEPTH/2) {
553 agerrorf("subgraphs nested more than %d deep", YYMAXDEPTH);
554 }
555 S = push(S, agsubg(S->g, name, 1));
556 agstrfree(G,name);
557}
558
559static void closesubg(void)
560{
561 Agraph_t *subg = S->g;
563 S = pop(S);
564 S->subg = subg;
565 assert(subg);
566}
567
568static void freestack(void)
569{
570 while (S) {
571 deletelist(&S->nodelist);
572 deletelist(&S->attrlist);
573 deletelist(&S->edgelist);
574 S = pop(S);
575 }
576}
577
578extern FILE *aagin;
580{
581 aagin = chan;
582 G = g;
584 Disc = (disc? disc : &AgDefaultDisc);
585 aglexinit(Disc, chan);
586 aagparse();
587 if (Ag_G_global == NULL) aglexbad();
588 return Ag_G_global;
589}
590
591Agraph_t *agread(void *fp, Agdisc_t *disc) {return agconcat(NULL,fp,disc); }
592
static void agxbfree(agxbuf *xb)
free any malloced resources
Definition agxbuf.h:78
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
Definition agxbuf.h:234
static WUR char * agxbuse(agxbuf *xb)
Definition agxbuf.h:307
Memory allocation wrappers that exit on failure.
static void * gv_alloc(size_t size)
Definition alloc.h:47
cgraph.h additions
void aglexbad(void)
Definition scan.c:2402
void aglexinit(Agdisc_t *disc, void *ifile)
Definition scan.c:2421
Agraph_t * Ag_G_global
Definition graph.c:24
int aagparse(void)
void aglexeof(void)
Definition scan.c:2400
static Agnode_t * pop(void)
Definition ccomps.c:231
#define head
Definition dthdr.h:15
static Dtdisc_t disc
Definition exparse.y:209
#define S
Definition expr.h:72
#define G
Definition gdefs.h:7
static double len(glCompPoint p)
Definition glutils.c:150
#define YYMAXDEPTH
Definition gmlparse.c:1147
void free(void *)
NAME attrlist
Definition gmlparse.y:291
static const char Key[]
Definition grammar.c:90
#define T_atom
Definition grammar.c:243
static Agdisc_t * Disc
Definition grammar.c:143
struct list_s list_t
#define T_attr
Definition grammar.c:242
static int SubgraphDepth
Definition grammar.c:91
struct item_s item
void aagerror(const char *)
Definition scan.l:147
#define T_strict
Definition grammar.c:239
struct gstack_s gstack_t
union s val_t
#define T_graph
Definition grammar.c:234
#define T_list
Definition grammar.c:241
#define T_edgeop
Definition grammar.c:240
atom $5
Definition grammar.y:165
static void freestack(void)
Definition grammar.y:568
body
Definition grammar.y:197
static gstack_t * push(gstack_t *s, Agraph_t *subg)
Definition grammar.y:237
static void appendattr(char *name, char *value)
Definition grammar.y:279
static char * concat(char *s1, char *s2)
Definition grammar.y:449
T_subgraph
Definition grammar.y:201
hdr $2
Definition grammar.y:131
static void delete_items(item *ilist)
Definition grammar.y:252
static void bindattrs(int kind)
Definition grammar.y:288
node NULL
Definition grammar.y:163
simple
Definition grammar.y:156
static void newedge(Agnode_t *t, char *tport, Agnode_t *h, char *hport, char *key)
Definition grammar.y:508
atom $3
Definition grammar.y:164
graphattrdefs
Definition grammar.y:169
static void applyattrs(void *obj)
Definition grammar.y:305
static void getedgeitems(void)
Definition grammar.y:398
static item * cons_attr(char *name, char *value)
Definition grammar.y:228
static void opensubg(char *name)
Definition grammar.y:550
qatom T_qatom
Definition grammar.y:212
else endnode()
Definition grammar.y:383
static void endgraph(void)
Definition grammar.y:544
static void appendnode(char *name, char *port, char *sport)
Definition grammar.y:366
static item * cons_subg(Agraph_t *subg)
Definition grammar.y:234
static void endedge(void)
Definition grammar.y:411
static void closesubg(void)
Definition grammar.y:559
FILE * aagin
static item * cons_node(Agnode_t *n, char *port)
Definition grammar.y:225
static item * cons_list(item *list)
Definition grammar.y:231
static void mkport(Agedge_t *e, char *name, char *val)
Definition grammar.y:498
T_node
Definition grammar.y:173
hdr $1
Definition grammar.y:131
static item * newitem(int tag, void *p0, char *p1)
Definition grammar.y:216
static void listapp(list_t *list, item *v)
Definition grammar.y:270
static char * concatPort(char *s1, char *s2)
Definition grammar.y:468
T_edge
Definition grammar.y:174
nodelist node
Definition grammar.y:161
qatom
Definition grammar.y:208
rcompound
Definition grammar.y:156
T_digraph
Definition grammar.y:138
static void attrstmt(int tkind, char *macroname)
Definition grammar.y:332
static void edgerhs(Agnode_t *tail, char *tport, item *hlist, char *key)
Definition grammar.y:481
static void nomacros(void)
Definition grammar.y:323
static void startgraph(char *name, bool directed, bool strict)
Definition grammar.y:530
static void deletelist(list_t *list)
Definition grammar.y:264
void aginternalmapclearlocalnames(Agraph_t *g)
Definition imap.c:165
Agsym_t * agattr(Agraph_t *g, int kind, char *name, const char *value)
creates or looks up attributes of a graph
Definition attr.c:338
int agxset(void *obj, Agsym_t *sym, const char *value)
Definition attr.c:478
Agdisc_t AgDefaultDisc
Definition graph.c:289
Agedge_t * agedge(Agraph_t *g, Agnode_t *t, Agnode_t *h, char *name, int createflag)
Definition edge.c:260
#define TAILPORT_ID
Definition cgraph.h:887
#define HEADPORT_ID
Definition cgraph.h:888
#define agtail(e)
Definition cgraph.h:880
#define aghead(e)
Definition cgraph.h:881
void agwarningf(const char *fmt,...)
Definition agerror.c:173
void agerrorf(const char *fmt,...)
Definition agerror.c:165
int agclose(Agraph_t *g)
deletes a graph, freeing its associated storage
Definition graph.c:102
Agraph_t * agconcat(Agraph_t *g, void *chan, Agdisc_t *disc)
merges the file contents with a pre-existing graph
Definition grammar.y:579
Agraph_t * agopen(char *name, Agdesc_t desc, Agdisc_t *disc)
creates a new graph with the given name and kind
Definition graph.c:44
Agraph_t * agread(void *fp, Agdisc_t *disc)
constructs a new graph
Definition grammar.y:591
Agnode_t * agnode(Agraph_t *g, char *name, int createflag)
Definition node.c:145
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition node.c:47
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:40
Agnode_t * agsubnode(Agraph_t *g, Agnode_t *n, int createflag)
Definition node.c:259
#define AGTYPE(obj)
returns AGRAPH, AGNODE, or AGEDGE depending on the type of the object
Definition cgraph.h:216
@ AGOUTEDGE
Definition cgraph.h:207
@ AGEDGE
Definition cgraph.h:207
@ AGNODE
Definition cgraph.h:207
@ AGINEDGE
Definition cgraph.h:207
@ AGRAPH
Definition cgraph.h:207
int agstrfree(Agraph_t *, const char *)
Definition refstr.c:139
char * agstrdup(Agraph_t *, const char *)
returns a pointer to a reference-counted copy of the argument string, creating one if necessary
Definition refstr.c:131
Agraph_t * agsubg(Agraph_t *g, char *name, int cflag)
Definition subg.c:58
Agraph_t * graph(char *name)
Definition gv.cpp:30
textitem scanner parser str
Definition htmlparse.y:224
table Syntax error
Definition htmlparse.y:294
$$
Definition htmlparse.y:327
NEATOPROCS_API void s1(graph_t *, node_t *)
Definition stuff.c:671
static bool streq(const char *a, const char *b)
are a and b equal?
Definition streq.h:11
graph descriptor
Definition cgraph.h:284
unsigned directed
Definition cgraph.h:285
user's discipline
Definition cgraph.h:337
graph or subgraph
Definition cgraph.h:425
string attribute descriptor symbol in Agattr_s.dict
Definition cgraph.h:637
unsigned char print
Definition cgraph.h:644
int dummy
Definition grammar.c:206
list_t attrlist
Definition grammar.c:117
list_t edgelist
Definition grammar.c:117
list_t nodelist
Definition grammar.c:117
Agraph_t * g
Definition grammar.c:115
Agraph_t * subg
Definition grammar.c:116
struct gstack_s * down
Definition grammar.c:118
char * str
Definition grammar.c:105
val_t u
Definition grammar.c:104
struct item_s * next
Definition grammar.c:106
int tag
Definition grammar.c:103
Definition utils.c:747
item * last
Definition grammar.c:111
item * first
Definition grammar.c:110
Definition types.h:48
Definition grammar.c:93
Agedge_t * e
Definition grammar.c:96
Agraph_t * subg
Definition grammar.c:95
Agsym_t * asym
Definition grammar.c:97
Agnode_t * n
Definition grammar.c:94
struct item_s * list
Definition grammar.c:99
char * name
Definition grammar.c:98
#define UNREACHABLE()
Definition unreachable.h:30