Improved parser scope errors.

Added the caret for indicating where the error is.
This commit is contained in:
Edward R. Gonzalez 2023-07-29 17:14:02 -04:00
parent b9064fba9d
commit 03df940085
5 changed files with 64 additions and 54 deletions

View File

@ -33,8 +33,8 @@ namespace Parser
Entry( BraceSquare_Close, "]" ) \ Entry( BraceSquare_Close, "]" ) \
Entry( Capture_Start, "(" ) \ Entry( Capture_Start, "(" ) \
Entry( Capture_End, ")" ) \ Entry( Capture_End, ")" ) \
Entry( Comment, "__comment__" ) \ Entry( Comment, "comment" ) \
Entry( Char, "__char__" ) \ Entry( Char, "character" ) \
Entry( Comma, "," ) \ Entry( Comma, "," ) \
Entry( Decl_Class, "class" ) \ Entry( Decl_Class, "class" ) \
Entry( Decl_GNU_Attribute, "__attribute__" ) \ Entry( Decl_GNU_Attribute, "__attribute__" ) \
@ -50,7 +50,7 @@ namespace Parser
Entry( Decl_Typedef, "typedef" ) \ Entry( Decl_Typedef, "typedef" ) \
Entry( Decl_Using, "using" ) \ Entry( Decl_Using, "using" ) \
Entry( Decl_Union, "union" ) \ Entry( Decl_Union, "union" ) \
Entry( Identifier, "__identifier__" ) \ Entry( Identifier, "identifier" ) \
Entry( Module_Import, "import" ) \ Entry( Module_Import, "import" ) \
Entry( Module_Export, "export" ) \ Entry( Module_Export, "export" ) \
Entry( Number, "number" ) \ Entry( Number, "number" ) \
@ -80,7 +80,7 @@ namespace Parser
Entry( Spec_Volatile, "volatile") \ Entry( Spec_Volatile, "volatile") \
Entry( Star, "*" ) \ Entry( Star, "*" ) \
Entry( Statement_End, ";" ) \ Entry( Statement_End, ";" ) \
Entry( String, "__string__" ) \ Entry( String, "string" ) \
Entry( Type_Unsigned, "unsigned" ) \ Entry( Type_Unsigned, "unsigned" ) \
Entry( Type_Signed, "signed" ) \ Entry( Type_Signed, "signed" ) \
Entry( Type_Short, "short" ) \ Entry( Type_Short, "short" ) \

View File

@ -82,6 +82,7 @@ namespace Parser
{ {
StackNode* Prev; StackNode* Prev;
Token Start;
Token Name; // The name of the AST node (if parsed) Token Name; // The name of the AST node (if parsed)
StrC ProcName; // The name of the procedure StrC ProcName; // The name of the procedure
}; };
@ -91,44 +92,6 @@ namespace Parser
TokArray Tokens; TokArray Tokens;
StackNode* Scope; StackNode* Scope;
String to_string()
{
String result = String::make_reserve( GlobalAllocator, kilobytes(4) );
result.append_fmt("\tContext:\n");
Token last_valid = Tokens.Idx >= Tokens.Arr.num() ? Tokens.Arr[Tokens.Arr.num() -1] : Tokens.current();
char const* current = last_valid.Text;
sptr length = last_valid.Length;
while ( current <= Tokens.Arr.back().Text && *current != '\n' )
{
current++;
length++;
}
String line = String::make( GlobalAllocator, { length, last_valid.Text } );
result.append_fmt("\t(%d, %d): %s\n", last_valid.Line, last_valid.Column, line );
line.free();
StackNode* curr_scope = Scope;
do
{
if ( curr_scope->Name )
{
result.append_fmt("\tProcedure: %s, AST Name: %s\n", curr_scope->ProcName.Ptr, (StrC)curr_scope->Name );
}
else
{
result.append_fmt("\tProcedure: %s\n", curr_scope->ProcName.Ptr );
}
curr_scope = curr_scope->Prev;
}
while ( curr_scope );
return result;
}
void push( StackNode* node ) void push( StackNode* node )
{ {
node->Prev = Scope; node->Prev = Scope;
@ -139,6 +102,51 @@ namespace Parser
{ {
Scope = Scope->Prev; Scope = Scope->Prev;
} }
String to_string()
{
String result = String::make_reserve( GlobalAllocator, kilobytes(4) );
Token scope_start = Scope->Start;
Token last_valid = Tokens.Idx >= Tokens.Arr.num() ? Tokens.Arr[Tokens.Arr.num() -1] : Tokens.current();
sptr length = scope_start.Length;
char const* current = scope_start.Text + length;
while ( current <= Tokens.Arr.back().Text && *current != '\n' && length < 74 )
{
current++;
length++;
}
String line = String::make( GlobalAllocator, { length, scope_start.Text } );
result.append_fmt("\tScope: %s\n", line );
line.free();
sptr dist = (sptr)last_valid.Text - (sptr)scope_start.Text;
sptr length_from_err = dist;
String line_from_err = String::make( GlobalAllocator, { length_from_err, last_valid.Text } );
result.append_fmt("\t(%d, %d):%*c\n", last_valid.Line, last_valid.Column, length_from_err, '^' );
StackNode* curr_scope = Scope;
s32 level = 0;
do
{
if ( curr_scope->Name )
{
result.append_fmt("\t%d: %s, AST Name: %s\n", level, curr_scope->ProcName.Ptr, (StrC)curr_scope->Name );
}
else
{
result.append_fmt("\t%d: %s\n", level, curr_scope->ProcName.Ptr );
}
curr_scope = curr_scope->Prev;
level++;
}
while ( curr_scope );
return result;
}
}; };
global ParseContext Context; global ParseContext Context;
@ -155,7 +163,7 @@ namespace Parser
{ {
String token_str = String::make( GlobalAllocator, { Arr[Idx].Length, Arr[Idx].Text } ); String token_str = String::make( GlobalAllocator, { Arr[Idx].Length, Arr[Idx].Text } );
log_failure( "Parse Error, TokArray::eat, Expected: %s, not %s (%d, %d)`\n%s", ETokType::to_str(type), token_str, Context.to_string() ); log_failure( "Parse Error, TokArray::eat, Expected: %s, not '%s' (%d, %d)`\n%s", ETokType::to_str(type), token_str, current().Line, current().Column, Context.to_string() );
return false; return false;
} }
@ -727,7 +735,7 @@ if ( def.Ptr == nullptr )
# define check( Type_ ) ( left && currtok.Type == Type_ ) # define check( Type_ ) ( left && currtok.Type == Type_ )
# define push_scope() \ # define push_scope() \
StackNode scope { nullptr, NullToken, txt_StrC( __func__ ) }; \ StackNode scope { nullptr, currtok, NullToken, txt_StrC( __func__ ) }; \
Context.push( & scope ) Context.push( & scope )
#pragma endregion Helper Macros #pragma endregion Helper Macros
@ -1796,8 +1804,7 @@ Code parse_class_struct( Parser::TokType which )
attributes = parse_attributes(); attributes = parse_attributes();
if ( check( TokType::Identifier ) ) name = parse_identifier();
name = parse_identifier();
local_persist local_persist
char interface_arr_mem[ kilobytes(4) ] {0}; char interface_arr_mem[ kilobytes(4) ] {0};
@ -2649,7 +2656,10 @@ CodeStruct parse_struct( StrC def )
return CodeInvalid; return CodeInvalid;
Context.Tokens = toks; Context.Tokens = toks;
return (CodeStruct) parse_class_struct( TokType::Decl_Struct ); push_scope();
CodeStruct result = (CodeStruct) parse_class_struct( TokType::Decl_Struct );
Context.pop();
return result;
} }
internal internal

