mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 09:18:09 +00:00
eval2: first pass at c recursive type expression parsing
This commit is contained in:
+141
-32
@@ -1070,6 +1070,21 @@ e2_expr_push_child(Arena *arena, E2_Expr *parent, E2_Expr *expr)
|
||||
e2_expr_push_child_node(parent, n);
|
||||
}
|
||||
|
||||
internal void
|
||||
e2_expr_push_child_node_front(E2_Expr *parent, E2_ExprNode *node)
|
||||
{
|
||||
SLLQueuePushFront(parent->first_child, parent->last_child, node);
|
||||
parent->child_count += 1;
|
||||
}
|
||||
|
||||
internal void
|
||||
e2_expr_push_child_front(Arena *arena, E2_Expr *parent, E2_Expr *expr)
|
||||
{
|
||||
E2_ExprNode *n = push_array(arena, E2_ExprNode, 1);
|
||||
n->v = expr;
|
||||
e2_expr_push_child_node_front(parent, n);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Expression Constructors
|
||||
|
||||
@@ -1539,14 +1554,26 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
E2_Parse parse = {E2_ParseStatus_Error, .expr = &e2_expr_nil, .params_expr = &e2_expr_nil};
|
||||
E2_LangInfo *lang_info = &e2_lang_kind_info_table[lang];
|
||||
|
||||
//- rjf: set up initial parsing task
|
||||
if(state->top_task == 0)
|
||||
{
|
||||
state->top_task = &state->start_task;
|
||||
state->top_task->src_range = r1u64(0, string.size);
|
||||
state->top_task->child_count_target = max_U64;
|
||||
state->top_task->max_precedence = max_S64;
|
||||
state->top_task->expected_splitter = s(",");
|
||||
state->top_task->splitter_min_child_count = 0;
|
||||
}
|
||||
|
||||
//- rjf: parse & attach to top parsing task - if we don't have a top task
|
||||
// then it is just the result
|
||||
E2_Expr *expr = &e2_expr_nil;
|
||||
for(B32 done = 0; !done;)
|
||||
{
|
||||
U64 start_off = off;
|
||||
S64 max_precedence = state->top_task ? state->top_task->max_precedence : max_S64;
|
||||
B32 need_new_expr = (expr == &e2_expr_nil && !state->caller_info_completes_task);
|
||||
S64 max_precedence = state->top_task->max_precedence;
|
||||
B32 type_ancestors = state->top_task->do_type_ancestors;
|
||||
B32 need_new_expr = (expr == &e2_expr_nil && !type_ancestors && !state->caller_info_completes_task);
|
||||
E2_Token token = {0};
|
||||
|
||||
//- rjf: skip leading whitespace / comments
|
||||
@@ -1638,7 +1665,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
}
|
||||
|
||||
//- rjf: identifiers with an active dot op kind -> member access
|
||||
else if(need_new_expr && state->top_task != 0 && state->top_task->expr_kind == E2_ExprKind_Dot && e2_try_token(lang, string, E2_TokenKind_Identifier, s(""), &off, &token))
|
||||
else if(need_new_expr && state->top_task->expr_kind == E2_ExprKind_Dot && e2_try_token(lang, string, E2_TokenKind_Identifier, s(""), &off, &token))
|
||||
{
|
||||
expr = e2_expr(arena, E2_ExprKind_Dot);
|
||||
expr->first_child = state->top_task->first_child;
|
||||
@@ -1656,7 +1683,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
{
|
||||
String8 identifier = str8_substr(string, token.range);
|
||||
B32 identifier_mapped = 0;
|
||||
B32 definitions_are_allowed = (state->top_task == 0 || state->top_task->expr_kind != E2_ExprKind_Macro);
|
||||
B32 definitions_are_allowed = (state->top_task->expr_kind != E2_ExprKind_Macro);
|
||||
|
||||
// rjf: first try to resolve as a definition
|
||||
if(definitions_are_allowed && !identifier_mapped && e2_try_token(lang, string, E2_TokenKind_Symbol, s("="), &off, 0))
|
||||
@@ -1792,7 +1819,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
}
|
||||
|
||||
// rjf: try to resolve it as a macro argument
|
||||
if(!identifier_mapped && state->top_task != 0 && state->top_task->expr_kind == E2_ExprKind_Macro)
|
||||
if(!identifier_mapped && state->top_task->expr_kind == E2_ExprKind_Macro)
|
||||
{
|
||||
U64 macro_arg_num = 0;
|
||||
{
|
||||
@@ -1862,16 +1889,17 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
expr->string = raw_string;
|
||||
}
|
||||
|
||||
//- rjf: extend parsed expression tree with completed trailing type operators (right-to-left)
|
||||
if(!state->caller_info_completes_task && expr != &e2_expr_nil)
|
||||
//- rjf: parse left-hand-side type operators
|
||||
if(!state->caller_info_completes_task && (expr != &e2_expr_nil || state->top_task->do_type_ancestors))
|
||||
{
|
||||
U64 trailing_symbol_off = off;
|
||||
if(e2_try_token(lang, string, E2_TokenKind_Symbol, s(""), &trailing_symbol_off, &token))
|
||||
{
|
||||
B32 is_expr_type = (expr->kind == E2_ExprKind_TypeIdentifier ||
|
||||
expr->kind == E2_ExprKind_Ptr ||
|
||||
(state->top_task != 0 && state->top_task->expr_kind == E2_ExprKind_Cast));
|
||||
if(is_expr_type)
|
||||
B32 parent_looking_for_type = (state->top_task->expr_kind != E2_ExprKind_Null &&
|
||||
state->top_task->child_count == 0 &&
|
||||
e2_expr_kind_is_first_operand_type_maybe_table[state->top_task->expr_kind]);
|
||||
B32 is_expr_type = (e2_expr_kind_is_type_expr_table[expr->kind] || parent_looking_for_type);
|
||||
if(is_expr_type || state->top_task->do_type_ancestors)
|
||||
{
|
||||
// rjf: token string -> operator kind
|
||||
E2_ExprKind expr_kind = E2_ExprKind_Null;
|
||||
@@ -1893,7 +1921,10 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
if(expr_kind != E2_ExprKind_Null)
|
||||
{
|
||||
E2_Expr *op_expr = e2_expr(arena, expr_kind);
|
||||
if(expr != &e2_expr_nil)
|
||||
{
|
||||
e2_expr_push_child(arena, op_expr, expr);
|
||||
}
|
||||
expr = op_expr;
|
||||
off = trailing_symbol_off;
|
||||
}
|
||||
@@ -1901,6 +1932,38 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: if we're parsing a type, and we see a C-style type info recursion (to
|
||||
// express ancestors of the current type), then we need to generate a task to
|
||||
// descend and parse the ancestor type
|
||||
if(!state->caller_info_completes_task && expr != &e2_expr_nil)
|
||||
{
|
||||
B32 parent_looking_for_type = (state->top_task->expr_kind != E2_ExprKind_Null &&
|
||||
state->top_task->child_count == 0 &&
|
||||
e2_expr_kind_is_first_operand_type_maybe_table[state->top_task->expr_kind]);
|
||||
B32 is_expr_type = (e2_expr_kind_is_type_expr_table[expr->kind] || parent_looking_for_type);
|
||||
if(is_expr_type && e2_try_token(lang, string, E2_TokenKind_Symbol, s("("), &off, &token))
|
||||
{
|
||||
E2_ParseTask *task = state->free_task;
|
||||
if(task != 0)
|
||||
{
|
||||
SLLStackPop(state->free_task);
|
||||
}
|
||||
else
|
||||
{
|
||||
task = push_array_no_zero(arena, E2_ParseTask, 1);
|
||||
}
|
||||
MemoryZeroStruct(task);
|
||||
task->src_range = token.range;
|
||||
task->expected_closer = s(")");
|
||||
task->child_count_target = 1;
|
||||
task->max_precedence = max_S64;
|
||||
task->do_type_ancestors = 1;
|
||||
task->type_lhs = expr;
|
||||
SLLStackPush(state->top_task, task);
|
||||
expr = &e2_expr_nil;
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: extend parsed expression tree with trailing operators
|
||||
if(!state->caller_info_completes_task && expr != &e2_expr_nil)
|
||||
{
|
||||
@@ -1926,7 +1989,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
E2_ExprKindParseInfo *expr_kind_info = &lang_info->expr_kind_parse_infos[idx];
|
||||
if(expr_kind_info->precedence <= max_precedence &&
|
||||
str8_match(token_string, expr_kind_info->sep, 0) &&
|
||||
(!!expr_is_type == !!e2_expr_kind_is_type_expr_table[expr_kind_info->expr_kind]))
|
||||
(!expr_is_type || e2_expr_kind_allow_type_operands_table[expr_kind_info->expr_kind]))
|
||||
{
|
||||
splitter = expr_kind_info->chain;
|
||||
closer = expr_kind_info->post;
|
||||
@@ -1939,7 +2002,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: non-null operator kind -> build binary expression node, push task to fill other child
|
||||
// rjf: non-null operator kind -> push task to fill other children of this operator node
|
||||
if(expr_kind != E2_ExprKind_Null)
|
||||
{
|
||||
E2_ParseTask *task = state->free_task;
|
||||
@@ -1959,6 +2022,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
task->reverse_children = reverse_children;
|
||||
task->max_precedence = precedence;
|
||||
task->expected_splitter = splitter;
|
||||
task->splitter_min_child_count = 2;
|
||||
task->expected_closer = closer;
|
||||
task->splitter_is_required = splitter_is_required;
|
||||
SLLStackPush(state->top_task, task);
|
||||
@@ -1974,6 +2038,18 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
//- rjf: pop finished expressions
|
||||
for(B32 task_pushed = 0; state->top_task != 0 && !done && !task_pushed;)
|
||||
{
|
||||
//- rjf: if this task has a type ancestor: our finished expression is
|
||||
// actually a descendant of that. we want to push our finished expression
|
||||
// as a child, and then use the next type ancestor as the root expression
|
||||
// which we push to our current task.
|
||||
if(state->top_task->next_type_ancestor != 0 && state->top_task->next_type_ancestor != &e2_expr_nil)
|
||||
{
|
||||
E2_Expr *type_descendant = expr;
|
||||
expr = state->top_task->next_type_ancestor;
|
||||
state->top_task->next_type_ancestor = &e2_expr_nil;
|
||||
e2_expr_push_child_front(arena, expr, type_descendant);
|
||||
}
|
||||
|
||||
//- rjf: gather finished expression to current task; increase task child count
|
||||
if(!state->caller_info_completes_task)
|
||||
{
|
||||
@@ -1992,7 +2068,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
|
||||
//- rjf: consume expected splitters
|
||||
if(!state->caller_info_completes_task &&
|
||||
state->top_task->child_count > 1 &&
|
||||
state->top_task->child_count >= state->top_task->splitter_min_child_count &&
|
||||
state->top_task->expected_splitter.size != 0 &&
|
||||
state->top_task->child_count < state->top_task->child_count_target)
|
||||
{
|
||||
@@ -2011,7 +2087,8 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
|
||||
//- rjf: determine if the task above a parenthesized sub-expression is expecting a type
|
||||
B32 parent_looking_for_type = 0;
|
||||
if(state->top_task->next != 0 &&
|
||||
if(!state->top_task->do_type_ancestors &&
|
||||
state->top_task->next != 0 &&
|
||||
state->top_task->next->expr_kind != E2_ExprKind_Null &&
|
||||
state->top_task->next->child_count == 0 &&
|
||||
e2_expr_kind_is_first_operand_type_maybe_table[state->top_task->next->expr_kind])
|
||||
@@ -2021,7 +2098,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
|
||||
//- rjf: determine if first child of a parenthesized sub-expression is a type
|
||||
B32 parenthesized_child_is_type = 0;
|
||||
if(!parent_looking_for_type && closer_found && state->top_task->child_count == 1)
|
||||
if(!state->top_task->do_type_ancestors && !parent_looking_for_type && closer_found && state->top_task->child_count == 1)
|
||||
{
|
||||
E2_Expr *expr = state->top_task->first_child->v;
|
||||
parenthesized_child_is_type = 1;
|
||||
@@ -2093,6 +2170,12 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
|
||||
//- rjf: produced finished expression tree, given all children
|
||||
E2_Expr *finished_root = &e2_expr_nil;
|
||||
{
|
||||
if(completed_task->expr_kind == E2_ExprKind_Null && completed_task->child_count == 1)
|
||||
{
|
||||
finished_root = completed_task->first_child->v;
|
||||
}
|
||||
else
|
||||
{
|
||||
finished_root = e2_expr(arena, completed_task->expr_kind);
|
||||
finished_root->first_child = completed_task->first_child;
|
||||
@@ -2100,6 +2183,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
finished_root->child_count = completed_task->child_count;
|
||||
finished_root->src_range = completed_task->src_range;
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: report missing closers
|
||||
if(!completed_with_caller_info && completed_task->expected_closer.size != 0 && !closer_found)
|
||||
@@ -2107,6 +2191,25 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
e2_msgf(arena, &parse.msgs, r1u64(off, off), "Expected `%S`.", completed_task->expected_closer);
|
||||
}
|
||||
|
||||
//- rjf: if this task parsed type ancestors:
|
||||
//
|
||||
// we need to pop this task, and return to working on the original left-hand-side
|
||||
// type descendant. but, we need to remember the parsed type ancestors, so that
|
||||
// we can apply them to the type once the right-hand-side has been parsed.
|
||||
//
|
||||
// otherwise (normal case): work on the parent of the finished expression next,
|
||||
// using the finished expression as the completed child.
|
||||
//
|
||||
if(completed_task->do_type_ancestors)
|
||||
{
|
||||
expr = completed_task->type_lhs;
|
||||
completed_task->next->next_type_ancestor = finished_root;
|
||||
}
|
||||
else
|
||||
{
|
||||
expr = finished_root;
|
||||
}
|
||||
|
||||
//- rjf: release task
|
||||
if(!done)
|
||||
{
|
||||
@@ -2114,14 +2217,25 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
SLLStackPush(state->free_task, completed_task);
|
||||
}
|
||||
|
||||
//- rjf: work on the parent of the finished expression next
|
||||
expr = finished_root;
|
||||
//- rjf: if this task still has potential right-hand-sides, then we need to
|
||||
// break out of the pop-loop and keep parsing at this level.
|
||||
if(state->top_task->expr_kind == E2_ExprKind_Null || completed_task->do_type_ancestors)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: if the top task is not done -> break & continue - reset expression, because we need to parse another.
|
||||
//- rjf: if the top task is not done -> break & continue.
|
||||
//
|
||||
// if we have an active op kind, reset expression, because we need to parse another.
|
||||
// if we don't, we need to look for extensions of our current expression instead.
|
||||
//
|
||||
else
|
||||
{
|
||||
if(state->top_task->expr_kind != E2_ExprKind_Null)
|
||||
{
|
||||
expr = &e2_expr_nil;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2131,9 +2245,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
if(off >= string.size || (off == start_off && !e2_parse_status_is_caller_request(parse.status)))
|
||||
{
|
||||
done = 1;
|
||||
if(state->top_task == 0)
|
||||
{
|
||||
if(parse.expr == &e2_expr_nil && expr != &e2_expr_nil)
|
||||
if(expr != &e2_expr_nil)
|
||||
{
|
||||
parse.expr = expr;
|
||||
}
|
||||
@@ -2143,7 +2255,6 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: asking caller for info? -> if we already did this at this offset,
|
||||
// the user couldn't provide the info, so we just fail out.
|
||||
@@ -2164,7 +2275,7 @@ e2_parse_from_string(Arena *arena, E2_ParseState *state, B32 identifier_is_type,
|
||||
//- rjf: report incomplete tasks
|
||||
if(off >= string.size && !e2_parse_status_is_caller_request(parse.status))
|
||||
{
|
||||
for(E2_ParseTask *t = state->top_task; t != 0; t = t->next)
|
||||
for(E2_ParseTask *t = state->top_task; t != 0 && t != &state->start_task; t = t->next)
|
||||
{
|
||||
String8 symbol = {0};
|
||||
if(t->expr_kind != E2_ExprKind_Null)
|
||||
@@ -2410,6 +2521,7 @@ e2_compile_from_expr(Arena *arena, E2_CompileState *state, E2_IRNode *resolve_re
|
||||
finished_root->string = e->string;
|
||||
finished_root->type_key = e2_type_key_cons_array(e2_type_key_basic(E2_TypeKind_UChar8), e->string.size);
|
||||
finished_root->val.u64 = e->string.size;
|
||||
finished_root->mode = E2_Mode_Value;
|
||||
}break;
|
||||
|
||||
//- rjf: character literals
|
||||
@@ -2545,16 +2657,8 @@ e2_compile_from_expr(Arena *arena, E2_CompileState *state, E2_IRNode *resolve_re
|
||||
{
|
||||
e2_msgf(arena, &compile.msgs, e->src_range, "Cannot cast to this type.");
|
||||
}
|
||||
else if(e2_type_kind_is_ptr_or_ref(e2_type_kind_from_key(cast_type_key)))
|
||||
{
|
||||
finished_root = rhs;
|
||||
rhs->mode = E2_Mode_Address;
|
||||
}
|
||||
else
|
||||
{
|
||||
E2_IRNode *castee_ir = rhs;
|
||||
finished_root = e2_irnode_convert_if_possible(arena, castee_ir, cast_type_key);
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: dereferences
|
||||
@@ -2912,6 +3016,10 @@ e2_compile_from_expr(Arena *arena, E2_CompileState *state, E2_IRNode *resolve_re
|
||||
{
|
||||
compile_time_cond = 1;
|
||||
}
|
||||
if(pass_ir->mode != fail_ir->mode)
|
||||
{
|
||||
compile_time_cond = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: compile-time conditional -> ask caller to evaluate conditional
|
||||
@@ -2993,6 +3101,7 @@ e2_compile_from_expr(Arena *arena, E2_CompileState *state, E2_IRNode *resolve_re
|
||||
|
||||
// rjf: take result
|
||||
finished_root = cond_root;
|
||||
finished_root->mode = pass_ir->mode;
|
||||
}
|
||||
}break;
|
||||
}
|
||||
|
||||
@@ -341,6 +341,7 @@ struct E2_ParseTask
|
||||
Rng1U64 src_range;
|
||||
E2_ExprNode *first_child;
|
||||
E2_ExprNode *last_child;
|
||||
E2_Expr *next_type_ancestor;
|
||||
U64 child_count;
|
||||
U64 child_count_target;
|
||||
B32 reverse_children;
|
||||
@@ -349,14 +350,18 @@ struct E2_ParseTask
|
||||
String8 identifier;
|
||||
String8 expected_closer;
|
||||
String8 expected_splitter;
|
||||
U64 splitter_min_child_count;
|
||||
B32 splitter_is_required;
|
||||
String8List macro_arg_names;
|
||||
B32 do_type_ancestors;
|
||||
E2_Expr *type_lhs;
|
||||
};
|
||||
|
||||
typedef struct E2_ParseState E2_ParseState;
|
||||
struct E2_ParseState
|
||||
{
|
||||
U64 string_off;
|
||||
E2_ParseTask start_task;
|
||||
E2_ParseTask *top_task;
|
||||
E2_ParseTask *free_task;
|
||||
U64 last_caller_request_string_off;
|
||||
@@ -632,6 +637,8 @@ internal E2_TypeKey e2_coerced_type_key_from_operands(E2_TypeKey lhs, E2_TypeKey
|
||||
internal E2_Expr *e2_expr(Arena *arena, E2_ExprKind kind);
|
||||
internal void e2_expr_push_child_node(E2_Expr *parent, E2_ExprNode *node);
|
||||
internal void e2_expr_push_child(Arena *arena, E2_Expr *parent, E2_Expr *expr);
|
||||
internal void e2_expr_push_child_node_front(E2_Expr *parent, E2_ExprNode *node);
|
||||
internal void e2_expr_push_child_front(Arena *arena, E2_Expr *parent, E2_Expr *expr);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: IR Tree Constructors
|
||||
|
||||
+50
-43
@@ -1,51 +1,51 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
@table(name is_type_expression is_first_operand_type_maybe target_operand_count)
|
||||
@table(name allow_type_operands is_type_expression is_first_operand_type_maybe target_operand_count)
|
||||
E2_ExprKindTable:
|
||||
{
|
||||
{Identifier 0 0 0 }
|
||||
{MacroArg 0 0 0 }
|
||||
{TypeIdentifier 1 0 0 }
|
||||
{Ptr 1 1 1 }
|
||||
{Array 1 1 2 }
|
||||
{Numeric 0 0 0 }
|
||||
{StringLiteral 0 0 0 }
|
||||
{CharLiteral 0 0 0 }
|
||||
{Dot 0 0 1 }
|
||||
{Index 0 0 2 }
|
||||
{Call 0 0 0xffffffffffffffffull}
|
||||
{DerefAsm 0 0 1 }
|
||||
{SizeOf 0 1 1 }
|
||||
{TypeOf 1 1 1 }
|
||||
{Cast 0 1 2 }
|
||||
{Deref 0 0 1 }
|
||||
{Address 0 0 1 }
|
||||
{Pos 0 0 1 }
|
||||
{Neg 0 0 1 }
|
||||
{LogNot 0 0 1 }
|
||||
{BitNot 0 0 1 }
|
||||
{Mul 0 0 2 }
|
||||
{Div 0 0 2 }
|
||||
{Mod 0 0 2 }
|
||||
{Add 0 0 2 }
|
||||
{Sub 0 0 2 }
|
||||
{LShift 0 0 2 }
|
||||
{RShift 0 0 2 }
|
||||
{Less 0 0 2 }
|
||||
{LtEq 0 0 2 }
|
||||
{Grtr 0 0 2 }
|
||||
{GrEq 0 0 2 }
|
||||
{EqEq 0 0 2 }
|
||||
{NtEq 0 0 2 }
|
||||
{BitAnd 0 0 2 }
|
||||
{BitXor 0 0 2 }
|
||||
{BitOr 0 0 2 }
|
||||
{LogAnd 0 0 2 }
|
||||
{LogOr 0 0 2 }
|
||||
{Define 0 0 1 }
|
||||
{Macro 0 0 1 }
|
||||
{Cond 0 0 3 }
|
||||
{Identifier 0 0 0 0 }
|
||||
{MacroArg 0 0 0 0 }
|
||||
{TypeIdentifier 0 1 0 0 }
|
||||
{Ptr 1 1 1 1 }
|
||||
{Array 1 1 1 2 }
|
||||
{Numeric 0 0 0 0 }
|
||||
{StringLiteral 0 0 0 0 }
|
||||
{CharLiteral 0 0 0 0 }
|
||||
{Dot 1 0 0 1 }
|
||||
{Index 0 0 0 2 }
|
||||
{Call 1 0 0 0xffffffffffffffffull}
|
||||
{DerefAsm 1 0 0 1 }
|
||||
{SizeOf 1 0 1 1 }
|
||||
{TypeOf 1 1 1 1 }
|
||||
{Cast 1 0 1 2 }
|
||||
{Deref 1 0 0 1 }
|
||||
{Address 1 0 0 1 }
|
||||
{Pos 1 0 0 1 }
|
||||
{Neg 1 0 0 1 }
|
||||
{LogNot 1 0 0 1 }
|
||||
{BitNot 1 0 0 1 }
|
||||
{Mul 1 0 0 2 }
|
||||
{Div 1 0 0 2 }
|
||||
{Mod 1 0 0 2 }
|
||||
{Add 1 0 0 2 }
|
||||
{Sub 1 0 0 2 }
|
||||
{LShift 1 0 0 2 }
|
||||
{RShift 1 0 0 2 }
|
||||
{Less 1 0 0 2 }
|
||||
{LtEq 1 0 0 2 }
|
||||
{Grtr 1 0 0 2 }
|
||||
{GrEq 1 0 0 2 }
|
||||
{EqEq 1 0 0 2 }
|
||||
{NtEq 1 0 0 2 }
|
||||
{BitAnd 1 0 0 2 }
|
||||
{BitXor 1 0 0 2 }
|
||||
{BitOr 1 0 0 2 }
|
||||
{LogAnd 1 0 0 2 }
|
||||
{LogOr 1 0 0 2 }
|
||||
{Define 1 0 0 1 }
|
||||
{Macro 1 0 0 1 }
|
||||
{Cond 1 0 0 3 }
|
||||
}
|
||||
|
||||
@enum E2_ExprKind:
|
||||
@@ -55,6 +55,12 @@ E2_ExprKindTable:
|
||||
COUNT,
|
||||
}
|
||||
|
||||
@data(B8) e2_expr_kind_allow_type_operands_table:
|
||||
{
|
||||
0,
|
||||
@expand(E2_ExprKindTable a) `$(a.allow_type_operands)`
|
||||
}
|
||||
|
||||
@data(B8) e2_expr_kind_is_type_expr_table:
|
||||
{
|
||||
0,
|
||||
@@ -110,6 +116,7 @@ E2_LangKindTable:
|
||||
@table(name parse_kind precedence pre sep pos chain reverse_children)
|
||||
E2_ExprKindParseInfoTable_CLike:
|
||||
{
|
||||
{Dot Postfix 1 "" "." "" "" 0}
|
||||
{Index Postfix 1 "" "[" "]" "" 0}
|
||||
{Call Postfix 1 "" "(" ")" "," 0}
|
||||
{DerefAsm Prefix 1 "[" "" "]" "" 0}
|
||||
|
||||
@@ -4,6 +4,53 @@
|
||||
//- GENERATED CODE
|
||||
|
||||
C_LINKAGE_BEGIN
|
||||
B8 e2_expr_kind_allow_type_operands_table[43] =
|
||||
{
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
};
|
||||
|
||||
B8 e2_expr_kind_is_type_expr_table[43] =
|
||||
{
|
||||
0,
|
||||
@@ -150,8 +197,9 @@ E2_LangInfo e2_lang_kind_info_table[1] =
|
||||
{ArrayCount(e2_expr_kind_parse_info_table__clike), (e2_expr_kind_parse_info_table__clike)},
|
||||
};
|
||||
|
||||
E2_ExprKindParseInfo e2_expr_kind_parse_info_table__clike[37] =
|
||||
E2_ExprKindParseInfo e2_expr_kind_parse_info_table__clike[38] =
|
||||
{
|
||||
{E2_ExprKind_Dot, E2_ExprParseKind_Postfix, 1, 0, str8_lit_comp(""), str8_lit_comp("."), str8_lit_comp(""), str8_lit_comp("")},
|
||||
{E2_ExprKind_Index, E2_ExprParseKind_Postfix, 1, 0, str8_lit_comp(""), str8_lit_comp("["), str8_lit_comp("]"), str8_lit_comp("")},
|
||||
{E2_ExprKind_Call, E2_ExprParseKind_Postfix, 1, 0, str8_lit_comp(""), str8_lit_comp("("), str8_lit_comp(")"), str8_lit_comp(",")},
|
||||
{E2_ExprKind_DerefAsm, E2_ExprParseKind_Prefix, 1, 0, str8_lit_comp("["), str8_lit_comp(""), str8_lit_comp("]"), str8_lit_comp("")},
|
||||
|
||||
@@ -158,11 +158,12 @@ E2_ExprKindParseInfo *expr_kind_parse_infos;
|
||||
};
|
||||
|
||||
C_LINKAGE_BEGIN
|
||||
extern B8 e2_expr_kind_allow_type_operands_table[43];
|
||||
extern B8 e2_expr_kind_is_type_expr_table[43];
|
||||
extern B8 e2_expr_kind_is_first_operand_type_maybe_table[43];
|
||||
extern U64 e2_expr_kind_target_operand_count_table[43];
|
||||
extern E2_LangInfo e2_lang_kind_info_table[1];
|
||||
extern E2_ExprKindParseInfo e2_expr_kind_parse_info_table__clike[37];
|
||||
extern E2_ExprKindParseInfo e2_expr_kind_parse_info_table__clike[38];
|
||||
extern U8 e2_type_kind_basic_byte_size_table[61];
|
||||
extern String8 e2_type_kind_basic_string_table[61];
|
||||
|
||||
|
||||
+22
-17
@@ -43,46 +43,51 @@ entry_point(CmdLine *cmdline)
|
||||
// (A)
|
||||
// int & B
|
||||
// (1 + (int)&B)
|
||||
s("int32[100]"),
|
||||
|
||||
// TODO(rjf): this is now busted, `mul` root comes out - related to always having a top task maybe?
|
||||
s("3 * 4 + 2"),
|
||||
s("(3 * 4) + 2"),
|
||||
s("3 * 4"),
|
||||
s("foo"),
|
||||
s("foo.bar"),
|
||||
s("[123]"),
|
||||
s("123[456]"),
|
||||
s("2 + (3 * 4)"),
|
||||
s("int32 == int32"),
|
||||
s("123, 456"),
|
||||
s("222.f"),
|
||||
s("123 as float32"),
|
||||
s("int32 (*) [100]"),
|
||||
s("int32[100]"),
|
||||
s("cast float32 123"),
|
||||
s("cast (float32) 123"),
|
||||
s("(int32 *)123"),
|
||||
s("bar(a, b) = a + b"),
|
||||
s("123, 456"),
|
||||
s("int32 == int32"),
|
||||
s("foo = 123"),
|
||||
s("1 > 2"),
|
||||
s("1 ? 123 : 456"),
|
||||
s("0 ? 123 : 456"),
|
||||
s("1 ? \"Test\" : 888"),
|
||||
s("'a'"),
|
||||
s("'b'"),
|
||||
s("float32(111)"),
|
||||
s("float64(111)"),
|
||||
s("222.f"),
|
||||
s("222.0"),
|
||||
s("(float32)222"),
|
||||
s("(float64)222"),
|
||||
s("[123]"),
|
||||
s("foo"),
|
||||
s("foo.bar"),
|
||||
s("123[456]"),
|
||||
s("222.0"),
|
||||
s("123"),
|
||||
s("123 + 456"),
|
||||
s("!1"),
|
||||
s("!0"),
|
||||
s("1 + 1 + 1"),
|
||||
s("40 / 0"),
|
||||
s("3 * 4"),
|
||||
s("3 * 4 + 2"),
|
||||
s("(3 * 4) + 2"),
|
||||
s("2 + (3 * 4)"),
|
||||
s("123 | 456"),
|
||||
s("123 + "),
|
||||
s("-123"),
|
||||
s("sizeof 123"),
|
||||
s("1 ? 123 : 456"),
|
||||
s("0 ? 123 : 456"),
|
||||
s("123(1, 2, 3)"),
|
||||
#if 0
|
||||
// s("float32(111)"),
|
||||
// s("float64(111)"),
|
||||
#endif
|
||||
};
|
||||
for EachElement(idx, strings)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user