fix incorrect parsing / expr-building order of casts vs. other prefix unaries in new parser path

This commit is contained in:
Ryan Fleury
2025-05-06 13:02:48 -07:00
parent 08402a57b4
commit a6eda7db04
+109 -91
View File
@@ -849,7 +849,7 @@ e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray t
} }
//////////////////////////// ////////////////////////////
//- rjf: parse prefix unaries //- rjf: parse atom, gather prefix unary tasks
// //
typedef struct PrefixUnaryTask PrefixUnaryTask; typedef struct PrefixUnaryTask PrefixUnaryTask;
struct PrefixUnaryTask struct PrefixUnaryTask
@@ -857,13 +857,18 @@ e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray t
PrefixUnaryTask *next; PrefixUnaryTask *next;
E_ExprKind kind; E_ExprKind kind;
Rng1U64 range; Rng1U64 range;
E_Expr *cast_type_expr;
}; };
PrefixUnaryTask *first_prefix_unary = 0; PrefixUnaryTask *first_prefix_unary = 0;
PrefixUnaryTask *last_prefix_unary = 0; PrefixUnaryTask *last_prefix_unary = 0;
E_Expr *atom = &e_expr_nil;
B32 atom_is_maybe_cast = 0;
for(B32 done = 0; !done && it < it_opl;)
{ {
for(;it < it_opl;) //////////////////////////
//- rjf: prefix unary operators
//
{ {
E_Token *start_it = it;
E_Token token = e_token_at_it(it, &tokens); E_Token token = e_token_at_it(it, &tokens);
String8 token_string = str8_substr(text, token.range); String8 token_string = str8_substr(text, token.range);
S64 prefix_unary_precedence = 0; S64 prefix_unary_precedence = 0;
@@ -889,58 +894,34 @@ e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray t
prefix_unary_precedence = 2; prefix_unary_precedence = 2;
} }
// rjf: consume valid op // rjf: push prefix unary if we got one
if(prefix_unary_precedence != 0) if(prefix_unary_precedence != 0)
{ {
range = token.range; range = token.range;
PrefixUnaryTask *prefix_unary_task = push_array(scratch.arena, PrefixUnaryTask, 1);
prefix_unary_task->kind = prefix_unary_kind;
prefix_unary_task->range = range;
SLLQueuePush(first_prefix_unary, last_prefix_unary, prefix_unary_task);
it += 1; it += 1;
} }
// rjf: break if we got no operators
if(prefix_unary_precedence == 0)
{
break;
} }
// rjf: break if the token node iterator has not changed
if(it == start_it)
{
break;
}
// rjf: push prefix unary if we got one
{
PrefixUnaryTask *op_n = push_array(scratch.arena, PrefixUnaryTask, 1);
op_n->kind = prefix_unary_kind;
op_n->range = range;
SLLQueuePushFront(first_prefix_unary, last_prefix_unary, op_n);
}
}
}
////////////////////////////
//- rjf: parse atom, gather cast tasks
//
typedef struct CastTask CastTask;
struct CastTask
{
CastTask *next;
E_Expr *type_expr;
};
CastTask *first_cast = 0;
CastTask *last_cast = 0;
E_Expr *atom = &e_expr_nil;
for(B32 done = 0; !done && it < it_opl;)
{
E_Expr *possible_cast = atom;
E_Token token = e_token_at_it(it, &tokens);
String8 token_string = str8_substr(text, token.range);
done = 1;
////////////////////////// //////////////////////////
//- rjf: try to parse an atom
//
if(atom == &e_expr_nil || atom_is_maybe_cast)
{
B32 got_new_atom = 0;
E_Expr *maybe_cast = atom_is_maybe_cast ? atom : &e_expr_nil;
atom_is_maybe_cast = 0;
////////////////////////
//- rjf: consume resolution qualifiers //- rjf: consume resolution qualifiers
// //
String8 resolution_qualifier = {0}; String8 resolution_qualifier = {0};
{
E_Token token = e_token_at_it(it, &tokens);
String8 token_string = str8_substr(text, token.range);
if(token.kind == E_TokenKind_Identifier) if(token.kind == E_TokenKind_Identifier)
{ {
E_Token next_token = e_token_at_it(it+1, &tokens); E_Token next_token = e_token_at_it(it+1, &tokens);
@@ -949,14 +930,17 @@ e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray t
{ {
it += 2; it += 2;
resolution_qualifier = token_string; resolution_qualifier = token_string;
token = e_token_at_it(it, &tokens); }
token_string = str8_substr(text, token.range);
} }
} }
////////////////////////// ////////////////////////
//- rjf: descent to nested expression (...) //- rjf: descent to nested expression (...)
// //
if(!got_new_atom)
{
E_Token token = e_token_at_it(it, &tokens);
String8 token_string = str8_substr(text, token.range);
if(token.kind == E_TokenKind_Symbol && str8_match(token_string, str8_lit("("), 0)) if(token.kind == E_TokenKind_Symbol && str8_match(token_string, str8_lit("("), 0))
{ {
// rjf: skip ( // rjf: skip (
@@ -967,6 +951,8 @@ e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray t
e_msg_list_concat_in_place(&result.msgs, &nested_parse.msgs); e_msg_list_concat_in_place(&result.msgs, &nested_parse.msgs);
atom = nested_parse.expr; atom = nested_parse.expr;
it = nested_parse.last_token; it = nested_parse.last_token;
atom_is_maybe_cast = 1;
got_new_atom = 1;
// rjf: expect ) // rjf: expect )
E_Token close_paren_maybe = e_token_at_it(it, &tokens); E_Token close_paren_maybe = e_token_at_it(it, &tokens);
@@ -981,15 +967,17 @@ e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray t
{ {
it += 1; it += 1;
} }
}
// rjf: this may have been a cast, so keep parsing after this
done = 0;
} }
////////////////////////// ////////////////////////
//- rjf: descent to assembly-style dereference sub-expression [...] //- rjf: descent to assembly-style dereference sub-expression [...]
// //
else if(token.kind == E_TokenKind_Symbol && str8_match(token_string, str8_lit("["), 0)) if(!got_new_atom)
{
E_Token token = e_token_at_it(it, &tokens);
String8 token_string = str8_substr(text, token.range);
if(token.kind == E_TokenKind_Symbol && str8_match(token_string, str8_lit("["), 0))
{ {
// rjf: skip [ // rjf: skip [
it += 1; it += 1;
@@ -999,6 +987,7 @@ e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray t
e_msg_list_concat_in_place(&result.msgs, &nested_parse.msgs); e_msg_list_concat_in_place(&result.msgs, &nested_parse.msgs);
atom = nested_parse.expr; atom = nested_parse.expr;
it = nested_parse.last_token; it = nested_parse.last_token;
got_new_atom = 1;
// rjf: build cast-to-U64*, and dereference operators // rjf: build cast-to-U64*, and dereference operators
if(nested_parse.expr == &e_expr_nil) if(nested_parse.expr == &e_expr_nil)
@@ -1031,21 +1020,32 @@ e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray t
it += 1; it += 1;
} }
} }
}
////////////////////////// ////////////////////////
//- rjf: leaf identifier //- rjf: leaf identifier
// //
else if(token.kind == E_TokenKind_Identifier) if(!got_new_atom)
{
E_Token token = e_token_at_it(it, &tokens);
String8 token_string = str8_substr(text, token.range);
if(token.kind == E_TokenKind_Identifier)
{ {
atom = e_push_expr(arena, E_ExprKind_LeafIdentifier, token.range); atom = e_push_expr(arena, E_ExprKind_LeafIdentifier, token.range);
atom->string = token_string; atom->string = token_string;
it += 1; it += 1;
got_new_atom = 1;
}
} }
////////////////////////// ////////////////////////
//- rjf: leaf numeric //- rjf: leaf numeric
// //
else if(token.kind == E_TokenKind_Numeric) if(!got_new_atom)
{
E_Token token = e_token_at_it(it, &tokens);
String8 token_string = str8_substr(text, token.range);
if(token.kind == E_TokenKind_Numeric)
{ {
U64 dot_pos = str8_find_needle(token_string, 0, str8_lit("."), 0); U64 dot_pos = str8_find_needle(token_string, 0, str8_lit("."), 0);
it += 1; it += 1;
@@ -1079,12 +1079,19 @@ e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray t
atom->value.f64 = val; atom->value.f64 = val;
} }
} }
got_new_atom = 1;
}
} }
////////////////////////// ////////////////////////
//- rjf: leaf char literal //- rjf: leaf char literal
// //
else if(token.kind == E_TokenKind_CharLiteral) if(!got_new_atom)
{
E_Token token = e_token_at_it(it, &tokens);
String8 token_string = str8_substr(text, token.range);
if(token.kind == E_TokenKind_CharLiteral)
{ {
it += 1; it += 1;
if(token_string.size > 1 && token_string.str[0] == '\'' && token_string.str[1] != '\'') if(token_string.size > 1 && token_string.str[0] == '\'' && token_string.str[1] != '\'')
@@ -1094,17 +1101,23 @@ e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray t
U8 char_val = char_literal_raw.size > 0 ? char_literal_raw.str[0] : 0; U8 char_val = char_literal_raw.size > 0 ? char_literal_raw.str[0] : 0;
atom = e_push_expr(arena, E_ExprKind_LeafU64, token.range); atom = e_push_expr(arena, E_ExprKind_LeafU64, token.range);
atom->value.u64 = (U64)char_val; atom->value.u64 = (U64)char_val;
got_new_atom = 1;
} }
else else
{ {
e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token.range, "Malformed character literal."); e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, token.range, "Malformed character literal.");
} }
} }
}
////////////////////////// ////////////////////////
//- rjf: filesystem-qualified leaf string literal //- rjf: filesystem-qualified leaf string literal
// //
else if(token.kind == E_TokenKind_StringLiteral && if(!got_new_atom)
{
E_Token token = e_token_at_it(it, &tokens);
String8 token_string = str8_substr(text, token.range);
if(token.kind == E_TokenKind_StringLiteral &&
(str8_match(resolution_qualifier, str8_lit("file"), 0) || (str8_match(resolution_qualifier, str8_lit("file"), 0) ||
str8_match(resolution_qualifier, str8_lit("folder"), 0))) str8_match(resolution_qualifier, str8_lit("folder"), 0)))
{ {
@@ -1113,29 +1126,29 @@ e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray t
atom = e_push_expr(arena, E_ExprKind_LeafFilePath, token.range); atom = e_push_expr(arena, E_ExprKind_LeafFilePath, token.range);
atom->string = string_value_raw; atom->string = string_value_raw;
it += 1; it += 1;
got_new_atom = 1;
}
} }
////////////////////////// ////////////////////////
//- rjf: leaf string literal //- rjf: leaf string literal
// //
else if(token.kind == E_TokenKind_StringLiteral) if(!got_new_atom)
{
E_Token token = e_token_at_it(it, &tokens);
String8 token_string = str8_substr(text, token.range);
if(token.kind == E_TokenKind_StringLiteral)
{ {
String8 string_value_escaped = str8_chop(str8_skip(token_string, 1), 1); String8 string_value_escaped = str8_chop(str8_skip(token_string, 1), 1);
String8 string_value_raw = raw_from_escaped_str8(arena, string_value_escaped); String8 string_value_raw = raw_from_escaped_str8(arena, string_value_escaped);
atom = e_push_expr(arena, E_ExprKind_LeafStringLiteral, token.range); atom = e_push_expr(arena, E_ExprKind_LeafStringLiteral, token.range);
atom->string = string_value_raw; atom->string = string_value_raw;
it += 1; it += 1;
got_new_atom = 1;
}
} }
////////////////////////// ////////////////////////
//- rjf: not a recognized atom pattern
//
else
{
done = 1;
}
//////////////////////////
//- rjf: upgrade atom w/ qualifier //- rjf: upgrade atom w/ qualifier
// //
if(atom != &e_expr_nil && resolution_qualifier.size != 0) if(atom != &e_expr_nil && resolution_qualifier.size != 0)
@@ -1143,17 +1156,26 @@ e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray t
atom->qualifier = resolution_qualifier; atom->qualifier = resolution_qualifier;
} }
////////////////////////// ////////////////////////
//- rjf: gather cast //- rjf: got new atom, but we had a potential cast atom? -> gather cast operator
// //
if(possible_cast != &e_expr_nil && possible_cast != atom) if(got_new_atom && maybe_cast != &e_expr_nil)
{ {
CastTask *t = push_array(scratch.arena, CastTask, 1); PrefixUnaryTask *prefix_unary_task = push_array(scratch.arena, PrefixUnaryTask, 1);
t->type_expr = possible_cast; prefix_unary_task->kind = E_ExprKind_Cast;
SLLQueuePushFront(first_cast, last_cast, t); prefix_unary_task->range = maybe_cast->range;
prefix_unary_task->cast_type_expr = maybe_cast;
SLLQueuePush(first_prefix_unary, last_prefix_unary, prefix_unary_task);
} }
} }
////////////////////////
//- rjf: if our atom is not potentially a cast, *or* if we simply did not get an atom,
// then we need to stop parsing at this stage.
//
done = (!atom_is_maybe_cast || atom == &e_expr_nil);
}
//////////////////////////// ////////////////////////////
//- rjf: upgrade atom w/ postfix unaries //- rjf: upgrade atom w/ postfix unaries
// //
@@ -1294,20 +1316,6 @@ e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray t
} }
} }
////////////////////////////
//- rjf: upgrade `atom` w/ previously parsed casts
//
if(atom != &e_expr_nil)
{
for(CastTask *cast = first_cast; cast != 0; cast = cast->next)
{
E_Expr *rhs = atom;
atom = e_push_expr(arena, E_ExprKind_Cast, cast->type_expr->range);
e_expr_push_child(atom, cast->type_expr);
e_expr_push_child(atom, rhs);
}
}
//////////////////////////// ////////////////////////////
//- rjf: upgrade `atom` w/ previously parsed prefix unaries //- rjf: upgrade `atom` w/ previously parsed prefix unaries
// //
@@ -1316,12 +1324,22 @@ e_push_parse_from_string_tokens__prec(Arena *arena, String8 text, E_TokenArray t
for(PrefixUnaryTask *prefix_unary = first_prefix_unary; for(PrefixUnaryTask *prefix_unary = first_prefix_unary;
prefix_unary != 0; prefix_unary != 0;
prefix_unary = prefix_unary->next) prefix_unary = prefix_unary->next)
{
if(prefix_unary->kind == E_ExprKind_Cast)
{
E_Expr *rhs = atom;
atom = e_push_expr(arena, prefix_unary->kind, prefix_unary->range);
e_expr_push_child(atom, prefix_unary->cast_type_expr);
e_expr_push_child(atom, rhs);
}
else
{ {
E_Expr *rhs = atom; E_Expr *rhs = atom;
atom = e_push_expr(arena, prefix_unary->kind, prefix_unary->range); atom = e_push_expr(arena, prefix_unary->kind, prefix_unary->range);
e_expr_push_child(atom, rhs); e_expr_push_child(atom, rhs);
} }
} }
}
else if(first_prefix_unary != 0) else if(first_prefix_unary != 0)
{ {
e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, last_prefix_unary->range, "Missing expression."); e_msgf(arena, &result.msgs, E_MsgKind_MalformedInput, last_prefix_unary->range, "Missing expression.");