1 %{
2 /*
3  * A scanner for EMP-style numeric ranges
4  */
5 
6 /* LCOV_EXCL_START */
7 
8 /* No reason to constrain amount of data slurped */
9 #define YY_READ_BUF_SIZE 16777216
10 
11 /* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
12 #undef fprintf
13 #define fprintf(file, fmt, msg)  fprintf_to_ereport(fmt, msg)
14 
15 static void
fprintf_to_ereport(const char * fmt,const char * msg)16 fprintf_to_ereport(const char *fmt, const char *msg)
17 {
18 	ereport(ERROR, (errmsg_internal("%s", msg)));
19 }
20 
21 /* Handles to the buffer that the lexer uses internally */
22 static YY_BUFFER_STATE scanbufhandle;
23 static char *scanbuf;
24 static int	scanbuflen;
25 %}
26 
27 %option 8bit
28 %option never-interactive
29 %option nodefault
30 %option noinput
31 %option nounput
32 %option noyywrap
33 %option warn
34 %option prefix="seg_yy"
35 
36 
37 range        (\.\.)(\.)?
38 plumin       (\'\+\-\')|(\(\+\-)\)
39 integer      [+-]?[0-9]+
40 real         [+-]?[0-9]+\.[0-9]+
41 float        ({integer}|{real})([eE]{integer})?
42 
43 %%
44 
45 {range}      yylval.text = yytext; return RANGE;
46 {plumin}     yylval.text = yytext; return PLUMIN;
47 {float}      yylval.text = yytext; return SEGFLOAT;
48 \<           yylval.text = "<"; return EXTENSION;
49 \>           yylval.text = ">"; return EXTENSION;
50 \~           yylval.text = "~"; return EXTENSION;
51 [ \t\n\r\f]+ /* discard spaces */
52 .            return yytext[0]; /* alert parser of the garbage */
53 
54 %%
55 
56 /* LCOV_EXCL_STOP */
57 
58 void
59 yyerror(SEG *result, const char *message)
60 {
61 	if (*yytext == YY_END_OF_BUFFER_CHAR)
62 	{
63 		ereport(ERROR,
64 				(errcode(ERRCODE_SYNTAX_ERROR),
65 				 errmsg("bad seg representation"),
66 				 /* translator: %s is typically "syntax error" */
67 				 errdetail("%s at end of input", message)));
68 	}
69 	else
70 	{
71 		ereport(ERROR,
72 				(errcode(ERRCODE_SYNTAX_ERROR),
73 				 errmsg("bad seg representation"),
74 				 /* translator: first %s is typically "syntax error" */
75 				 errdetail("%s at or near \"%s\"", message, yytext)));
76 	}
77 }
78 
79 
80 /*
81  * Called before any actual parsing is done
82  */
83 void
84 seg_scanner_init(const char *str)
85 {
86 	Size	slen = strlen(str);
87 
88 	/*
89 	 * Might be left over after ereport()
90 	 */
91 	if (YY_CURRENT_BUFFER)
92 		yy_delete_buffer(YY_CURRENT_BUFFER);
93 
94 	/*
95 	 * Make a scan buffer with special termination needed by flex.
96 	 */
97 	scanbuflen = slen;
98 	scanbuf = palloc(slen + 2);
99 	memcpy(scanbuf, str, slen);
100 	scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR;
101 	scanbufhandle = yy_scan_buffer(scanbuf, slen + 2);
102 
103 	BEGIN(INITIAL);
104 }
105 
106 
107 /*
108  * Called after parsing is done to clean up after seg_scanner_init()
109  */
110 void
111 seg_scanner_finish(void)
112 {
113 	yy_delete_buffer(scanbufhandle);
114 	pfree(scanbuf);
115 }
116