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
|
/*
This software may only be used by you under license from AT&T Corp.
("AT&T"). A copy of AT&T's Source Code Agreement is available at
AT&T's Internet website having the URL:
<http://www.research.att.com/sw/tools/graphviz/license/source.html>
If you received this software without first entering into a license
with AT&T, you have an infringing copy of this software and cannot use
it without violating AT&T's intellectual property rights.
*/
/* requires flex (i.e. not lex) */
%{
#pragma prototyped
#include <grammar.h>
#include <aghdr.h>
#define GRAPH_EOF_TOKEN '@' /* lex class must be defined below */
/* this is a workaround for linux flex */
#ifndef yywrap
#define yywrap() 1
#endif
static int line_num = 1;
static Agdisc_t *Disc;
static void *Ifile;
/* There is a hole here, because switching channels
* requires pushing back whatever was previously read.
* There probably is a right way of doing this.
*/
void aglexinit(Agdisc_t *disc, void *ifile) { Disc = disc; Ifile = ifile;}
#ifndef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
if ((result = Disc->io->afread(Ifile, buf, max_size)) < 0) \
YY_FATAL_ERROR( "input in flex scanner failed" )
#endif
/* buffer for arbitrary length strings (longer than BUFSIZ) */
static char *Sbuf,*Sptr,*Send;
static void beginstr(void) {
if (Sbuf == NIL(char*)) {
Sbuf = malloc(BUFSIZ);
Send = Sbuf + BUFSIZ;
}
Sptr = Sbuf;
*Sptr = 0;
}
static void addstr(char *src) {
char c;
if (Sptr > Sbuf) Sptr--;
do {
do {c = *Sptr++ = *src++;} while (c && (Sptr < Send));
if (c) {
long sz = Send - Sbuf;
long off = Sptr - Sbuf;
sz *= 2;
Sbuf = (char*)realloc(Sbuf,sz);
Send = Sbuf + sz;
Sptr = Sbuf + off;
}
} while (c);
}
static void endstr(void) {
yylval.str = (char*)agstrdup(Ag_G_global,Sbuf);
}
%}
GRAPH_EOF_TOKEN [@]
LETTER [A-Za-z_]
DIGIT [0-9]
NAME {LETTER}({LETTER}|{DIGIT})*
NUMBER [-]?(({DIGIT}+(\.{DIGIT}*)?)|(\.{DIGIT}+))
ID ({NAME}|{NUMBER})
%x comment
%x qstring
%%
{GRAPH_EOF_TOKEN} return(EOF);
<INITIAL,comment,qstring>\n line_num++;
"/*" BEGIN(comment);
<comment>[^*\n]* /* eat anything not a '*' */
<comment>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */
<comment>"*"+"/" BEGIN(INITIAL);
"//".* /* ignore C++-style comments */
"#".* /* ignore shell-like comments */
[ \t] /* ignore whitespace */
"node" return(T_node); /* see tokens in agcanonstr */
"edge" return(T_edge);
"graph" return(T_graph);
"digraph" return(T_digraph);
"strict" return(T_strict);
"subgraph" return(T_subgraph);
"->"|"--" return(T_edgeop);
{ID} { yylval.str = (char*)agstrdup(Ag_G_global,yytext); return(T_atom); }
["] BEGIN(qstring); beginstr();
<qstring>["] BEGIN(INITIAL); endstr(); return (T_atom);
<qstring>[\\][\n] line_num++; /* ignore escaped newlines */
<qstring>([^"\\]*|[\\].) addstr(yytext);
. return (yytext[0]);
%%
void yyerror(char *str)
{
char buf[BUFSIZ];
sprintf(buf,"%s in line %d near '%s'",str,line_num,yytext);
agerror(AGERROR_SYNTAX,buf);
}
/* must be here to see flex's macro defns */
void aglexeof() { unput(GRAPH_EOF_TOKEN); }
|