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
137
138
139
140
141
142
143
144
145
146
147
148
|
%{
/*-------------------------------------------------------------------------
*
* exprscan.l
* a lexical scanner for a simple expression syntax
*
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*-------------------------------------------------------------------------
*/
/* line and column number for error reporting */
static int yyline = 0, yycol = 0;
/* Handles to the buffer that the lexer uses internally */
static YY_BUFFER_STATE scanbufhandle;
static char *scanbuf;
static int scanbuflen;
/* context information for error reporting */
static char *expr_source = NULL;
static int expr_lineno = 0;
static char *expr_full_line = NULL;
static char *expr_command = NULL;
static int expr_col = 0;
%}
%option 8bit
%option never-interactive
%option nodefault
%option noinput
%option nounput
%option noyywrap
%option warn
%option prefix="expr_yy"
alpha [a-zA-Z_]
digit [0-9]
alnum [a-zA-Z0-9_]
space [ \t\r\f]
%%
"+" { yycol += yyleng; return '+'; }
"-" { yycol += yyleng; return '-'; }
"*" { yycol += yyleng; return '*'; }
"/" { yycol += yyleng; return '/'; }
"%" { yycol += yyleng; return '%'; }
"(" { yycol += yyleng; return '('; }
")" { yycol += yyleng; return ')'; }
"," { yycol += yyleng; return ','; }
:{alnum}+ {
yycol += yyleng;
yylval.str = pg_strdup(yytext + 1);
return VARIABLE;
}
{digit}+ {
yycol += yyleng;
yylval.ival = strtoint64(yytext);
return INTEGER;
}
{alpha}{alnum}* {
yycol += yyleng;
yylval.str = pg_strdup(yytext);
return FUNCTION;
}
[\n] { yycol = 0; yyline++; }
{space}+ { yycol += yyleng; /* ignore */ }
. {
yycol += yyleng;
syntax_error(expr_source, expr_lineno, expr_full_line, expr_command,
"unexpected character", yytext, expr_col + yycol);
/* dead code, exit is called from syntax_error */
return CHAR_ERROR;
}
%%
void
expr_yyerror_more(const char *message, const char *more)
{
syntax_error(expr_source, expr_lineno, expr_full_line, expr_command,
message, more, expr_col + yycol);
}
void
yyerror(const char *message)
{
expr_yyerror_more(message, NULL);
}
/*
* Called before any actual parsing is done
*/
void
expr_scanner_init(const char *str, const char *source,
const int lineno, const char *line,
const char *cmd, const int ecol)
{
Size slen = strlen(str);
/* save context informations for error messages */
expr_source = (char *) source;
expr_lineno = (int) lineno;
expr_full_line = (char *) line;
expr_command = (char *) cmd;
expr_col = (int) ecol;
/* reset error pointers for this scan */
yycol = yyline = 0;
/*
* Might be left over after error
*/
if (YY_CURRENT_BUFFER)
yy_delete_buffer(YY_CURRENT_BUFFER);
/*
* Make a scan buffer with special termination needed by flex.
*/
scanbuflen = slen;
scanbuf = pg_malloc(slen + 2);
memcpy(scanbuf, str, slen);
scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR;
scanbufhandle = yy_scan_buffer(scanbuf, slen + 2);
BEGIN(INITIAL);
}
/*
* Called after parsing is done to clean up after seg_scanner_init()
*/
void
expr_scanner_finish(void)
{
yy_delete_buffer(scanbufhandle);
pg_free(scanbuf);
expr_source = NULL;
expr_lineno = 0;
expr_full_line = NULL;
expr_command = NULL;
expr_col = 0;
}
|