1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
/* By default, Flex emits a lexer using symbols prefixed with "yy". Graphviz
* contains multiple Flex-generated lexers, so we alter this prefix to avoid
* symbol clashes.
*/
%option prefix="gml"
/* Avoid generating an unused input function. See
https://westes.github.io/flex/manual/Scanner-Options.html
*/
%option noinput
%{
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <gml2gv.h>
#include <gmlparse.h>
#include <util/alloc.h>
#include <util/agxbuf.h>
#include "config.h"
#define GRAPH_EOF_TOKEN '@' /* lex class must be defined below */
static int line_num = 1;
static int errors;
static FILE* Ifile;
void initgmlscan(FILE *ifile)
{
if (ifile) {
Ifile = ifile;
line_num = 1;
}
errors = 0;
}
#ifndef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
if ((result = fread(buf, 1, max_size, Ifile)) < 0) \
YY_FATAL_ERROR( "input in flex scanner failed" )
#endif
/// buffer for arbitrary length strings
static agxbuf Sbuf;
static void beginstr(void) {
assert(agxblen(&Sbuf) == 0 && "leaking memory");
}
static void addstr(const char *src) {
agxbput(&Sbuf, src);
}
static void endstr(void) {
// take ownership of the Sbuf backing memory
gmllval.str = agxbdisown(&Sbuf);
}
%}
GRAPH_EOF_TOKEN [@]
ASCII [ !#$%\047-\177]
DIGIT [0-9]
L_INT [-+]?{DIGIT}+
MANTISSA E[-+]?{DIGIT}
L_REAL [-+]?{DIGIT}*\.{DIGIT}*{MANTISSA}?
L_ID [a-zA-Z_][_a-zA-Z0-9]*
%x qstring
%%
{GRAPH_EOF_TOKEN} return(EOF);
<INITIAL,qstring>\n line_num++;
^"#".* /* ignore # line */
[ \t\r] /* ignore whitespace */
"graph" return (GRAPH);
"node" return (NODE);
"edge" return (EDGE);
"directed" return (DIRECTED);
"id" return (ID);
"source" return (SOURCE);
"target" return (TARGET);
"x" return (XVAL);
"y" return (YVAL);
"w" return (WVAL);
"h" return (HVAL);
"label" return (LABEL);
"graphics" return (GRAPHICS);;
"LabelGraphics" return (LABELGRAPHICS);
"type" return (TYPE);
"fill" return (FILL);
"outline" return (OUTLINE);
"outlineStyle" return (OUTLINESTYLE);
"outlineWidth" return (OUTLINEWIDTH);
"width" return (WIDTH);
"style" return (STYLE);
"Line" return (LINE);
"point" return (POINT);
"text" return (TEXT);
"fontSize" return (FONTSIZE);
"fontName" return (FONTNAME);
"color" return (COLOR);
{L_INT} { gmllval.str = gv_strdup(yytext); return (INTEGER); }
{L_REAL} { gmllval.str = gv_strdup(yytext); return (REAL); }
{L_ID} { gmllval.str = gv_strdup(yytext); return (NAME); }
["] BEGIN(qstring); beginstr();
<qstring>["] BEGIN(INITIAL); endstr(); return (STRING);
<qstring>([^"]+) addstr(yytext);
. return (yytext[0]);
%%
void gmlerror(const char *str)
{
if (errors)
return;
errors = 1;
agwarningf(" %s in line %d near '%s'\n", str,line_num,yytext);
}
int gmlerrors(void)
{
return errors;
}
void gmllexeof(void) { unput(GRAPH_EOF_TOKEN); }
#ifndef YY_CALL_ONLY_ARG
# define YY_CALL_ONLY_ARG void
#endif
int yywrap(YY_CALL_ONLY_ARG)
{
return 1;
}
|