%{ // // 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 using namespace std; // 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; } %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 %% graph : direction nodeStyleList edgeStyleList nodeLabelList adjacencyList ; direction : DIRECTION EQUALS VERTICAL SEMI | DIRECTION EQUALS HORIZONTAL SEMI | ; nodeStyleList : nodeStyleList nodeStyle SEMI | ; edgeStyleList : edgeStyleList edgeStyle SEMI | ; nodeLabelList : nodeLabelList nodeLabel SEMI | ; nodeStyle : NODESTYLE NAME LBRACK attributeList RBRACK nodeList | NODESTYLE LBRACK attributeList RBRACK nodeList ; edgeStyle : EDGESTYLE NAME LBRACK attributeList RBRACK ; attributeList : attributeList COMMA attribute | attribute ; attribute : COLOR EQUALS NAME | SHAPE EQUALS NAME | FONTNAME EQUALS NAME | FONTSIZE EQUALS NUMBER ; nodeList : nodeList NAME | NAME ; nodeLabel : NAME EQUALS LABEL ; adjacencyList : adjacencyList edgeHead SEMI | edgeHead SEMI ; edgeHead : NAME ARROW edgeList edgeList : edgeList COMMA edge | edge ; edge : NAME | NAME LABEL | NAME NAME | NAME LABEL NAME ; %% main() { // yydebug = 1; yyparse(); } void yyerror(char * s) { fprintf(stderr, "line %d: %s\n", line_num, s); }