View File

@ -5,7 +5,7 @@ void assert_handler( char const* condition, char const* file, s32 line, char con
_printf_err( "%s:(%d): Assert Failure: ", file, line ); _printf_err( "%s:(%d): Assert Failure: ", file, line );
if ( condition ) if ( condition )
_printf_err( "`%s` ", condition ); _printf_err( "`%s` \n", condition );
if ( msg ) if ( msg )
{ {

View File

@ -15,8 +15,8 @@ BraceSquare_Open, "["
BraceSquare_Close, "]" BraceSquare_Close, "]"
Capture_Start, "(" Capture_Start, "("
Capture_End, ")" Capture_End, ")"
Comment, "__comment__" Comment, "comemnt"
Char, "__char__" Char, "character"
Comma, "," Comma, ","
Decl_Class, "class" Decl_Class, "class"
Decl_GNU_Attribute, "__attribute__" Decl_GNU_Attribute, "__attribute__"
@ -32,7 +32,7 @@ Decl_Template, "template"
Decl_Typedef, "typedef" Decl_Typedef, "typedef"
Decl_Using, "using" Decl_Using, "using"
Decl_Union, "union" Decl_Union, "union"
Identifier, "__identifier__" Identifier, "identifier"
Module_Import, "import" Module_Import, "import"
Module_Export, "export" Module_Export, "export"
Number, "number" Number, "number"
@ -62,7 +62,7 @@ Spec_ThreadLocal, "thread_local"
Spec_Volatile, "volatile" Spec_Volatile, "volatile"
Star, "*" Star, "*"
Statement_End, ";" Statement_End, ";"
String, "__string__" String, "string"
Type_Unsigned, "unsigned" Type_Unsigned, "unsigned"
Type_Signed, "signed" Type_Signed, "signed"
Type_Short, "short" Type_Short, "short"

1 Invalid __invalid__
15 BraceSquare_Close ]
16 Capture_Start (
17 Capture_End )
18 Comment __comment__ comemnt
19 Char __char__ character
20 Comma ,
21 Decl_Class class
22 Decl_GNU_Attribute __attribute__
32 Decl_Typedef typedef
33 Decl_Using using
34 Decl_Union union
35 Identifier __identifier__ identifier
36 Module_Import import
37 Module_Export export
38 Number number
62 Spec_Volatile volatile
63 Star *
64 Statement_End ;
65 String __string__ string
66 Type_Unsigned unsigned
67 Type_Signed signed
68 Type_Short short

View File

@ -12,9 +12,9 @@ int gen_main()
using namespace gen; using namespace gen;
log_fmt("\ngen_time:"); log_fmt("\ngen_time:");
// check_sanity(); check_sanity();
checkSOA(); check_SOA();
return 0; return 0;
} }