@@ -90,6 +90,7 @@ void lexer_init(Lexer *lexer, const char *source, const char *filename) {
9090 lexer -> column = 1 ;
9191 lexer -> pending_token .type = TOKEN_EOF ;
9292 lexer -> pending_token .literal = NULL ;
93+ lexer -> pending_token .literal_kind = TOKEN_LITERAL_NULL ;
9394 lexer -> pending_token .line = 0 ;
9495 lexer -> pending_token .column = 0 ;
9596 lexer -> has_pending = false;
@@ -175,15 +176,31 @@ static Token make_token(Lexer *lexer, PTokenType type, const char *start, size_t
175176 Token token ;
176177 token .type = type ;
177178 token .line = lexer -> line ;
178- token .column = lexer -> column - (int )length ; // Approximate start column
179+ token .column = lexer -> column - (int )length ;
179180 if (length == 0 && start != NULL ) {
180181 token .literal = safe_strdup (start );
182+ token .literal_kind = TOKEN_LITERAL_HEAP ;
183+ } else if (length == 1 && start != NULL ) {
184+ static char pool [256 ][2 ];
185+ static bool pool_ready = false;
186+ if (!pool_ready ) {
187+ for (int i = 0 ; i < 256 ; i ++ ) {
188+ pool [i ][0 ] = (char )i ;
189+ pool [i ][1 ] = '\0' ;
190+ }
191+ pool_ready = true;
192+ }
193+ unsigned char uc = (unsigned char )start [0 ];
194+ token .literal = pool [uc ];
195+ token .literal_kind = TOKEN_LITERAL_STATIC ;
181196 } else if (start != NULL ) {
182197 token .literal = (char * )safe_malloc (length + 1 );
183198 memcpy (token .literal , start , length );
184199 token .literal [length ] = '\0' ;
200+ token .literal_kind = TOKEN_LITERAL_HEAP ;
185201 } else {
186202 token .literal = NULL ;
203+ token .literal_kind = TOKEN_LITERAL_NULL ;
187204 }
188205 return token ;
189206}
@@ -194,6 +211,7 @@ static Token error_token(Lexer *lexer, const char *message) {
194211 token .line = lexer -> line ;
195212 token .column = lexer -> column ;
196213 token .literal = safe_strdup (message );
214+ token .literal_kind = TOKEN_LITERAL_HEAP ;
197215 return token ;
198216}
199217
@@ -246,6 +264,7 @@ static Token flush_fmt_buffer(Lexer *lexer) {
246264 t .line = lexer -> line ;
247265 t .column = lexer -> column - (int )lexer -> fmt_buffer_len ;
248266 t .literal = safe_strdup (lexer -> fmt_buffer ? lexer -> fmt_buffer : "" );
267+ t .literal_kind = TOKEN_LITERAL_HEAP ;
249268 lexer -> fmt_buffer_len = 0 ;
250269 if (lexer -> fmt_buffer ) {
251270 lexer -> fmt_buffer [0 ] = '\0' ;
@@ -433,7 +452,8 @@ static Token scan_fmt_string_text(Lexer *lexer, char quote_char) {
433452 lexer -> pending_token .type = TOKEN_FMT_OPEN ;
434453 lexer -> pending_token .line = lexer -> line ;
435454 lexer -> pending_token .column = lexer -> column ;
436- lexer -> pending_token .literal = safe_strdup ("{" );
455+ lexer -> pending_token .literal = "{" ;
456+ lexer -> pending_token .literal_kind = TOKEN_LITERAL_STATIC ;
437457 return t ;
438458 }
439459
@@ -529,12 +549,12 @@ Token lexer_next_token(Lexer *lexer) {
529549 }
530550 if (c == '\n' ) {
531551 advance (lexer );
532- Token t = {TOKEN_NEWLINE , safe_strdup ( "\n" ) , lexer -> line - 1 , lexer -> column };
552+ Token t = {TOKEN_NEWLINE , "\n" , TOKEN_LITERAL_STATIC , lexer -> line - 1 , lexer -> column };
533553 return t ;
534554 }
535555 if (c == ';' ) {
536556 advance (lexer );
537- Token t = {TOKEN_NEWLINE , safe_strdup ( "\n" ) , lexer -> line , lexer -> column };
557+ Token t = {TOKEN_NEWLINE , "\n" , TOKEN_LITERAL_STATIC , lexer -> line , lexer -> column };
538558 return t ;
539559 }
540560 if (c == '!' ) {
@@ -674,7 +694,7 @@ Token lexer_next_token(Lexer *lexer) {
674694 return error_token (lexer , err_msg );
675695 }
676696
677- Token t = {TOKEN_EOF , NULL , lexer -> line , lexer -> column };
697+ Token t = {TOKEN_EOF , NULL , TOKEN_LITERAL_NULL , lexer -> line , lexer -> column };
678698 return t ;
679699}
680700
@@ -736,6 +756,7 @@ static Token identifier_token(Lexer *lexer) {
736756 Token t ;
737757 t .type = type ;
738758 t .literal = value ;
759+ t .literal_kind = TOKEN_LITERAL_HEAP ;
739760 t .line = start_line ;
740761 t .column = start_col ;
741762 return t ;
@@ -861,6 +882,17 @@ static Token number_token(Lexer *lexer, bool is_negative_start) {
861882 }
862883
863884 value [len_val ] = '\0' ;
864- Token t = {(int )has_dot ? TOKEN_FLOAT : TOKEN_NUMBER , value , start_line , start_col };
885+ Token t = {(int )has_dot ? TOKEN_FLOAT : TOKEN_NUMBER , value , TOKEN_LITERAL_HEAP , start_line , start_col };
865886 return t ;
866887}
888+
889+ void token_free (Token * token ) {
890+ if (!token ) {
891+ return ;
892+ }
893+ if (token -> literal_kind == TOKEN_LITERAL_HEAP && token -> literal != NULL ) {
894+ free (token -> literal );
895+ }
896+ token -> literal = NULL ;
897+ token -> literal_kind = TOKEN_LITERAL_NULL ;
898+ }
0 commit comments