%{ // // Graph Generator /* This parser recognizes the following graph grammar graph => direction? nodeStyleList edgeStyleList nodeLabelList adjacencyList direction => DIRECTION = VERTICAL ; | DIRECTION = HORIZONTAL ; nodeStyleList => (nodeStyle ;)* edgeStyleList => (edgeStyle ;)* nodeLableList => (nodeLabel ;)* nodeStyle => NODESTYLE STYLE_NAME? [ attributeList ] nodelist edgeStyle => EDGESTYLE STYLE_NAME [ attributeList ] attributeList => attribute (, attribute)* attribute => COLOR = PROPERTY_NAME | SHAPE = PROPERTY_NAME | FONTNAME = PROPERTY_NAME | FONTSIZE = NUMBER nodeList => NODE_NAME+ nodeLabel => NODE_NAME = "NODE_LABEL" adjacencyList => nodeAdjacencyList+ nodeAdjacencyList => NODE_NAME -> NODE_NAME "EDGE_LABEL"? STYLE_NAME? (, NODE_NAME "EDGE_LABEL"? STYLE_NAME?)* ; */ #include #include #include #include "graph.h" using namespace std; // for keeping track of edge styles list *edgeStyles; // root of the syntax tree graphNode *root; // for keeping track of line numbers in the program we are parsing int line_num = 1; // function prototypes, we need the yylex return prototype so C++ won't complain int yylex(); void yyerror(char * s); %} %start graph %union { int num; char *name; char *lab; direction *directionNode; nodeStyle *nodeStyleNode; edgeStyle *edgeStyleNode; nodeLabel *labelNode; attribute *attrNode; edgeList *toVertices; list *nodeNameList; list *attrList; list *nStyleList; list *nLabelList; list *adjList; list *toVtxList; edge *newEdge; } %error-verbose %token NUMBER %token NAME %token LABEL %token DIRECTION HORIZONTAL VERTICAL %token COLOR SHAPE FONTNAME FONTSIZE %token NODESTYLE EDGESTYLE %token COMMA SEMI %token LBRACK RBRACK %token EQUALS %token ARROW %type direction; %type nodeStyleList; %type nodeLabelList; %type attributeList; %type nodeList; %type nodeStyle; %type edgeStyle; %type nodeLabel; %type attribute; %type adjacencyList; %type edgeList; %type edgeHead; %type edge; %% graph : direction nodeStyleList edgeStyleList nodeLabelList adjacencyList { root = new graphNode($1, $2, $4, $5); } ; direction : DIRECTION EQUALS VERTICAL SEMI { $$ = new direction("TB"); } | DIRECTION EQUALS HORIZONTAL SEMI { $$ = new direction("LR"); } | { $$ = NULL; } ; nodeStyleList : nodeStyleList nodeStyle SEMI { $$ = $1; $$->push_back($2); } | { $$ = new list(); } ; edgeStyleList : edgeStyleList edgeStyle SEMI { edgeStyles->push_back($2); } | { edgeStyles = new list(); } ; nodeLabelList : nodeLabelList nodeLabel SEMI { $$ = $1; $$->push_back($2); } | { $$ = new list(); } ; nodeStyle : NODESTYLE NAME LBRACK attributeList RBRACK nodeList { $$ = new nodeStyle($4, $6); } | NODESTYLE LBRACK attributeList RBRACK nodeList { $$ = new nodeStyle($3, $5); } ; edgeStyle : EDGESTYLE NAME LBRACK attributeList RBRACK { $$ = new edgeStyle($2, $4); } ; attributeList : attributeList COMMA attribute { $$ = $1; $$->push_back($3); } | attribute { $$ = new list(); $$->push_back($1); } ; attribute : COLOR EQUALS NAME { $$ = new colorAttribute($3); } | SHAPE EQUALS NAME { $$ = new shapeAttribute($3); } | FONTNAME EQUALS NAME { $$ = new fontNameAttribute($3); } | FONTSIZE EQUALS NUMBER { $$ = new fontSizeAttribute($3); } ; nodeList : nodeList NAME { $$ = $1; $$->push_back($2); } | NAME { $$ = new list(); $$->push_back($1); } ; nodeLabel : NAME EQUALS LABEL { $$ = new nodeLabel($1, $3); } ; adjacencyList : adjacencyList edgeHead SEMI { $$ = $1; $$->push_back($2); } | edgeHead SEMI { $$ = new list(); $$->push_back($1); } ; edgeHead : NAME ARROW edgeList { $$ = new edgeList($1, $3); } edgeList : edgeList COMMA edge { $$ = $1; $$->push_back($3); } | edge { $$ = new list(); $$->push_back($1); } ; edge : NAME { $$ = new edge($1); } | NAME LABEL { $$ = new edge($1, $2, true); } | NAME NAME { $$ = new edge($1, $2, false); } | NAME LABEL NAME { $$ = new edge($1, $2, $3, true); } ; %% main() { // yydebug = 1; yyparse(); root->print(); } void yyerror(char * s) { fprintf(stderr, "line %d: %s\n", line_num, s); }