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