Skip to content

Commit

Permalink
Diagnostics: Various changes to fix crashes with invalid sources (#611)
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinEady committed Feb 3, 2024
1 parent 3775eb5 commit 2779edb
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 36 deletions.
4 changes: 2 additions & 2 deletions lib/Parser/EscriptGrammar/EscriptLexer.cpp
Expand Up @@ -571,7 +571,7 @@ void EscriptLexer::INTERPOLATED_STRING_STARTAction(antlr4::RuleContext *context,
void EscriptLexer::LBRACEAction(antlr4::RuleContext *context, size_t actionIndex) {
switch (actionIndex) {
case 1:
if ( interpolatedStringLevel > 0 )
if ( interpolatedStringLevel > 0 && !curlyLevels.empty() )
{
auto currentLevel = curlyLevels.top();
curlyLevels.pop();
Expand All @@ -587,7 +587,7 @@ void EscriptLexer::LBRACEAction(antlr4::RuleContext *context, size_t actionIndex
void EscriptLexer::RBRACEAction(antlr4::RuleContext *context, size_t actionIndex) {
switch (actionIndex) {
case 2:
if ( interpolatedStringLevel > 0 )
if ( interpolatedStringLevel > 0 && !curlyLevels.empty() )
{
auto currentLevel = curlyLevels.top();
curlyLevels.pop();
Expand Down
4 changes: 2 additions & 2 deletions lib/Parser/EscriptGrammar/EscriptLexer.g4
Expand Up @@ -115,7 +115,7 @@ LBRACK: '[';
RBRACK: ']';
LBRACE: '{'
{
if ( interpolatedStringLevel > 0 )
if ( interpolatedStringLevel > 0 && !curlyLevels.empty() )
{
auto currentLevel = curlyLevels.top();
curlyLevels.pop();
Expand All @@ -124,7 +124,7 @@ LBRACE: '{'
};
RBRACE: '}'
{
if ( interpolatedStringLevel > 0 )
if ( interpolatedStringLevel > 0 && !curleyLevels.empty() )
{
auto currentLevel = curlyLevels.top();
curlyLevels.pop();
Expand Down
58 changes: 45 additions & 13 deletions pol-core/bscript/compiler/astbuilder/CompoundStatementBuilder.cpp
Expand Up @@ -73,7 +73,10 @@ void CompoundStatementBuilder::add_statements( EscriptParser::StatementContext*
}
else if ( auto foreach_statement = ctx->foreachStatement() )
{
statements.push_back( foreach_loop( foreach_statement ) );
if ( auto statement = foreach_loop( foreach_statement ) )
{
statements.push_back( std::move( statement ) );
}
}
else if ( auto for_st = ctx->forStatement() )
{
Expand Down Expand Up @@ -133,17 +136,20 @@ std::unique_ptr<BasicForLoop> CompoundStatementBuilder::basic_for_loop(
EscriptParser::BasicForStatementContext* ctx, std::string label )
{
auto identifier = text( ctx->IDENTIFIER() );
auto first = expression( ctx->expression( 0 ) );
auto last = expression( ctx->expression( 1 ) );
auto body = block( ctx->block() );
auto size = ctx->expression().size();
auto first = expression( size > 0 ? ctx->expression( 0 ) : nullptr );
auto last = expression( size > 1 ? ctx->expression( 1 ) : nullptr );
auto body = ctx->block() ? block( ctx->block() )
: std::make_unique<Block>( location_for( *ctx ),
std::vector<std::unique_ptr<Statement>>() );

return std::make_unique<BasicForLoop>( location_for( *ctx ), std::move( label ),
std::move( identifier ), std::move( first ),
std::move( last ), std::move( body ) );
}

std::vector<std::unique_ptr<Statement>> CompoundStatementBuilder::block_statements(
EscriptParser::BlockContext* ctx )
EscriptParser::BlockContext* ctx )
{
std::vector<std::unique_ptr<Statement>> statements;

Expand Down Expand Up @@ -228,10 +234,14 @@ std::unique_ptr<CaseStatement> CompoundStatementBuilder::case_statement(
std::unique_ptr<CstyleForLoop> CompoundStatementBuilder::cstyle_for_loop(
EscriptParser::CstyleForStatementContext* ctx, std::string label )
{
auto initializer = expression( ctx->expression( 0 ) );
auto predicate = expression( ctx->expression( 1 ) );
auto advancer = expression( ctx->expression( 2 ) );
auto body = block( ctx->block() );
auto size = ctx->expression().size();
auto initializer = expression( size > 0 ? ctx->expression( 0 ) : nullptr );
auto predicate = expression( size > 1 ? ctx->expression( 1 ) : nullptr );
auto advancer = expression( size > 2 ? ctx->expression( 2 ) : nullptr );
auto body = ctx->block() ? block( ctx->block() )
: std::make_unique<Block>( location_for( *ctx ),
std::vector<std::unique_ptr<Statement>>() );

return std::make_unique<CstyleForLoop>( location_for( *ctx ), std::move( label ),
std::move( initializer ), std::move( predicate ),
std::move( advancer ), std::move( body ) );
Expand All @@ -245,7 +255,9 @@ std::unique_ptr<DoWhileLoop> CompoundStatementBuilder::do_while_loop(
if ( auto statement_label = ctx->statementLabel() )
label = text( statement_label->IDENTIFIER() );
auto body = block( ctx->block() );
auto predicate = expression( ctx->parExpression()->expression() );
auto parExpression = ctx->parExpression();

auto predicate = expression( parExpression ? parExpression->expression() : nullptr );
return std::make_unique<DoWhileLoop>( source_location, std::move( label ), std::move( body ),
std::move( predicate ) );
}
Expand All @@ -261,6 +273,10 @@ std::unique_ptr<Statement> CompoundStatementBuilder::for_loop( EscriptParser::Fo
{
return basic_for_loop( basic, std::move( label ) );
}
else if ( workspace.continue_on_error )
{
return std::make_unique<EmptyStatement>( location_for( *ctx ) );
}
else
{
location_for( *ctx ).internal_error(
Expand Down Expand Up @@ -295,6 +311,10 @@ std::unique_ptr<Expression> CompoundStatementBuilder::foreach_iterable_expressio
{
return expression( par_ex->expression() );
}
else if ( workspace.continue_on_error )
{
return std::make_unique<UninitializedValue>( location_for( *ctx ) );
}
else
{
location_for( *ctx ).internal_error( "unhandled foreach iterable expression" );
Expand All @@ -308,7 +328,15 @@ std::unique_ptr<ForeachLoop> CompoundStatementBuilder::foreach_loop(
std::string label;
if ( auto statement_label = ctx->statementLabel() )
label = text( statement_label->IDENTIFIER() );
std::string iterator_name = text( ctx->IDENTIFIER() );
auto identifier = ctx->IDENTIFIER();
if ( identifier == nullptr )
return {};

auto foreachIterableExpression = ctx->foreachIterableExpression();
if ( !foreachIterableExpression )
return {};

std::string iterator_name = text( identifier );
auto iterable = foreach_iterable_expression( ctx->foreachIterableExpression() );
auto body = block( ctx->block() );
return std::make_unique<ForeachLoop>( source_location, std::move( label ),
Expand Down Expand Up @@ -337,7 +365,11 @@ std::unique_ptr<Statement> CompoundStatementBuilder::if_statement(
--clause_index;
auto expression_ctx = par_expression.at( clause_index );
auto expression_ast = expression( expression_ctx->expression() );
auto consequent_ast = block( blocks.at( clause_index ) );
auto consequent_ast =
blocks.size() > clause_index
? block( blocks.at( clause_index ) )
: std::make_unique<Block>( location_for( *ctx ),
std::vector<std::unique_ptr<Statement>>() );
auto alternative_ast =
if_statement_ast ? std::move( if_statement_ast ) : std::move( else_clause );
auto source_location = location_for( *expression_ctx );
Expand Down Expand Up @@ -384,7 +416,7 @@ std::unique_ptr<WhileLoop> CompoundStatementBuilder::while_loop(
auto predicate = expression( ctx->parExpression()->expression() );
auto body = block( ctx->block() );
return std::make_unique<WhileLoop>( source_location, std::move( label ), std::move( predicate ),
std::move( body ) );
std::move( body ) );
}

} // namespace Pol::Bscript::Compiler
20 changes: 15 additions & 5 deletions pol-core/bscript/compiler/astbuilder/ExpressionBuilder.cpp
Expand Up @@ -185,6 +185,8 @@ BTokenId ExpressionBuilder::binary_operator_token(
return TOK_CHKMEMBER;
else if ( ctx->DELMEMBER() )
return TOK_DELMEMBER;
else if ( workspace.continue_on_error )
return RSV_FUTURE;
else
location_for( *ctx ).internal_error( "unrecognized binary operator" );
}
Expand Down Expand Up @@ -246,9 +248,10 @@ std::unique_ptr<ConditionalOperator> ExpressionBuilder::conditional_operator(
{
auto source_location = location_for( *ctx );
auto expressions = ctx->expression();
auto conditional = expression( expressions[0] );
auto consequent = expression( expressions[1] );
auto alternate = expression( expressions[2] );
auto size = expressions.size();
auto conditional = expression( size > 0 ? expressions[0] : nullptr );
auto consequent = expression( size > 1 ? expressions[1] : nullptr );
auto alternate = expression( size > 2 ? expressions[2] : nullptr );

return std::make_unique<ConditionalOperator>( source_location, std::move( conditional ),
std::move( consequent ), std::move( alternate ) );
Expand Down Expand Up @@ -340,7 +343,7 @@ std::vector<std::unique_ptr<Expression>> ExpressionBuilder::expressions(
{
expressions.push_back( string_value( escaped, false ) );
}
else
else if ( !workspace.continue_on_error )
{
location_for( *interstringPart_ctx )
.internal_error( "unhandled context in interpolated string part" );
Expand All @@ -367,7 +370,10 @@ std::unique_ptr<Expression> ExpressionBuilder::expression( EscriptParser::Expres
bool consume )
{
std::unique_ptr<Expression> result;
if ( auto prim = ctx->primary() )
if ( ctx == nullptr )
result =
std::make_unique<UninitializedValue>( SourceLocation( &source_file_identifier, 0, 0 ) );
else if ( auto prim = ctx->primary() )
result = primary( prim );
else if ( ctx->prefix )
result = prefix_unary_operator( ctx );
Expand Down Expand Up @@ -464,6 +470,10 @@ std::unique_ptr<Expression> ExpressionBuilder::expression_suffix(
{
return method_call( std::move( lhs ), method );
}
else if ( workspace.continue_on_error )
{
return expression( nullptr );
}
else
{
location_for( *ctx ).internal_error( "unhandled navigation suffix" );
Expand Down
11 changes: 7 additions & 4 deletions pol-core/bscript/compiler/astbuilder/ProgramBuilder.cpp
Expand Up @@ -26,10 +26,13 @@ std::unique_ptr<Program> ProgramBuilder::program( EscriptParser::ProgramDeclarat
{
for ( auto param : param_list->programParameter() )
{
auto name = text( param->IDENTIFIER() );
bool unused = param->UNUSED() != nullptr;
parameter_declarations.push_back( std::make_unique<ProgramParameterDeclaration>(
location_for( *param ), std::move( name ), unused ) );
if ( auto identifier = param->IDENTIFIER() )
{
auto name = text( identifier );
bool unused = param->UNUSED() != nullptr;
parameter_declarations.push_back( std::make_unique<ProgramParameterDeclaration>(
location_for( *param ), std::move( name ), unused ) );
}
}
}
}
Expand Down
21 changes: 18 additions & 3 deletions pol-core/bscript/compiler/astbuilder/SimpleStatementBuilder.cpp
Expand Up @@ -43,7 +43,13 @@ void SimpleStatementBuilder::add_var_statements(
{
auto loc = location_for( *decl );
auto var_decl_location = has_multiple_decls ? loc : location_for( *ctx->VAR() );
std::string name = text( decl->IDENTIFIER() );
auto identifier = decl->IDENTIFIER();
if ( !identifier )
{
continue;
}

std::string name = text( identifier );
std::unique_ptr<VarStatement> var_ast;

if ( auto initializer_context = decl->variableDeclarationInitializer() )
Expand Down Expand Up @@ -83,12 +89,21 @@ std::unique_ptr<ConstDeclaration> SimpleStatementBuilder::const_declaration(
EscriptParser::ConstStatementContext* ctx )
{
auto variable_declaration = ctx->constantDeclaration();
if ( !variable_declaration )
{
return std::make_unique<ConstDeclaration>( location_for( *ctx ), "", expression( nullptr ) );
}

auto identifier = text( variable_declaration->IDENTIFIER() );
auto expression_context = variable_declaration->variableDeclarationInitializer()->expression();
auto variableDeclarationInitializer = variable_declaration->variableDeclarationInitializer();

auto expression_context =
variableDeclarationInitializer ? variableDeclarationInitializer->expression() : nullptr;

auto value = expression( expression_context );

return std::make_unique<ConstDeclaration>( location_for( *ctx ), std::move( identifier ),
std::move( value ) );
std::move( value ) );
}

std::unique_ptr<JumpStatement> SimpleStatementBuilder::continue_statement(
Expand Down
19 changes: 12 additions & 7 deletions pol-core/bscript/compiler/astbuilder/SourceFileProcessor.cpp
Expand Up @@ -135,6 +135,8 @@ void SourceFileProcessor::handle_include_declaration( EscriptParser::IncludeDecl
include_name = tree_builder.unquote( string_literal );
else if ( auto identifier = ctx->stringIdentifier()->IDENTIFIER() )
include_name = identifier->getSymbol()->getText();
else if ( workspace.continue_on_error )
return;
else
source_location.internal_error(
"Unable to include module: expected a string literal or identifier.\n" );
Expand Down Expand Up @@ -292,12 +294,15 @@ void SourceFileProcessor::handle_use_declaration( EscriptParser::UseDeclarationC
antlrcpp::Any SourceFileProcessor::visitFunctionDeclaration(
EscriptParser::FunctionDeclarationContext* ctx )
{
auto loc = location_for( *ctx );
workspace.function_resolver.register_available_user_function( loc, ctx );
const std::string& function_name = tree_builder.text( ctx->IDENTIFIER() );
workspace.compiler_workspace.all_function_locations.emplace( function_name, loc );
if ( user_function_inclusion == UserFunctionInclusion::All )
workspace.function_resolver.force_reference( function_name, loc );
if ( auto identifier = ctx->IDENTIFIER() )
{
auto loc = location_for( *ctx );
workspace.function_resolver.register_available_user_function( loc, ctx );
const std::string& function_name = tree_builder.text( identifier );
workspace.compiler_workspace.all_function_locations.emplace( function_name, loc );
if ( user_function_inclusion == UserFunctionInclusion::All )
workspace.function_resolver.force_reference( function_name, loc );
}
return antlrcpp::Any();
}

Expand All @@ -323,7 +328,7 @@ antlrcpp::Any SourceFileProcessor::visitProgramDeclaration(
" Other declaration: {}",
workspace.compiler_workspace.program->source_location );
}
else
else if ( ctx->IDENTIFIER() )
{
workspace.compiler_workspace.program = tree_builder.program( ctx );
}
Expand Down
2 changes: 2 additions & 0 deletions pol-core/bscript/compiler/astbuilder/TreeBuilder.cpp
Expand Up @@ -33,6 +33,8 @@ SourceLocation TreeBuilder::location_for( antlr4::tree::TerminalNode& ctx ) cons

std::string TreeBuilder::text( antlr4::tree::TerminalNode* terminal )
{
if ( !terminal )
return "";
return terminal->getSymbol()->getText();
}

Expand Down
4 changes: 4 additions & 0 deletions pol-core/bscript/compiler/astbuilder/ValueBuilder.cpp
Expand Up @@ -224,11 +224,15 @@ int ValueBuilder::to_int( EscriptParser::IntegerLiteralContext* ctx )
catch ( std::invalid_argument& )
{
report.error( location_for( *ctx ), "unable to convert integer value '{}'.", ctx->getText() );
if ( workspace.continue_on_error )
return 0;
throw;
}
catch ( std::out_of_range& )
{
report.error( location_for( *ctx ), "integer value '{}' out of range.", ctx->getText() );
if ( workspace.continue_on_error )
return 0;
throw;
}

Expand Down

0 comments on commit 2779edb

Please sign in to comment.