Tokenization of Python programming language source text. Returns 1 when a next valid token is recognized. Then the token is made avaliable in the NUL-terminated string `token`, and its token class is indicated via `type` and its location in the source via `line` and `col`. Returns 0 upon EOF or error. */
| 227 | Returns 0 upon EOF or error. |
| 228 | */ |
| 229 | static int tokenize(char *token, const char **type, |
| 230 | unsigned *line, unsigned *col) |
| 231 | { |
| 232 | unsigned len; |
| 233 | int cc; |
| 234 | *type = "unknown"; |
| 235 | |
| 236 | do { // infinite loop; after token recognized breaks out. |
| 237 | len = 0; |
| 238 | cc = get(); |
| 239 | |
| 240 | restart: |
| 241 | // cc already read. |
| 242 | |
| 243 | /*** WHITE-SPACE ***/ |
| 244 | |
| 245 | /* Can have [ \t\f]* inbetween tokens. |
| 246 | May have indentation \f?[ \t]* at beginning of logical line. |
| 247 | Tokens (except strings) cannot extend beyond a physical line |
| 248 | and may not be interrupted by a line continuation. |
| 249 | |
| 250 | \n signals completion of a logical line |
| 251 | \r signals a line joiner and generally will be ignored |
| 252 | blank lines do not generate NEWLINE tokens |
| 253 | */ |
| 254 | |
| 255 | if (strchr(" \t\f", cc)) { |
| 256 | cc = process_ws(cc); |
| 257 | goto restart; |
| 258 | } |
| 259 | |
| 260 | if (cc == '\n') { |
| 261 | prev_was_newline = 1; |
| 262 | cc = get(); |
| 263 | // Maybe EOF! |
| 264 | if (!brackets_opened && !strchr(" \t\n#\r\f", cc)) |
| 265 | process_newline(0); |
| 266 | goto restart; |
| 267 | } |
| 268 | |
| 269 | if (cc == '\r') { |
| 270 | cc = get(); |
| 271 | goto restart; |
| 272 | } |
| 273 | |
| 274 | // cc !in [ \t\n\r\f], maybe EOF |
| 275 | if (cc == EOF) { |
| 276 | // Undo any outstanding indents: |
| 277 | while (!indents_empty()) { |
| 278 | emit("DEDENT", linenr, column); |
| 279 | indents_pop(); |
| 280 | } |
| 281 | return 0; |
| 282 | } |
| 283 | |
| 284 | /*** LINE COMMENT ***/ |
| 285 | |
| 286 | if (cc == '#') { |
no test coverage detected