[expr parser] getting familiar with the expression parser

This commit is contained in:
Allen Webster
2021-10-01 20:03:50 -07:00
parent e36e0de276
commit 4ce22d786c
6 changed files with 246 additions and 213 deletions
+4 -1
View File
@@ -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 ###########################################################
+9
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.