| #include "Python.h" | |
| #include "pycore_token.h" | |
| #include "errcode.h" | |
| #include "state.h" | |
| #include "../tokenizer/helpers.h" | |
| #include "../tokenizer/reader.h" | |
| ftstring_state * | |
| _PyLexer_PushFTString(struct tok_state *tok) | |
| { | |
| assert(tok->ftstring_depth >= 0 && tok->ftstring_depth <= tok->ftstring_capacity); | |
| int next_depth = tok->ftstring_depth + 1; | |
| if (next_depth >= MAXFTSTRINGLEVEL) { | |
| _PyTokenizer_syntaxerror( | |
| tok, "too many nested f-strings or t-strings"); | |
| return NULL; | |
| } | |
| if (tok->ftstring_depth == tok->ftstring_capacity) { | |
| int capacity = Py_MIN(Py_MAX(tok->ftstring_capacity * 2, 4), | |
| MAXFTSTRINGLEVEL); | |
| size_t size = (size_t)capacity * sizeof(*tok->ftstring_stack); | |
| ftstring_state *stack; | |
| if (tok->ftstring_stack == tok->ftstring_stack_inline) { | |
| stack = PyMem_Malloc(size); | |
| if (stack != NULL) { | |
| memcpy(stack, tok->ftstring_stack, | |
| (size_t)tok->ftstring_depth * sizeof(*stack)); | |
| } | |
| } | |
| else { | |
| stack = PyMem_Realloc(tok->ftstring_stack, size); | |
| } | |
| if (stack == NULL) { | |
| PyErr_NoMemory(); | |
| tok->done = E_NOMEM; | |
| return NULL; | |
| } | |
| tok->ftstring_stack = stack; | |
| tok->ftstring_capacity = capacity; | |
| } | |
| ftstring_state *state = &tok->ftstring_stack[tok->ftstring_depth]; | |
| tok->ftstring_depth = next_depth; | |
| *state = (ftstring_state){0}; | |
| return state; | |
| } | |
| void | |
| _PyLexer_PopFTString(struct tok_state *tok) | |
| { | |
| ftstring_state *state = _PyLexer_CurrentFTString(tok); | |
| assert(state != NULL); | |
| PyMem_Free(state->comments); | |
| tok->ftstring_depth--; | |
| } | |
| /* Free a tok_state structure */ | |
| void | |
| _PyTokenizer_Free(struct tok_state *tok) | |
| { | |
| Py_XDECREF(tok->filename); | |
| Py_XDECREF(tok->module); | |
| _PyTok_ReaderFree(tok); | |
| _PyTok_SourceClear(&tok->source); | |
| for (int i = 0; i < tok->ftstring_depth; i++) { | |
| PyMem_Free(tok->ftstring_stack[i].comments); | |
| } | |
| if (tok->ftstring_stack != tok->ftstring_stack_inline) { | |
| PyMem_Free(tok->ftstring_stack); | |
| } | |
| PyMem_Free(tok); | |
| } | |
| void | |
| _PyToken_Init(struct token *token) { | |
| *token = (struct token){ | |
| .type = -1, | |
| .span = {-1, -1}, | |
| .start_loc = {-1, -1}, | |
| .end_loc = {-1, -1}, | |
| }; | |
| } | |
| int | |
| _PyLexer_token_setup(struct tok_state *tok, struct token *token, int type, _PyTok_Off start, _PyTok_Off end) | |
| { | |
| token->level = tok->level; | |
| token->is_raw = 0; | |
| assert((start == -1 && end == -1) || (start >= 0 && end >= start)); | |
| token->span = (_PyTok_Span){start, end}; | |
| if (start >= 0) { | |
| token->start_loc = tok->start_loc; | |
| token->end_loc = (_PyTok_Loc){tok->lineno, _PyLexer_ByteColumn(tok)}; | |
| } | |
| else { | |
| token->start_loc = token->end_loc = (_PyTok_Loc){tok->lineno, -1}; | |
| } | |
| return type; | |
| } |