mirror of
https://github.com/Ed94/metadesk.git
synced 2026-06-13 07:52:22 -07:00
[expr parser] getting familiar with the expression parser
This commit is contained in:
+4
-1
@@ -5,11 +5,14 @@ og_path=$PWD
|
||||
cd "$(dirname "$0")"
|
||||
cd ..
|
||||
|
||||
echo ~~~ Running Sanity Tests ~~~
|
||||
mkdir -p build
|
||||
cd build
|
||||
|
||||
echo ~~~ Running Sanity Tests ~~~
|
||||
./sanity_tests.exe
|
||||
./unicode_test.exe
|
||||
|
||||
echo ~~~ Running Expression Tests ~~~
|
||||
./expression_tests.exe
|
||||
|
||||
###### Restore Path ###########################################################
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
I don't get what's going on with error messages:
|
||||
`MD_u64 error_offset = node->offset - ctx->original_first->offset;`
|
||||
Why is it rebased by "original_first"?
|
||||
Why is it the same for 3 locations but different here?
|
||||
`MD_u64 error_offset = ctx.first->offset - first->offset;`
|
||||
Why is it named `MD_MakeExprParseError` it doesn't seem to have any\
|
||||
details tied expression parsing.
|
||||
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ Example Programs:
|
||||
[x] User error checking
|
||||
[x] Datadesk-like setup
|
||||
[ ] Example type metadata
|
||||
[ ] Cleanup & Simplification Pass
|
||||
[x] Cleanup & Simplification Pass
|
||||
[ ] Commentary
|
||||
[ ] Example Type File With Errors
|
||||
[ ] Example of simple expression parser
|
||||
|
||||
+155
-106
@@ -3,6 +3,56 @@
|
||||
#if !defined(MD_C)
|
||||
#define MD_C
|
||||
|
||||
/* NOTE(allen): Notes on overrides/macro options:
|
||||
**
|
||||
** Overridable :
|
||||
** "memset" ** REQUIRED (default crt-based implementation available)
|
||||
** #define MD_IMPL_Memset (void*, int, MD_u64) -> void*
|
||||
** #define MD_IMPL_Memmove (void*, void*, MD_u64) -> void*
|
||||
**
|
||||
** "file iteration" ** OPTIONAL
|
||||
** #define MD_IMPL_FileIterBegin (MD_FileIter*, MD_String8) -> MD_b32
|
||||
** #define MD_IMPL_FileIterNext (MD_Arena*, MD_FileIter*) -> MD_FileInfo
|
||||
** #define MD_IMPL_FileIterEnd (MD_FileIter*) -> void
|
||||
**
|
||||
** "file load" ** OPTIONAL
|
||||
** #define MD_IMPL_LoadEntireFile (MD_Arena*, MD_String8 filename) -> MD_String8
|
||||
**
|
||||
** "low level memory" ** OPTIONAL (required for default arena)
|
||||
** #define MD_IMPL_Reserve (MD_u64) -> void*
|
||||
** #define MD_IMPL_Commit (void*, MD_u64) -> MD_b32
|
||||
** #define MD_IMPL_Decommit (void*, MD_u64) -> void
|
||||
** #define MD_IMPL_Release (void*, MD_u64) -> void
|
||||
**
|
||||
** "arena" ** REQUIRED (default implementation available)
|
||||
** #define MD_IMPL_Arena <type>
|
||||
** #define MD_IMPL_ArenaAlloc () -> MD_IMPL_Arena*
|
||||
** #define MD_IMPL_ArenaRelease (MD_IMPL_Arena*) -> void
|
||||
** #define MD_IMPL_ArenaGetPos (MD_IMPL_Arena*) -> MD_u64
|
||||
** #define MD_IMPL_ArenaPush (MD_IMPL_Arena*, MD_u64) -> void*
|
||||
** #define MD_IMPL_ArenaPopTo (MD_IMPL_Arena*, MD_u64) -> void
|
||||
** #define MD_IMPL_ArenaSetAutoAlign (MD_IMPL_Arena*, MD_u64) -> void
|
||||
** #define MD_IMPL_ArenaHeaderSize MD_u64
|
||||
**
|
||||
** "scratch" ** REQUIRED (default implementation available)
|
||||
** #define MD_IMPL_GetScratch (MD_IMPL_Arena**, MD_u64) -> MD_IMPL_Arena*
|
||||
** "scratch constants" ** OPTIONAL (required for default scratch)
|
||||
** #define MD_IMPL_ScratchCount MD_u64 / default 2
|
||||
**
|
||||
** "sprintf" ** OPTIONAL (default implementation available)
|
||||
** #define MD_IMPL_Vsnprintf (char * buf, int count, char const * fmt, va_list va) -> int
|
||||
**
|
||||
** Default Implementation Controls
|
||||
** These controls default to '1' i.e. 'enabled'
|
||||
** #define MD_DEFAULT_MEMSET -> construct "memset" from CRT
|
||||
** #define MD_DEFAULT_FILE_ITER -> construct "file iteration" from OS headers
|
||||
** #define MD_DEFAULT_MEMORY -> construct "low level memory" from OS headers
|
||||
** #define MD_DEFAULT_ARENA -> construct "arena" from "low level memory"
|
||||
** #define MD_DEFAULT_SCRATCH -> construct "scratch" from "arena"
|
||||
** #define MD_DEFAULT_SPRINTF -> construct "vsnprintf" from internal implementaion
|
||||
**
|
||||
*/
|
||||
|
||||
//~/////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////// CRT Implementation /////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -3262,70 +3312,53 @@ MD_NodeDeepMatch(MD_Node *a, MD_Node *b, MD_MatchFlags flags)
|
||||
//~ Expression Parsing
|
||||
|
||||
MD_FUNCTION void
|
||||
MD_ExprOperatorPush(MD_Arena *arena, MD_ExprOperatorList *list,
|
||||
MD_u32 op_id, MD_ExprOperatorKind kind,
|
||||
MD_u64 precedence, MD_Node *md_node)
|
||||
MD_ExprOprPush(MD_Arena *arena, MD_ExprOprList *list,
|
||||
MD_u32 op_id, MD_ExprOprKind kind,
|
||||
MD_u64 precedence, MD_Node *md_node)
|
||||
{
|
||||
MD_ExprOperatorNode *node = MD_PushArrayZero(arena, MD_ExprOperatorNode, 1);
|
||||
MD_ExprOprNode *node = MD_PushArrayZero(arena, MD_ExprOprNode, 1);
|
||||
MD_QueuePush(list->first, list->last, node);
|
||||
list->count += 1;
|
||||
node->op.op_id = op_id;
|
||||
node->op.kind = kind;
|
||||
node->op.precedence = precedence;
|
||||
node->op.md_node = md_node;
|
||||
node->op.md_node__ = md_node;
|
||||
}
|
||||
|
||||
MD_FUNCTION MD_ExprOperator *
|
||||
_MD_ExprOperatorMatch(MD_ExprOperatorTable *table, MD_ExprOperatorKind kind, MD_String8 s)
|
||||
MD_FUNCTION MD_ExprOprTable
|
||||
MD_ExprBakeOperatorTableFromList(MD_Arena *arena, MD_ExprOprList *list)
|
||||
{
|
||||
// NOTE(mal): Look for operator on one or all (kind == MD_ExprOperatorKind_Null) tables
|
||||
MD_ExprOperator *result = 0;
|
||||
for(MD_ExprOperatorKind cur_kind = (MD_ExprOperatorKind)(MD_ExprOperatorKind_Null+1);
|
||||
!result && cur_kind < MD_ExprOperatorKind_COUNT;
|
||||
cur_kind = (MD_ExprOperatorKind)(cur_kind+1))
|
||||
{
|
||||
if(kind == MD_ExprOperatorKind_Null || kind == cur_kind)
|
||||
{
|
||||
MD_ExprOperatorList *op_list = table->table+cur_kind;
|
||||
for(MD_ExprOperatorNode *op_node = op_list->first; !result && op_node; op_node = op_node->next)
|
||||
{
|
||||
if(MD_S8Match(op_node->op.md_node->string, s, 0))
|
||||
{
|
||||
result = &op_node->op;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MD_FUNCTION MD_ExprOperatorTable
|
||||
MD_ExprBakeOperatorTableFromList(MD_Arena *arena, MD_ExprOperatorList *list)
|
||||
{
|
||||
MD_ExprOperatorTable result = MD_ZERO_STRUCT;
|
||||
MD_ExprOprTable result = MD_ZERO_STRUCT;
|
||||
|
||||
for(MD_ExprOperatorNode *op_node = list->first; op_node; op_node = op_node->next)
|
||||
for(MD_ExprOprNode *op_node = list->first;
|
||||
op_node != 0;
|
||||
op_node = op_node->next)
|
||||
{
|
||||
MD_ExprOperator op = op_node->op;
|
||||
MD_String8 op_s = op.md_node->string;
|
||||
MD_ExprOpr op = op_node->op;
|
||||
MD_String8 op_s = op.md_node__->string;
|
||||
|
||||
// TODO(allen): @upgrade_potential(minor)
|
||||
|
||||
// error checking
|
||||
MD_String8 error_str = MD_ZERO_STRUCT;
|
||||
if(op.kind != MD_ExprOperatorKind_Prefix && op.kind != MD_ExprOperatorKind_Postfix &&
|
||||
op.kind != MD_ExprOperatorKind_Binary && op.kind != MD_ExprOperatorKind_BinaryRightAssociative)
|
||||
if(op.kind != MD_ExprOprKind_Prefix && op.kind != MD_ExprOprKind_Postfix &&
|
||||
op.kind != MD_ExprOprKind_Binary && op.kind != MD_ExprOprKind_BinaryRightAssociative)
|
||||
{
|
||||
error_str = MD_S8Fmt(arena, "Invalid operator kind.");
|
||||
}
|
||||
else
|
||||
{
|
||||
for(MD_ExprOperatorNode *op_node2 = list->first; op_node2 != op_node; op_node2 = op_node2->next)
|
||||
for(MD_ExprOprNode *op_node2 = list->first;
|
||||
op_node2 != op_node;
|
||||
op_node2 = op_node2->next)
|
||||
{ // NOTE(mal): O(n^2)
|
||||
MD_ExprOperator op2 = op_node2->op;
|
||||
MD_String8 op2_s = op2.md_node->string;
|
||||
MD_ExprOpr op2 = op_node2->op;
|
||||
MD_String8 op2_s = op2.md_node__->string;
|
||||
if(op.precedence == op2.precedence &&
|
||||
((op.kind == MD_ExprOperatorKind_Binary && op2.kind == MD_ExprOperatorKind_BinaryRightAssociative) ||
|
||||
(op.kind == MD_ExprOperatorKind_BinaryRightAssociative && op2.kind == MD_ExprOperatorKind_Binary)))
|
||||
((op.kind == MD_ExprOprKind_Binary && op2.kind == MD_ExprOprKind_BinaryRightAssociative) ||
|
||||
(op.kind == MD_ExprOprKind_BinaryRightAssociative && op2.kind == MD_ExprOprKind_Binary)))
|
||||
{
|
||||
error_str = MD_S8Fmt(arena, "Ignored binary operator \"%.*s\" because another binary operator"
|
||||
error_str = MD_S8Fmt(arena, "Ignored binary operator \"%.*s\" because another binary operator"
|
||||
"has the same precedence and different associativity", MD_S8VArg(op_s));
|
||||
}
|
||||
else if(MD_S8Match(op_s, op2_s, 0))
|
||||
@@ -3334,60 +3367,49 @@ MD_ExprBakeOperatorTableFromList(MD_Arena *arena, MD_ExprOperatorList *list)
|
||||
{
|
||||
error_str = MD_S8Fmt(arena, "Ignored repeat operator \"%.*s\".", MD_S8VArg(op_s));
|
||||
}
|
||||
else if(op.kind != MD_ExprOperatorKind_Prefix && op2.kind != MD_ExprOperatorKind_Prefix)
|
||||
else if(op.kind != MD_ExprOprKind_Prefix && op2.kind != MD_ExprOprKind_Prefix)
|
||||
{
|
||||
error_str = MD_S8Fmt(arena, "Ignored conflicting repeat operator \"%.*s\". There can't be"
|
||||
"more than one posfix/binary operator associated to the same token",
|
||||
MD_S8VArg(op_s));
|
||||
error_str =
|
||||
MD_S8Fmt(arena, "Ignored conflicting repeat operator \"%.*s\". There can't be"
|
||||
"more than one posfix/binary operator associated to the same token",
|
||||
MD_S8VArg(op_s));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(error_str.size == 0)
|
||||
// save error
|
||||
if(error_str.size != 0)
|
||||
{
|
||||
MD_ExprOperatorList *list = result.table+op.kind;
|
||||
MD_ExprOperatorNode *op_node_copy = MD_PushArrayZero(arena, MD_ExprOperatorNode, 1);
|
||||
MD_Message *error = MD_MakeNodeError(arena, op.md_node__, MD_MessageKind_Warning, error_str);
|
||||
MD_MessageListPush(&result.errors, error);
|
||||
}
|
||||
|
||||
// save list
|
||||
else
|
||||
{
|
||||
MD_ExprOprList *list = result.table + op.kind;
|
||||
MD_ExprOprNode *op_node_copy = MD_PushArrayZero(arena, MD_ExprOprNode, 1);
|
||||
MD_QueuePush(list->first, list->last, op_node_copy);
|
||||
list->count += 1;
|
||||
op_node_copy->op = op;
|
||||
}
|
||||
else
|
||||
{
|
||||
MD_Message *error = MD_MakeNodeError(arena, op.md_node, MD_MessageKind_Warning, error_str);
|
||||
MD_MessageListPush(&result.errors, error);
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
typedef struct _MD_ExprParseCtx _MD_ExprParseCtx;
|
||||
struct _MD_ExprParseCtx
|
||||
{
|
||||
MD_ExprOperatorTable *op_table;
|
||||
MD_Node *original_first;
|
||||
MD_Node *first;
|
||||
MD_Node *one_past_last;
|
||||
|
||||
struct{
|
||||
MD_ExprOperator *call_op;
|
||||
MD_ExprOperator *subscript_op;
|
||||
MD_ExprOperator *bracket_set_op;
|
||||
MD_ExprOperator *brace_set_op;
|
||||
} accel;
|
||||
};
|
||||
|
||||
MD_FUNCTION MD_ExprParseResult
|
||||
_MD_ExprParse_Ctx_MinPrecedence(MD_Arena *arena, _MD_ExprParseCtx *ctx, MD_u32 min_precedence);
|
||||
_MD_ExprParse_Ctx_MinPrecedence(MD_Arena *arena, MD_ExprParseCtx *ctx, MD_u32 min_precedence);
|
||||
|
||||
MD_FUNCTION MD_ExprNode * _MD_Expr_Make(MD_Arena *arena, MD_ExprOperator *op, MD_Node *op_node,
|
||||
MD_ExprNode *left, MD_ExprNode *right)
|
||||
MD_FUNCTION MD_ExprNode*
|
||||
_MD_Expr_Make(MD_Arena *arena, MD_ExprOpr *op, MD_Node *op_node,
|
||||
MD_ExprNode *left, MD_ExprNode *right)
|
||||
{
|
||||
MD_ExprNode *result = MD_PushArrayZero(arena, MD_ExprNode, 1);
|
||||
result->is_op = 1;
|
||||
result->op_id = op->op_id;
|
||||
result->md_op_node = op->md_node;
|
||||
result->md_op_node = op->md_node__;
|
||||
result->md_node = op_node;
|
||||
result->left = left;
|
||||
result->right = right;
|
||||
@@ -3399,19 +3421,19 @@ MD_FUNCTION MD_ExprNode * _MD_Expr_Make(MD_Arena *arena, MD_ExprOperator *op, MD
|
||||
return result;
|
||||
}
|
||||
|
||||
MD_FUNCTION void _MD_CtxAdvance(_MD_ExprParseCtx *ctx)
|
||||
MD_FUNCTION void _MD_CtxAdvance(MD_ExprParseCtx *ctx)
|
||||
{
|
||||
ctx->first = ctx->first->next;
|
||||
}
|
||||
|
||||
MD_FUNCTION MD_b32 _MD_ExprOperatorConsumed(_MD_ExprParseCtx *ctx, MD_ExprOperatorKind kind, MD_u32 min_precedence,
|
||||
MD_ExprOperator **op_out)
|
||||
MD_FUNCTION MD_b32 _MD_ExprOprConsumed(MD_ExprParseCtx *ctx, MD_ExprOprKind kind, MD_u32 min_precedence,
|
||||
MD_ExprOpr **op_out)
|
||||
{
|
||||
MD_b32 result = 0;
|
||||
if(!MD_NodeIsNil(ctx->first))
|
||||
{
|
||||
MD_Node *node = ctx->first;
|
||||
MD_ExprOperator *op = _MD_ExprOperatorMatch(ctx->op_table, kind, node->string);
|
||||
MD_ExprOpr *op = MD_ExprOprFromKindString(ctx->op_table, kind, node->string);
|
||||
if(op && op->precedence >= min_precedence)
|
||||
{
|
||||
result = 1;
|
||||
@@ -3422,45 +3444,46 @@ MD_FUNCTION MD_b32 _MD_ExprOperatorConsumed(_MD_ExprParseCtx *ctx, MD_ExprOperat
|
||||
return result;
|
||||
}
|
||||
|
||||
MD_FUNCTION _MD_ExprParseCtx
|
||||
_MD_ExprParse_MakeContext(MD_ExprOperatorTable *op_table, MD_Node *first, MD_Node *one_past_last)
|
||||
MD_FUNCTION MD_ExprParseCtx
|
||||
_MD_ExprParse_MakeContext(MD_ExprOprTable *op_table, MD_Node *first, MD_Node *one_past_last)
|
||||
{
|
||||
_MD_ExprParseCtx result = MD_ZERO_STRUCT;
|
||||
MD_ExprParseCtx result = MD_ZERO_STRUCT;
|
||||
result.op_table = op_table;
|
||||
result.original_first = first;
|
||||
result.first = first;
|
||||
result.one_past_last = one_past_last;
|
||||
|
||||
result.accel.bracket_set_op = _MD_ExprOperatorMatch(op_table, MD_ExprOperatorKind_Prefix, MD_S8Lit("[]"));
|
||||
result.accel.brace_set_op = _MD_ExprOperatorMatch(op_table, MD_ExprOperatorKind_Prefix, MD_S8Lit("{}"));
|
||||
result.accel.call_op = _MD_ExprOperatorMatch(op_table, MD_ExprOperatorKind_Postfix, MD_S8Lit("()"));
|
||||
result.accel.subscript_op = _MD_ExprOperatorMatch(op_table, MD_ExprOperatorKind_Binary, MD_S8Lit("[]"));
|
||||
result.accel.bracket_set_op = MD_ExprOprFromKindString(op_table, MD_ExprOprKind_Prefix, MD_S8Lit("[]"));
|
||||
result.accel.brace_set_op = MD_ExprOprFromKindString(op_table, MD_ExprOprKind_Prefix, MD_S8Lit("{}"));
|
||||
result.accel.call_op = MD_ExprOprFromKindString(op_table, MD_ExprOprKind_Postfix, MD_S8Lit("()"));
|
||||
result.accel.subscript_op = MD_ExprOprFromKindString(op_table, MD_ExprOprKind_Binary, MD_S8Lit("[]"));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
MD_FUNCTION _MD_ExprParseCtx
|
||||
_MD_ExprParse_MakeSubcontext(_MD_ExprParseCtx *ctx, MD_Node *first, MD_Node *one_past_last)
|
||||
MD_FUNCTION MD_ExprParseCtx
|
||||
_MD_ExprParse_MakeSubcontext(MD_ExprParseCtx *ctx, MD_Node *first, MD_Node *one_past_last)
|
||||
{
|
||||
_MD_ExprParseCtx result = *ctx;
|
||||
MD_ExprParseCtx result = *ctx;
|
||||
result.first = first;
|
||||
result.one_past_last = one_past_last;
|
||||
return result;
|
||||
}
|
||||
|
||||
MD_FUNCTION MD_Message * MD_MakeExprParseError(MD_Arena *arena, MD_String8 str, MD_u64 offset)
|
||||
MD_FUNCTION MD_Message*
|
||||
MD_MakeExprParseError(MD_Arena *arena, MD_String8 str, MD_u64 offset)
|
||||
{
|
||||
MD_Node *err_node = MD_MakeNode(arena, MD_NodeKind_ErrorMarker, MD_S8Lit(""), MD_S8Lit(""), offset);
|
||||
return MD_MakeNodeError(arena, err_node, MD_MessageKind_FatalError, str);
|
||||
}
|
||||
|
||||
MD_FUNCTION MD_ExprParseResult
|
||||
_MD_ExprParse_Atom(MD_Arena *arena, _MD_ExprParseCtx *ctx)
|
||||
_MD_ExprParse_Atom(MD_Arena *arena, MD_ExprParseCtx *ctx)
|
||||
{
|
||||
MD_ExprParseResult result = MD_ZERO_STRUCT;
|
||||
|
||||
MD_Node *node = ctx->first;
|
||||
MD_ExprOperator *op = 0;
|
||||
MD_ExprOpr *op = 0;
|
||||
|
||||
if(MD_NodeIsNil(node))
|
||||
{
|
||||
@@ -3478,7 +3501,7 @@ _MD_ExprParse_Atom(MD_Arena *arena, _MD_ExprParseCtx *ctx)
|
||||
else if(node->flags & MD_NodeFlag_HasParenLeft && node->flags & MD_NodeFlag_HasParenRight)
|
||||
{ // NOTE(mal): Parens
|
||||
_MD_CtxAdvance(ctx);
|
||||
_MD_ExprParseCtx sub_ctx = _MD_ExprParse_MakeSubcontext(ctx, node->first_child, node->last_child->next);
|
||||
MD_ExprParseCtx sub_ctx = _MD_ExprParse_MakeSubcontext(ctx, node->first_child, node->last_child->next);
|
||||
result = _MD_ExprParse_Ctx_MinPrecedence(arena, &sub_ctx, 0);
|
||||
}
|
||||
else if((node->flags & MD_NodeFlag_HasBracketLeft && node->flags & MD_NodeFlag_HasBracketRight &&
|
||||
@@ -3491,7 +3514,7 @@ _MD_ExprParse_Atom(MD_Arena *arena, _MD_ExprParseCtx *ctx)
|
||||
result.node = MD_PushArrayZero(arena, MD_ExprNode, 1);
|
||||
result.node->md_node = node;
|
||||
}
|
||||
else if(_MD_ExprOperatorConsumed(ctx, MD_ExprOperatorKind_Prefix, 1, &op))
|
||||
else if(_MD_ExprOprConsumed(ctx, MD_ExprOprKind_Prefix, 1, &op))
|
||||
{
|
||||
MD_u32 min_precedence = op->precedence + 1;
|
||||
MD_ExprParseResult sub_parse_result = _MD_ExprParse_Ctx_MinPrecedence(arena, ctx, min_precedence);
|
||||
@@ -3503,7 +3526,7 @@ _MD_ExprParse_Atom(MD_Arena *arena, _MD_ExprParseCtx *ctx)
|
||||
result.errors = sub_parse_result.errors;
|
||||
}
|
||||
}
|
||||
else if(_MD_ExprOperatorConsumed(ctx, MD_ExprOperatorKind_Null, 1, &op))
|
||||
else if(_MD_ExprOprConsumed(ctx, MD_ExprOprKind_Null, 1, &op))
|
||||
{
|
||||
MD_String8 error_str = MD_S8Fmt(arena, "Expected leaf. Got operator \"%.*s\".", MD_S8VArg(node->string));
|
||||
MD_u64 error_offset = node->offset - ctx->original_first->offset;
|
||||
@@ -3528,11 +3551,11 @@ _MD_ExprParse_Atom(MD_Arena *arena, _MD_ExprParseCtx *ctx)
|
||||
}
|
||||
|
||||
MD_FUNCTION MD_ExprParseResult
|
||||
_MD_ExprParse_Ctx_MinPrecedence(MD_Arena *arena, _MD_ExprParseCtx *ctx, MD_u32 min_precedence)
|
||||
_MD_ExprParse_Ctx_MinPrecedence(MD_Arena *arena, MD_ExprParseCtx *ctx, MD_u32 min_precedence)
|
||||
{
|
||||
MD_ExprParseResult result = MD_ZERO_STRUCT;
|
||||
|
||||
MD_ExprOperator *subscript_op = ctx->accel.subscript_op;
|
||||
MD_ExprOpr *subscript_op = ctx->accel.subscript_op;
|
||||
|
||||
result = _MD_ExprParse_Atom(arena, ctx);
|
||||
if(result.errors.max_message_kind == MD_MessageKind_Null)
|
||||
@@ -3540,7 +3563,7 @@ _MD_ExprParse_Ctx_MinPrecedence(MD_Arena *arena, _MD_ExprParseCtx *ctx, MD_u32 m
|
||||
while(!MD_NodeIsNil(ctx->first) && ctx->first != ctx->one_past_last)
|
||||
{
|
||||
MD_Node *node = ctx->first;
|
||||
MD_ExprOperator *op;
|
||||
MD_ExprOpr *op;
|
||||
|
||||
if(subscript_op && subscript_op->precedence >= min_precedence &&
|
||||
node->flags & MD_NodeFlag_HasBracketLeft && node->flags & MD_NodeFlag_HasBracketRight)
|
||||
@@ -3548,7 +3571,7 @@ _MD_ExprParse_Ctx_MinPrecedence(MD_Arena *arena, _MD_ExprParseCtx *ctx, MD_u32 m
|
||||
_MD_CtxAdvance(ctx);
|
||||
|
||||
// NOTE(mal): Array subscript
|
||||
_MD_ExprParseCtx sub_ctx = _MD_ExprParse_MakeSubcontext(ctx, node->first_child, node->last_child->next);
|
||||
MD_ExprParseCtx sub_ctx = _MD_ExprParse_MakeSubcontext(ctx, node->first_child, node->last_child->next);
|
||||
MD_ExprParseResult sub_parse_result = _MD_ExprParse_Ctx_MinPrecedence(arena, &sub_ctx, 0);
|
||||
if(sub_parse_result.errors.max_message_kind == MD_MessageKind_Null)
|
||||
{
|
||||
@@ -3559,10 +3582,10 @@ _MD_ExprParse_Ctx_MinPrecedence(MD_Arena *arena, _MD_ExprParseCtx *ctx, MD_u32 m
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(_MD_ExprOperatorConsumed(ctx, MD_ExprOperatorKind_Binary, min_precedence, &op) ||
|
||||
_MD_ExprOperatorConsumed(ctx, MD_ExprOperatorKind_BinaryRightAssociative, min_precedence, &op))
|
||||
else if(_MD_ExprOprConsumed(ctx, MD_ExprOprKind_Binary, min_precedence, &op) ||
|
||||
_MD_ExprOprConsumed(ctx, MD_ExprOprKind_BinaryRightAssociative, min_precedence, &op))
|
||||
{
|
||||
MD_u32 next_min_precedence = op->precedence + (op->kind == MD_ExprOperatorKind_Binary);
|
||||
MD_u32 next_min_precedence = op->precedence + (op->kind == MD_ExprOprKind_Binary);
|
||||
MD_ExprParseResult sub_parse_result = _MD_ExprParse_Ctx_MinPrecedence(arena, ctx, next_min_precedence);
|
||||
if(sub_parse_result.errors.max_message_kind == MD_MessageKind_Null)
|
||||
{
|
||||
@@ -3579,7 +3602,7 @@ _MD_ExprParse_Ctx_MinPrecedence(MD_Arena *arena, _MD_ExprParseCtx *ctx, MD_u32 m
|
||||
_MD_CtxAdvance(ctx);
|
||||
result.node = _MD_Expr_Make(arena, ctx->accel.call_op, node, result.node, 0);
|
||||
}
|
||||
else if(_MD_ExprOperatorConsumed(ctx, MD_ExprOperatorKind_Postfix, min_precedence, &op))
|
||||
else if(_MD_ExprOprConsumed(ctx, MD_ExprOprKind_Postfix, min_precedence, &op))
|
||||
{
|
||||
result.node = _MD_Expr_Make(arena, op, node, result.node, 0);
|
||||
}
|
||||
@@ -3593,17 +3616,19 @@ _MD_ExprParse_Ctx_MinPrecedence(MD_Arena *arena, _MD_ExprParseCtx *ctx, MD_u32 m
|
||||
}
|
||||
|
||||
MD_FUNCTION MD_ExprParseResult
|
||||
MD_ExprParse(MD_Arena *arena, MD_ExprOperatorTable *op_table, MD_Node *first, MD_Node *one_past_last)
|
||||
MD_ExprParse(MD_Arena *arena, MD_ExprOprTable *op_table,
|
||||
MD_Node *first, MD_Node *one_past_last)
|
||||
{
|
||||
MD_ExprParseResult result = MD_ZERO_STRUCT;
|
||||
|
||||
_MD_ExprParseCtx ctx = _MD_ExprParse_MakeContext(op_table, first, one_past_last);
|
||||
MD_ExprParseCtx ctx = _MD_ExprParse_MakeContext(op_table, first, one_past_last);
|
||||
result = _MD_ExprParse_Ctx_MinPrecedence(arena, &ctx, 0);
|
||||
if(result.errors.max_message_kind == MD_MessageKind_Null)
|
||||
{
|
||||
if(ctx.first != ctx.one_past_last)
|
||||
{
|
||||
MD_String8 error_str = MD_S8Lit("Partial parse. Expected binary or unary postfix operator.");
|
||||
MD_String8 error_str =
|
||||
MD_S8Lit("Partial parse. Expected binary or unary postfix operator.");
|
||||
MD_u64 error_offset = ctx.first->offset - first->offset;
|
||||
MD_Message *error = MD_MakeExprParseError(arena, error_str, error_offset);
|
||||
MD_MessageListPush(&result.errors, error);
|
||||
@@ -3613,6 +3638,30 @@ MD_ExprParse(MD_Arena *arena, MD_ExprOperatorTable *op_table, MD_Node *first, MD
|
||||
return(result);
|
||||
}
|
||||
|
||||
MD_FUNCTION MD_ExprOpr*
|
||||
MD_ExprOprFromKindString(MD_ExprOprTable *table, MD_ExprOprKind kind, MD_String8 s)
|
||||
{
|
||||
// NOTE(mal): Look for operator on one or all (kind == MD_ExprOprKind_Null) tables
|
||||
MD_ExprOpr *result = 0;
|
||||
for(MD_ExprOprKind cur_kind = (MD_ExprOprKind)(MD_ExprOprKind_Null + 1);
|
||||
!result && cur_kind < MD_ExprOprKind_COUNT;
|
||||
cur_kind = (MD_ExprOprKind)(cur_kind + 1))
|
||||
{
|
||||
if(kind == MD_ExprOprKind_Null || kind == cur_kind)
|
||||
{
|
||||
MD_ExprOprList *op_list = table->table+cur_kind;
|
||||
for(MD_ExprOprNode *op_node = op_list->first; !result && op_node; op_node = op_node->next)
|
||||
{
|
||||
if(MD_S8Match(op_node->op.md_node__->string, s, 0))
|
||||
{
|
||||
result = &op_node->op;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//~ String Generation
|
||||
|
||||
MD_FUNCTION void
|
||||
|
||||
+54
-82
@@ -7,56 +7,6 @@
|
||||
#ifndef MD_H
|
||||
#define MD_H
|
||||
|
||||
/* NOTE(allen): Notes on overrides/macro options:
|
||||
**
|
||||
** Overridable :
|
||||
** "memset" ** REQUIRED (default crt-based implementation available)
|
||||
** #define MD_IMPL_Memset (void*, int, MD_u64) -> void*
|
||||
** #define MD_IMPL_Memmove (void*, void*, MD_u64) -> void*
|
||||
**
|
||||
** "file iteration" ** OPTIONAL
|
||||
** #define MD_IMPL_FileIterBegin (MD_FileIter*, MD_String8) -> MD_b32
|
||||
** #define MD_IMPL_FileIterNext (MD_Arena*, MD_FileIter*) -> MD_FileInfo
|
||||
** #define MD_IMPL_FileIterEnd (MD_FileIter*) -> void
|
||||
**
|
||||
** "file load" ** OPTIONAL
|
||||
** #define MD_IMPL_LoadEntireFile (MD_Arena*, MD_String8 filename) -> MD_String8
|
||||
**
|
||||
** "low level memory" ** OPTIONAL (required for default arena)
|
||||
** #define MD_IMPL_Reserve (MD_u64) -> void*
|
||||
** #define MD_IMPL_Commit (void*, MD_u64) -> MD_b32
|
||||
** #define MD_IMPL_Decommit (void*, MD_u64) -> void
|
||||
** #define MD_IMPL_Release (void*, MD_u64) -> void
|
||||
**
|
||||
** "arena" ** REQUIRED (default implementation available)
|
||||
** #define MD_IMPL_Arena <type>
|
||||
** #define MD_IMPL_ArenaAlloc () -> MD_IMPL_Arena*
|
||||
** #define MD_IMPL_ArenaRelease (MD_IMPL_Arena*) -> void
|
||||
** #define MD_IMPL_ArenaGetPos (MD_IMPL_Arena*) -> MD_u64
|
||||
** #define MD_IMPL_ArenaPush (MD_IMPL_Arena*, MD_u64) -> void*
|
||||
** #define MD_IMPL_ArenaPopTo (MD_IMPL_Arena*, MD_u64) -> void
|
||||
** #define MD_IMPL_ArenaSetAutoAlign (MD_IMPL_Arena*, MD_u64) -> void
|
||||
** #define MD_IMPL_ArenaHeaderSize MD_u64
|
||||
**
|
||||
** "scratch" ** REQUIRED (default implementation available)
|
||||
** #define MD_IMPL_GetScratch (MD_IMPL_Arena**, MD_u64) -> MD_IMPL_Arena*
|
||||
** "scratch constants" ** OPTIONAL (required for default scratch)
|
||||
** #define MD_IMPL_ScratchCount MD_u64 / default 2
|
||||
**
|
||||
** "sprintf" ** OPTIONAL (default implementation available)
|
||||
** #define MD_IMPL_Vsnprintf (char * buf, int count, char const * fmt, va_list va) -> int
|
||||
**
|
||||
** Default Implementation Controls
|
||||
** These controls default to '1' i.e. 'enabled'
|
||||
** #define MD_DEFAULT_MEMSET -> construct "memset" from CRT
|
||||
** #define MD_DEFAULT_FILE_ITER -> construct "file iteration" from OS headers
|
||||
** #define MD_DEFAULT_MEMORY -> construct "low level memory" from OS headers
|
||||
** #define MD_DEFAULT_ARENA -> construct "arena" from "low level memory"
|
||||
** #define MD_DEFAULT_SCRATCH -> construct "scratch" from "arena"
|
||||
** #define MD_DEFAULT_SPRINTF -> construct "vsnprintf" from internal implementaion
|
||||
**
|
||||
*/
|
||||
|
||||
//~ Set default values for controls
|
||||
#if !defined(MD_DEFAULT_MEMSET)
|
||||
# define MD_DEFAULT_MEMSET 1
|
||||
@@ -768,45 +718,44 @@ struct MD_ParseResult
|
||||
|
||||
//~ Expression Parsing
|
||||
|
||||
typedef enum MD_ExprOperatorKind
|
||||
typedef enum MD_ExprOprKind
|
||||
{
|
||||
MD_ExprOperatorKind_Null,
|
||||
// TODO(mal): Improve this naming scheme ?
|
||||
MD_ExprOperatorKind_Prefix,
|
||||
MD_ExprOperatorKind_Postfix,
|
||||
MD_ExprOperatorKind_Binary,
|
||||
MD_ExprOperatorKind_BinaryRightAssociative,
|
||||
MD_ExprOperatorKind_COUNT,
|
||||
} MD_ExprOperatorKind;
|
||||
MD_ExprOprKind_Null,
|
||||
MD_ExprOprKind_Prefix,
|
||||
MD_ExprOprKind_Postfix,
|
||||
MD_ExprOprKind_Binary,
|
||||
MD_ExprOprKind_BinaryRightAssociative,
|
||||
MD_ExprOprKind_COUNT,
|
||||
} MD_ExprOprKind;
|
||||
|
||||
typedef struct MD_ExprOperator MD_ExprOperator;
|
||||
struct MD_ExprOperator
|
||||
typedef struct MD_ExprOpr MD_ExprOpr;
|
||||
struct MD_ExprOpr
|
||||
{
|
||||
MD_u32 op_id;
|
||||
MD_ExprOperatorKind kind;
|
||||
MD_ExprOprKind kind;
|
||||
MD_u32 precedence;
|
||||
MD_Node *md_node;
|
||||
MD_Node *md_node__;
|
||||
};
|
||||
|
||||
typedef struct MD_ExprOperatorNode MD_ExprOperatorNode;
|
||||
struct MD_ExprOperatorNode
|
||||
typedef struct MD_ExprOprNode MD_ExprOprNode;
|
||||
struct MD_ExprOprNode
|
||||
{
|
||||
struct MD_ExprOperatorNode *next;
|
||||
MD_ExprOperator op;
|
||||
struct MD_ExprOprNode *next;
|
||||
MD_ExprOpr op;
|
||||
};
|
||||
|
||||
typedef struct MD_ExprOperatorList MD_ExprOperatorList;
|
||||
struct MD_ExprOperatorList
|
||||
typedef struct MD_ExprOprList MD_ExprOprList;
|
||||
struct MD_ExprOprList
|
||||
{
|
||||
MD_ExprOperatorNode *first;
|
||||
MD_ExprOperatorNode *last;
|
||||
MD_ExprOprNode *first;
|
||||
MD_ExprOprNode *last;
|
||||
MD_u64 count;
|
||||
};
|
||||
|
||||
typedef struct MD_ExprOperatorTable MD_ExprOperatorTable;
|
||||
struct MD_ExprOperatorTable
|
||||
typedef struct MD_ExprOprTable MD_ExprOprTable;
|
||||
struct MD_ExprOprTable
|
||||
{
|
||||
MD_ExprOperatorList table[MD_ExprOperatorKind_COUNT]; // TODO(mal): Hash?
|
||||
MD_ExprOprList table[MD_ExprOprKind_COUNT]; // TODO(mal): Hash?
|
||||
MD_MessageList errors;
|
||||
};
|
||||
|
||||
@@ -819,6 +768,7 @@ struct MD_ExprNode
|
||||
MD_b32 is_op;
|
||||
MD_u32 op_id;
|
||||
MD_Node *md_node;
|
||||
// TODO(allen): could md_op_node actually be void* ?
|
||||
MD_Node *md_op_node;
|
||||
};
|
||||
|
||||
@@ -829,6 +779,24 @@ struct MD_ExprParseResult
|
||||
MD_MessageList errors;
|
||||
};
|
||||
|
||||
// TODO(allen): nil MD_ExprNode
|
||||
|
||||
typedef struct MD_ExprParseCtx MD_ExprParseCtx;
|
||||
struct MD_ExprParseCtx
|
||||
{
|
||||
MD_ExprOprTable *op_table;
|
||||
MD_Node *original_first;
|
||||
MD_Node *first;
|
||||
MD_Node *one_past_last;
|
||||
|
||||
struct{
|
||||
MD_ExprOpr *call_op;
|
||||
MD_ExprOpr *subscript_op;
|
||||
MD_ExprOpr *bracket_set_op;
|
||||
MD_ExprOpr *brace_set_op;
|
||||
} accel;
|
||||
};
|
||||
|
||||
//~ String Generation Types
|
||||
|
||||
typedef MD_u32 MD_GenerateFlags;
|
||||
@@ -1049,9 +1017,9 @@ MD_FUNCTION MD_MapSlot* MD_MapOverwrite(MD_Arena *arena, MD_Map *map, MD_MapKey
|
||||
MD_FUNCTION MD_b32 MD_TokenGroupContainsKind(MD_TokenGroups groups, MD_TokenKind kind);
|
||||
MD_FUNCTION MD_Token MD_TokenFromString(MD_String8 string);
|
||||
MD_FUNCTION MD_u64 MD_LexAdvanceFromSkips(MD_String8 string, MD_TokenKind skip_kinds);
|
||||
MD_FUNCTION MD_Message * MD_MakeNodeError(MD_Arena *arena, MD_Node *node,
|
||||
MD_FUNCTION MD_Message* MD_MakeNodeError(MD_Arena *arena, MD_Node *node,
|
||||
MD_MessageKind kind, MD_String8 str);
|
||||
MD_FUNCTION MD_Message * MD_MakeTokenError(MD_Arena *arena, MD_String8 parse_contents,
|
||||
MD_FUNCTION MD_Message* MD_MakeTokenError(MD_Arena *arena, MD_String8 parse_contents,
|
||||
MD_Token token, MD_MessageKind kind,
|
||||
MD_String8 str);
|
||||
MD_FUNCTION void MD_MessageListPush(MD_MessageList *list, MD_Message *message);
|
||||
@@ -1136,16 +1104,20 @@ MD_FUNCTION MD_b32 MD_NodeDeepMatch(MD_Node *a, MD_Node *b, MD_MatchFlags flags)
|
||||
|
||||
//~ Expression Parsing
|
||||
|
||||
MD_FUNCTION void MD_ExprOperatorPush(MD_Arena *arena, MD_ExprOperatorList *list,
|
||||
MD_u32 op_id, MD_ExprOperatorKind kind,
|
||||
MD_u64 precedence, MD_Node *md_node);
|
||||
MD_FUNCTION void MD_ExprOprPush(MD_Arena *arena, MD_ExprOprList *list,
|
||||
MD_u32 op_id, MD_ExprOprKind kind,
|
||||
MD_u64 precedence, MD_Node *md_node);
|
||||
|
||||
MD_FUNCTION MD_ExprOperatorTable MD_ExprBakeOperatorTableFromList(MD_Arena *arena,
|
||||
MD_ExprOperatorList *list);
|
||||
MD_FUNCTION MD_ExprOprTable MD_ExprBakeOperatorTableFromList(MD_Arena *arena,
|
||||
MD_ExprOprList *list);
|
||||
|
||||
MD_FUNCTION MD_ExprParseResult MD_ExprParse(MD_Arena *arena, MD_ExprOperatorTable *op_table,
|
||||
MD_FUNCTION MD_ExprParseResult MD_ExprParse(MD_Arena *arena, MD_ExprOprTable *op_table,
|
||||
MD_Node *first, MD_Node *one_past_last);
|
||||
|
||||
|
||||
MD_FUNCTION MD_ExprOpr* MD_ExprOprFromKindString(MD_ExprOprTable *table,
|
||||
MD_ExprOprKind kind, MD_String8 s);
|
||||
|
||||
//~ String Generation
|
||||
|
||||
MD_FUNCTION void MD_DebugDumpFromNode(MD_Arena *arena, MD_String8List *out, MD_Node *node,
|
||||
|
||||
+23
-23
@@ -23,7 +23,7 @@ struct Expression_QA
|
||||
typedef struct OperatorDescription OperatorDescription;
|
||||
struct OperatorDescription{
|
||||
MD_String8 s;
|
||||
MD_ExprOperator op;
|
||||
MD_ExprOpr op;
|
||||
};
|
||||
|
||||
// NOTE(mal): Based on https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence 2021-09-05
|
||||
@@ -126,8 +126,8 @@ static void parenthesize_exclude_outer(MD_Arena *arena, OperatorDescription *des
|
||||
MD_S8ListPush(arena, l, MD_S8Lit("("));
|
||||
}
|
||||
|
||||
MD_ExprOperator *op = &descs[node->op_id].op;
|
||||
if(op->kind == MD_ExprOperatorKind_Binary || op->kind == MD_ExprOperatorKind_BinaryRightAssociative)
|
||||
MD_ExprOpr *op = &descs[node->op_id].op;
|
||||
if(op->kind == MD_ExprOprKind_Binary || op->kind == MD_ExprOprKind_BinaryRightAssociative)
|
||||
{
|
||||
|
||||
parenthesize_exclude_outer(arena, descs, l, node->left, 0);
|
||||
@@ -147,7 +147,7 @@ static void parenthesize_exclude_outer(MD_Arena *arena, OperatorDescription *des
|
||||
parenthesize_exclude_outer(arena, descs, l, node->right, 0);
|
||||
}
|
||||
}
|
||||
else if(op->kind == MD_ExprOperatorKind_Prefix)
|
||||
else if(op->kind == MD_ExprOprKind_Prefix)
|
||||
{
|
||||
MD_S8ListPush(arena, l, node->md_node->string);
|
||||
MD_u8 last_op_c = MD_S8Suffix(node->md_node->string, 1).str[0];
|
||||
@@ -159,7 +159,7 @@ static void parenthesize_exclude_outer(MD_Arena *arena, OperatorDescription *des
|
||||
|
||||
parenthesize_exclude_outer(arena, descs, l, node->left, 0);
|
||||
}
|
||||
else if(op->kind == MD_ExprOperatorKind_Postfix)
|
||||
else if(op->kind == MD_ExprOprKind_Postfix)
|
||||
{
|
||||
parenthesize_exclude_outer(arena, descs, l, node->left, 0);
|
||||
|
||||
@@ -223,7 +223,7 @@ int main(void)
|
||||
OperatorDescription operator_array[Op_COUNT] = {0};
|
||||
#define X(name, token, kind_, prec) \
|
||||
operator_array[Op_##name].s = MD_S8Lit(token); \
|
||||
operator_array[Op_##name].op = (MD_ExprOperator){ .op_id = Op_##name, .kind = MD_ExprOperatorKind_##kind_, .precedence = prec };
|
||||
operator_array[Op_##name].op = (MD_ExprOpr){ .op_id = Op_##name, .kind = MD_ExprOprKind_##kind_, .precedence = prec };
|
||||
OPERATORS
|
||||
#undef X
|
||||
|
||||
@@ -231,8 +231,8 @@ operator_array[Op_##name].op = (MD_ExprOperator){ .op_id = Op_##name, .kind = MD
|
||||
|
||||
/* NOTE: Operator table bake errors */
|
||||
{
|
||||
MD_ExprOperatorList operator_list = {0};
|
||||
MD_ExprOperatorTable op_table = {0};
|
||||
MD_ExprOprList operator_list = {0};
|
||||
MD_ExprOprTable op_table = {0};
|
||||
|
||||
MD_String8 plus = MD_S8Lit("+");
|
||||
MD_String8 minus = MD_S8Lit("-");
|
||||
@@ -241,49 +241,49 @@ operator_array[Op_##name].op = (MD_ExprOperator){ .op_id = Op_##name, .kind = MD
|
||||
MD_Node *plus_node_bis = MD_MakeNode(arena, MD_NodeKind_Main, plus, plus, 0);
|
||||
|
||||
// NOTE: Wrong operator kind
|
||||
operator_list = (MD_ExprOperatorList){0};
|
||||
MD_ExprOperatorPush(arena, &operator_list, Op_Addition, MD_ExprOperatorKind_Null, 1, plus_node);
|
||||
operator_list = (MD_ExprOprList){0};
|
||||
MD_ExprOprPush(arena, &operator_list, Op_Addition, MD_ExprOprKind_Null, 1, plus_node);
|
||||
op_table = MD_ExprBakeOperatorTableFromList(arena, &operator_list);
|
||||
MD_Assert(op_table.errors.max_message_kind = MD_MessageKind_Warning && op_table.errors.node_count == 1 &&
|
||||
op_table.errors.first->node == plus_node);
|
||||
|
||||
// NOTE: Repeat operator
|
||||
operator_list = (MD_ExprOperatorList){0};
|
||||
MD_ExprOperatorPush(arena, &operator_list, Op_Addition, MD_ExprOperatorKind_Binary, 1, plus_node);
|
||||
MD_ExprOperatorPush(arena, &operator_list, Op_Addition, MD_ExprOperatorKind_Binary, 1, plus_node_bis);
|
||||
operator_list = (MD_ExprOprList){0};
|
||||
MD_ExprOprPush(arena, &operator_list, Op_Addition, MD_ExprOprKind_Binary, 1, plus_node);
|
||||
MD_ExprOprPush(arena, &operator_list, Op_Addition, MD_ExprOprKind_Binary, 1, plus_node_bis);
|
||||
op_table = MD_ExprBakeOperatorTableFromList(arena, &operator_list);
|
||||
MD_Assert(op_table.errors.max_message_kind = MD_MessageKind_Warning && op_table.errors.node_count == 1 &&
|
||||
op_table.errors.first->node == plus_node_bis);
|
||||
|
||||
operator_list = (MD_ExprOperatorList){0};
|
||||
operator_list = (MD_ExprOprList){0};
|
||||
// NOTE: Binary-postfix operator conflict
|
||||
MD_ExprOperatorPush(arena, &operator_list, Op_Addition, MD_ExprOperatorKind_Binary, 1, plus_node);
|
||||
MD_ExprOperatorPush(arena, &operator_list, Op_Addition, MD_ExprOperatorKind_Postfix, 1, plus_node_bis);
|
||||
MD_ExprOprPush(arena, &operator_list, Op_Addition, MD_ExprOprKind_Binary, 1, plus_node);
|
||||
MD_ExprOprPush(arena, &operator_list, Op_Addition, MD_ExprOprKind_Postfix, 1, plus_node_bis);
|
||||
op_table = MD_ExprBakeOperatorTableFromList(arena, &operator_list);
|
||||
MD_Assert(op_table.errors.max_message_kind = MD_MessageKind_Warning && op_table.errors.node_count == 1 &&
|
||||
op_table.errors.first->node == plus_node_bis);
|
||||
|
||||
operator_list = (MD_ExprOperatorList){0};
|
||||
operator_list = (MD_ExprOprList){0};
|
||||
// NOTE: Same precedence difference associativity conflict
|
||||
MD_ExprOperatorPush(arena, &operator_list, Op_Addition, MD_ExprOperatorKind_Binary, 1, plus_node);
|
||||
MD_ExprOperatorPush(arena, &operator_list, Op_Addition, MD_ExprOperatorKind_BinaryRightAssociative,
|
||||
1, minus_node);
|
||||
MD_ExprOprPush(arena, &operator_list, Op_Addition, MD_ExprOprKind_Binary, 1, plus_node);
|
||||
MD_ExprOprPush(arena, &operator_list, Op_Addition, MD_ExprOprKind_BinaryRightAssociative,
|
||||
1, minus_node);
|
||||
op_table = MD_ExprBakeOperatorTableFromList(arena, &operator_list);
|
||||
MD_Assert(op_table.errors.max_message_kind = MD_MessageKind_Warning && op_table.errors.node_count == 1 &&
|
||||
op_table.errors.first->node == minus_node);
|
||||
|
||||
}
|
||||
|
||||
MD_ExprOperatorList operator_list = {0};
|
||||
MD_ExprOprList operator_list = {0};
|
||||
|
||||
for(Op op = Op_Null+1; op < Op_COUNT; ++op)
|
||||
{
|
||||
OperatorDescription *desc = operator_array + op;
|
||||
MD_Node *node = MD_MakeNode(arena, MD_NodeKind_Main, desc->s, desc->s, 0);
|
||||
MD_ExprOperatorPush(arena, &operator_list, op, desc->op.kind, desc->op.precedence, node);
|
||||
MD_ExprOprPush(arena, &operator_list, op, desc->op.kind, desc->op.precedence, node);
|
||||
}
|
||||
|
||||
MD_ExprOperatorTable op_table = MD_ExprBakeOperatorTableFromList(arena, &operator_list);
|
||||
MD_ExprOprTable op_table = MD_ExprBakeOperatorTableFromList(arena, &operator_list);
|
||||
|
||||
// NOTE(mal): I'm trying something different for expression parser tests. Normally one would take the
|
||||
// output of MD_ExprParse and compare it against the expected output expression tree.
|
||||
|
||||
Reference in New Issue
Block a user