9
9
10
10
%{
11
11
#include <cassert>
12
+ #include <cctype>
13
+ #include <cstdio>
12
14
#include <vector>
13
15
#include "location.hh"
14
16
#include "position.hh"
18
20
// Keep track of token lengths.
19
21
#define YY_USER_ACTION yyextra->loc.columns(yyleng);
20
22
23
+ static void escape(char c, char *buf);
24
+
21
25
%}
22
26
23
27
%option bison-bridge bison-locations
@@ -33,10 +37,12 @@ FLOAT -?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?
33
37
INTEGER -?(0|[1-9][0-9]*)
34
38
IDENTIFIER [_A-Za-z][_0-9A-Za-z]*
35
39
VARIABLE $[_0-9A-Za-z]+
40
+ BOM \xef\xbb\xbf
41
+ CRLF \r\n
42
+ BADCHAR [\x00-\x08\x0b\x0c\x0e-\x1f]
43
+ STRINGCHAR [^\x00-\x1f\\\x22]
36
44
37
- blank [ \t\v\f\xa0,]
38
- /* NOTE: When we do UTF-8, we need to add \u2028
39
- and \u2029 here. */
45
+ blank [ \t,]
40
46
newline [\n\r]
41
47
notnewline [^\n\r]
42
48
@@ -46,80 +52,141 @@ notnewline [^\n\r]
46
52
yyextra->loc.step();
47
53
%}
48
54
49
- {blank}+ { yyextra->loc.step(); }
50
- {newline}+ { yyextra->loc.lines(yyleng); yyextra->loc.step(); }
51
-
52
- # {yyextra->loc.step(); BEGIN(LINE_COMMENT_STATE); }
53
-
54
- <LINE_COMMENT_STATE>{
55
- {newline} { yyextra->loc.step(); BEGIN(INITIAL); }
56
- {notnewline}+ /* eat comment character */
57
- }
58
-
59
- false { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_FALSE; }
60
- fragment { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_FRAGMENT; }
61
- mutation { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_MUTATION; }
62
- null { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_NULL; }
63
- on { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_ON; }
64
- query { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_QUERY; }
65
- true { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_TRUE; }
66
-
67
- {INTEGER} { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_INTEGER; }
68
- {FLOAT} { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_FLOAT; }
69
- {IDENTIFIER} { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_IDENTIFIER; }
70
- {VARIABLE} { yylval->str = yytext + 1; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_VARIABLE; }
71
-
72
- "!" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_BANG; }
73
- "(" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_LPAREN; }
74
- ")" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_RPAREN; }
75
- "..." { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_ELLIPSIS; }
76
- ":" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_COLON; }
77
- "=" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_EQUAL; }
78
- "@" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_AT; }
79
- "[" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_LBRACKET; }
80
- "]" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_RBRACKET; }
81
- "{" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_LBRACE; }
82
- "|" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_PIPE; }
83
- "}" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_RBRACE; }
84
-
85
-
86
- <<EOF>> { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_EOF; }
87
-
88
- \" {
89
- BEGIN(STRING_STATE);
90
- yyextra->str.clear();
91
- }
92
-
93
55
<STRING_STATE>{
94
56
\" {
95
57
BEGIN(INITIAL);
96
58
yylval->str = yyextra->str.c_str();
97
59
return yy::GraphQLParserImpl::token::TOK_STRING;
98
60
}
99
61
100
- [^"\\]+ {
62
+ {newline} {
63
+ throw make_error(yyextra->loc, "Unterminated string");
64
+ }
65
+
66
+ <<EOF>> {
67
+ throw make_error(yyextra->loc, "Unterminated string at EOF");
68
+ }
69
+
70
+ {STRINGCHAR}+ {
101
71
char *p = yytext;
102
72
while (*p) {
103
73
yyextra->loc.columns();
104
74
yyextra->str.push_back(*p++);
105
75
}
106
76
}
107
77
108
- \\\" { yyextra->loc.columns(); yyextra-> str.push_back('"'); }
109
- \\\\ { yyextra->loc.columns(); yyextra-> str.push_back('\\'); }
110
- \\\/ { yyextra->loc.columns(); yyextra-> str.push_back('/'); }
111
- \\n { yyextra->loc.columns(); yyextra-> str.push_back('\n'); }
112
- \\t { yyextra->loc.columns(); yyextra-> str.push_back('\t'); }
113
- \\r { yyextra->loc.columns(); yyextra-> str.push_back('\r'); }
114
- \\b { yyextra->loc.columns(); yyextra-> str.push_back('\b'); }
115
- \\f { yyextra->loc.columns(); yyextra-> str.push_back('\f'); }
78
+ \\\" { yyextra->str.push_back('"'); }
79
+ \\\\ { yyextra->str.push_back('\\'); }
80
+ \\\/ { yyextra->str.push_back('/'); }
81
+ \\n { yyextra->str.push_back('\n'); }
82
+ \\t { yyextra->str.push_back('\t'); }
83
+ \\r { yyextra->str.push_back('\r'); }
84
+ \\b { yyextra->str.push_back('\b'); }
85
+ \\f { yyextra->str.push_back('\f'); }
116
86
117
87
\\u[0-9A-Fa-f]{4} {
118
- yyextra->loc.columns(6);
119
88
int ch;
120
89
sscanf(yytext + 1, "%x", &ch);
121
90
yyextra->str.push_back(ch);
122
91
}
92
+
93
+ \\u { throw make_error(yyextra->loc, "bad Unicode escape sequence"); }
94
+ \\. { throw make_error(yyextra->loc, std::string("bad escape sequence \\") + yytext[1]); }
95
+
123
96
}
124
97
125
- . {throw make_error(yyextra->loc, std::string("unrecognized character ") + yytext[0]); }
98
+ <LINE_COMMENT_STATE>{
99
+ {CRLF} { yyextra->loc.step(); BEGIN(INITIAL); }
100
+ {newline} { yyextra->loc.step(); BEGIN(INITIAL); }
101
+ {notnewline}+ /* eat comment character */
102
+ }
103
+
104
+ <INITIAL>{
105
+ {blank}+ { yyextra->loc.step(); }
106
+ {BOM}+ { yyextra->loc.step(); yyextra->loc.step(); yyextra->loc.step(); }
107
+ {CRLF}+ { yyextra->loc.lines(yyleng / 2); yyextra->loc.step(); }
108
+ {newline}+ { yyextra->loc.lines(yyleng); yyextra->loc.step(); }
109
+
110
+ # {yyextra->loc.step(); BEGIN(LINE_COMMENT_STATE); }
111
+
112
+ false { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_FALSE; }
113
+ fragment { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_FRAGMENT; }
114
+ mutation { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_MUTATION; }
115
+ null { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_NULL; }
116
+ on { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_ON; }
117
+ query { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_QUERY; }
118
+ true { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_TRUE; }
119
+
120
+ {INTEGER} { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_INTEGER; }
121
+ {FLOAT} { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_FLOAT; }
122
+ {IDENTIFIER} { yylval->str = yytext; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_IDENTIFIER; }
123
+ {VARIABLE} { yylval->str = yytext + 1; *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_VARIABLE; }
124
+
125
+ "!" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_BANG; }
126
+ "(" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_LPAREN; }
127
+ ")" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_RPAREN; }
128
+ "..." { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_ELLIPSIS; }
129
+ ":" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_COLON; }
130
+ "=" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_EQUAL; }
131
+ "@" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_AT; }
132
+ "[" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_LBRACKET; }
133
+ "]" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_RBRACKET; }
134
+ "{" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_LBRACE; }
135
+ "|" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_PIPE; }
136
+ "}" { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_RBRACE; }
137
+
138
+
139
+ <<EOF>> { *yylloc = yyextra->loc; return yy::GraphQLParserImpl::token::TOK_EOF; }
140
+
141
+ \" {
142
+ BEGIN(STRING_STATE);
143
+ yyextra->str.clear();
144
+ }
145
+ }
146
+
147
+ <INITIAL,STRING_STATE,LINE_COMMENT_STATE>. {
148
+ char buf[6];
149
+ escape(yytext[0], buf);
150
+ throw make_error(
151
+ yyextra->loc,
152
+ std::string("unrecognized character ") + buf);
153
+ }
154
+
155
+ %%
156
+
157
+ static void escape(char c, char *buf) {
158
+ if (std::isgraph(c)) {
159
+ *buf = c;
160
+ buf[1] = '\0';
161
+ } else {
162
+ buf[0] = '\\';
163
+ buf[2] = '\0';
164
+ switch (c) {
165
+ case '\a':
166
+ buf[1] = 'a';
167
+ break;
168
+ case '\b':
169
+ buf[1] = 'b';
170
+ break;
171
+ case '\f':
172
+ buf[1] = 'f';
173
+ break;
174
+ case '\n':
175
+ buf[1] = 'n';
176
+ break;
177
+ case '\r':
178
+ buf[1] = 'r';
179
+ break;
180
+ case '\t':
181
+ buf[1] = 't';
182
+ break;
183
+ case '\v':
184
+ buf[1] = 'v';
185
+ break;
186
+ default:
187
+ buf[1] = 'x';
188
+ std::snprintf(buf + 2, 3, "%x", ((int)c & 0xFF));
189
+ break;
190
+ }
191
+ }
192
+ }
0 commit comments