Skip to content

Commit ea1af98

Browse files
committed
Fix parsing of concatenated string literals
1 parent 2cc49d8 commit ea1af98

File tree

3 files changed

+51
-4
lines changed

3 files changed

+51
-4
lines changed

make_boilerplate/make_boilerplate.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#define NO_FIBERS
22
#define ACCEL ACCEL_TABLE
3+
#define OLD_PARSER 1
34

45
#include "../os/compat.h"
56
#include "../utils/read_file.c"

parser/metac_expr_parser.c

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ static inline bool IsPunctuationToken(metac_token_enum_t tok)
435435
return (
436436
(IsBinaryOperator(tok, expr_flags_none)
437437
&& tok != tok_star && tok != tok_lParen
438-
&& tok != tok_lBracket)
438+
&& tok != tok_lBracket && tok != tok_and)
439439
|| tok == tok_dotdot
440440
|| tok == tok_comma
441441
/*
@@ -741,10 +741,52 @@ metac_expr_t* MetaCParser_ParsePrimaryExpr(metac_parser_t* self, parse_expr_flag
741741
{
742742
// result = GetOrAddStringLiteral(_string_table, currentToken);
743743
MetaCParser_Match(self, tok_string);
744+
uint32_t stringLength = LENGTH_FROM_STRING_KEY(currentToken->StringKey);
745+
uint32_t currentLen = LENGTH_FROM_STRING_KEY(currentToken->StringKey);
746+
uint32_t adjacentStrings = 1;
747+
const char* currentStringP = IdentifierPtrToCharPtr(&self->Lexer->StringTable, currentToken->StringPtr);
748+
uint32_t stringHash = crc32c_nozero(~0, currentStringP, currentLen);
749+
char stringBuffer[8192]; // let's just hope we don't need to concat huge strings;
750+
char* stringBufferP = stringBuffer;
751+
744752
result = AllocNewExpr(expr_string);
745-
result->StringPtr = RegisterString(self, currentToken);
746-
result->StringKey = currentToken->StringKey;
747-
result->Hash = currentToken->StringKey;
753+
754+
for(metac_token_t* peekToken = 0; (peekToken = MetaCParser_PeekToken(self, 1))->TokenType == tok_string;)
755+
{
756+
MetaCParser_Match(self, tok_string);
757+
memcpy(stringBufferP, currentStringP, currentLen);
758+
stringBufferP += currentLen;
759+
760+
currentLen = LENGTH_FROM_STRING_KEY(peekToken->StringKey);
761+
currentStringP = IdentifierPtrToCharPtr(&self->Lexer->StringTable, peekToken->StringPtr);
762+
stringHash = crc32c_nozero(stringHash, currentStringP, currentLen);
763+
stringLength += currentLen;
764+
765+
adjacentStrings += 1;
766+
if (stringLength >= sizeof(stringBuffer)) { assert(!"concat string too long"); }
767+
}
768+
769+
if (adjacentStrings == 1)
770+
{
771+
result->StringPtr = RegisterString(self, currentToken);
772+
result->StringKey = currentToken->StringKey;
773+
result->Hash = currentToken->StringKey;
774+
}
775+
else
776+
{
777+
// for the last one
778+
memcpy(stringBufferP, currentStringP, currentLen);
779+
// we can now compute the string key
780+
assert(crc32c_nozero(~0, stringBuffer, stringLength) == stringHash);
781+
782+
result->StringKey = STRING_KEY(stringHash, stringLength);
783+
// GetOrAddIdentifier copies the string into string table memory
784+
// therefore we can just concat it into a temporary buffer
785+
result->StringPtr = GetOrAddIdentifier(&self->StringTable,
786+
result->StringKey, stringBuffer);
787+
result->Hash = result->StringKey;
788+
789+
}
748790
//PushOperand(result);
749791
}
750792
else if (tokenType == tok_char)

parser/metac_parser.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2310,7 +2310,11 @@ metac_stmt_t* MetaCParser_ParseStmt(metac_parser_t* self,
23102310
}
23112311
else
23122312
{
2313+
#ifdef OLD_PARSER
2314+
return_->ReturnExp = MetaCParser_ParseExpr(self, expr_flags_none, 0);
2315+
#else
23132316
return_->ReturnExp = MetaCParser_ParseExpr2(self, expr_flags_none);
2317+
#endif
23142318
hash = CRC32C_VALUE(hash, return_->ReturnExp->Hash);
23152319
}
23162320
return_->Hash = hash;

0 commit comments

Comments
 (0)