2020-08-18 03:07:51 -07:00
|
|
|
#include "ExpressionBuilder.h"
|
|
|
|
|
|
2021-02-25 16:53:22 +01:00
|
|
|
#include "bscript/compiler/Report.h"
|
|
|
|
|
#include "bscript/compiler/ast/Argument.h"
|
|
|
|
|
#include "bscript/compiler/ast/ArrayInitializer.h"
|
|
|
|
|
#include "bscript/compiler/ast/BinaryOperator.h"
|
2024-01-20 12:38:25 +08:00
|
|
|
#include "bscript/compiler/ast/BooleanValue.h"
|
2021-03-14 23:20:20 +01:00
|
|
|
#include "bscript/compiler/ast/ConditionalOperator.h"
|
2021-02-25 16:53:22 +01:00
|
|
|
#include "bscript/compiler/ast/DictionaryEntry.h"
|
|
|
|
|
#include "bscript/compiler/ast/DictionaryInitializer.h"
|
|
|
|
|
#include "bscript/compiler/ast/ElementAccess.h"
|
|
|
|
|
#include "bscript/compiler/ast/ElementAssignment.h"
|
|
|
|
|
#include "bscript/compiler/ast/ElementIndexes.h"
|
|
|
|
|
#include "bscript/compiler/ast/ElvisOperator.h"
|
|
|
|
|
#include "bscript/compiler/ast/ErrorInitializer.h"
|
2021-03-11 22:48:16 +01:00
|
|
|
#include "bscript/compiler/ast/FormatExpression.h"
|
2021-02-25 16:53:22 +01:00
|
|
|
#include "bscript/compiler/ast/FunctionCall.h"
|
|
|
|
|
#include "bscript/compiler/ast/FunctionParameterDeclaration.h"
|
|
|
|
|
#include "bscript/compiler/ast/FunctionParameterList.h"
|
|
|
|
|
#include "bscript/compiler/ast/FunctionReference.h"
|
|
|
|
|
#include "bscript/compiler/ast/Identifier.h"
|
2021-03-11 22:48:16 +01:00
|
|
|
#include "bscript/compiler/ast/InterpolateString.h"
|
2021-02-25 16:53:22 +01:00
|
|
|
#include "bscript/compiler/ast/MemberAccess.h"
|
|
|
|
|
#include "bscript/compiler/ast/MemberAssignment.h"
|
|
|
|
|
#include "bscript/compiler/ast/MethodCall.h"
|
|
|
|
|
#include "bscript/compiler/ast/MethodCallArgumentList.h"
|
|
|
|
|
#include "bscript/compiler/ast/ModuleFunctionDeclaration.h"
|
|
|
|
|
#include "bscript/compiler/ast/StringValue.h"
|
|
|
|
|
#include "bscript/compiler/ast/StructInitializer.h"
|
|
|
|
|
#include "bscript/compiler/ast/StructMemberInitializer.h"
|
|
|
|
|
#include "bscript/compiler/ast/UnaryOperator.h"
|
|
|
|
|
#include "bscript/compiler/ast/UninitializedValue.h"
|
|
|
|
|
#include "bscript/compiler/astbuilder/BuilderWorkspace.h"
|
2020-08-19 10:43:08 -07:00
|
|
|
|
|
|
|
|
using EscriptGrammar::EscriptParser;
|
2020-08-18 03:07:51 -07:00
|
|
|
|
|
|
|
|
namespace Pol::Bscript::Compiler
|
|
|
|
|
{
|
|
|
|
|
ExpressionBuilder::ExpressionBuilder( const SourceFileIdentifier& source_file_identifier,
|
|
|
|
|
BuilderWorkspace& workspace )
|
2021-03-11 22:48:16 +01:00
|
|
|
: ValueBuilder( source_file_identifier, workspace )
|
2020-08-18 03:07:51 -07:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-01 02:23:03 -08:00
|
|
|
void ExpressionBuilder::unhandled_operator( const SourceLocation& source_location )
|
2020-08-26 19:24:47 -07:00
|
|
|
{
|
|
|
|
|
// This indicates a log error in the compiler: likely a disconnect between the grammar
|
|
|
|
|
// and the code building the AST from the parsed file.
|
|
|
|
|
source_location.internal_error( "unhandled operator.\n" );
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-06 00:13:49 -07:00
|
|
|
std::unique_ptr<ArrayInitializer> ExpressionBuilder::array_initializer(
|
|
|
|
|
EscriptParser::BareArrayInitializerContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
auto values = expressions( ctx->expressionList() );
|
|
|
|
|
return std::make_unique<ArrayInitializer>( location_for( *ctx ), std::move( values ) );
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-11 22:48:16 +01:00
|
|
|
std::unique_ptr<InterpolateString> ExpressionBuilder::interpolate_string(
|
|
|
|
|
EscriptParser::InterpolatedStringContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
auto values = expressions( ctx->interpolatedStringPart() );
|
|
|
|
|
return std::make_unique<InterpolateString>( location_for( *ctx ), std::move( values ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<Expression> ExpressionBuilder::format_expression(
|
|
|
|
|
std::unique_ptr<Expression> expr, antlr4::tree::TerminalNode* format )
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<FormatExpression>( location_for( *format ), std::move( expr ),
|
|
|
|
|
string_value( format, false ) );
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-06 00:13:49 -07:00
|
|
|
std::unique_ptr<ArrayInitializer> ExpressionBuilder::array_initializer(
|
|
|
|
|
EscriptParser::ExplicitArrayInitializerContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
auto values = expressions( ctx->arrayInitializer() );
|
|
|
|
|
return std::make_unique<ArrayInitializer>( location_for( *ctx ), std::move( values ) );
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-28 06:21:42 -07:00
|
|
|
std::unique_ptr<Expression> ExpressionBuilder::binary_operator(
|
2020-09-30 08:19:05 -07:00
|
|
|
EscriptParser::ExpressionContext* ctx, bool consume )
|
2020-09-01 22:49:48 -07:00
|
|
|
{
|
|
|
|
|
auto lhs = expression( ctx->expression( 0 ) );
|
|
|
|
|
auto rhs = expression( ctx->expression( 1 ) );
|
|
|
|
|
|
2020-09-27 11:43:00 -07:00
|
|
|
BTokenId token_id = binary_operator_token( ctx );
|
|
|
|
|
|
2021-03-11 22:48:16 +01:00
|
|
|
if ( token_id == TOK_ASSIGN )
|
2020-09-28 06:21:42 -07:00
|
|
|
{
|
|
|
|
|
if ( auto element_access = dynamic_cast<ElementAccess*>( lhs.get() ) )
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<ElementAssignment>(
|
2020-09-30 08:19:05 -07:00
|
|
|
location_for( *ctx ), consume, element_access->take_entity(),
|
2020-09-28 06:21:42 -07:00
|
|
|
element_access->take_indexes(), std::move( rhs ) );
|
|
|
|
|
}
|
2020-09-28 08:11:10 -07:00
|
|
|
else if ( auto get_member = dynamic_cast<MemberAccess*>( lhs.get() ) )
|
2020-09-28 06:21:42 -07:00
|
|
|
{
|
2020-09-30 08:19:05 -07:00
|
|
|
return std::make_unique<MemberAssignment>( location_for( *ctx ), consume,
|
2020-09-28 08:11:10 -07:00
|
|
|
get_member->take_entity(), get_member->name,
|
|
|
|
|
std::move( rhs ), get_member->known_member );
|
2020-09-28 06:21:42 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-27 12:08:52 -07:00
|
|
|
if ( token_id == TOK_ADDMEMBER || token_id == TOK_CHKMEMBER || token_id == TOK_DELMEMBER )
|
|
|
|
|
{
|
|
|
|
|
// On the right-hand side, any of the following are valid:
|
|
|
|
|
// - an identifier: treat as the field name
|
|
|
|
|
// - an expression: evaluate and use as the field name
|
|
|
|
|
if ( auto identifier = dynamic_cast<Identifier*>( rhs.get() ) )
|
|
|
|
|
{
|
|
|
|
|
rhs = std::make_unique<StringValue>( rhs->source_location, identifier->name );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-30 08:19:05 -07:00
|
|
|
auto op = std::make_unique<BinaryOperator>( location_for( *ctx ), std::move( lhs ),
|
|
|
|
|
ctx->bop->getText(), token_id, std::move( rhs ) );
|
|
|
|
|
if ( consume )
|
|
|
|
|
return consume_expression_result( std::move( op ) );
|
|
|
|
|
else
|
|
|
|
|
return op;
|
2020-09-27 11:43:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BTokenId ExpressionBuilder::binary_operator_token(
|
|
|
|
|
EscriptGrammar::EscriptParser::ExpressionContext* ctx )
|
|
|
|
|
{
|
2020-09-01 22:49:48 -07:00
|
|
|
if ( ctx->ADD() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_ADD;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->SUB() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_SUBTRACT;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->MUL() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_MULT;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->DIV() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_DIV;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->ASSIGN() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_ASSIGN;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->EQUAL() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_EQUAL;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->NOTEQUAL_A() || ctx->NOTEQUAL_B() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_NEQ;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->LT() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_LESSTHAN;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->LE() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_LESSEQ;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->GT() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_GRTHAN;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->GE() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_GREQ;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->AND_A() || ctx->AND_B() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_AND;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->OR_A() || ctx->OR_B() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_OR;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->ADD_ASSIGN() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_PLUSEQUAL;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->SUB_ASSIGN() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_MINUSEQUAL;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->MUL_ASSIGN() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_TIMESEQUAL;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->DIV_ASSIGN() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_DIVIDEEQUAL;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->MOD() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_MODULUS;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->MOD_ASSIGN() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_MODULUSEQUAL;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->ADDMEMBER() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_ADDMEMBER;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->DELMEMBER() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_DELMEMBER;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->CHKMEMBER() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_CHKMEMBER;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->BITAND() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_BITAND;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->BITOR() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_BITOR;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->CARET() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_BITXOR;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->TOK_IN() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_IN;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->LSHIFT() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_BSLEFT;
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->RSHIFT() )
|
2020-09-27 11:43:00 -07:00
|
|
|
return TOK_BSRIGHT;
|
2020-09-27 12:08:52 -07:00
|
|
|
else if ( ctx->ADDMEMBER() )
|
|
|
|
|
return TOK_ADDMEMBER;
|
|
|
|
|
else if ( ctx->CHKMEMBER() )
|
|
|
|
|
return TOK_CHKMEMBER;
|
|
|
|
|
else if ( ctx->DELMEMBER() )
|
|
|
|
|
return TOK_DELMEMBER;
|
2020-09-01 22:49:48 -07:00
|
|
|
else
|
|
|
|
|
location_for( *ctx ).internal_error( "unrecognized binary operator" );
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-06 04:02:37 -07:00
|
|
|
std::unique_ptr<DictionaryInitializer> ExpressionBuilder::dictionary_initializer(
|
|
|
|
|
EscriptParser::ExplicitDictInitializerContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::unique_ptr<DictionaryEntry>> entries;
|
|
|
|
|
if ( auto initializer_ctx = ctx->dictInitializer() )
|
|
|
|
|
{
|
|
|
|
|
if ( auto list_ctx = initializer_ctx->dictInitializerExpressionList() )
|
|
|
|
|
{
|
|
|
|
|
for ( auto entry_ctx : list_ctx->dictInitializerExpression() )
|
|
|
|
|
{
|
|
|
|
|
auto loc = location_for( *entry_ctx );
|
|
|
|
|
auto expressions = entry_ctx->expression();
|
|
|
|
|
|
|
|
|
|
auto key = expression( expressions.at( 0 ) );
|
|
|
|
|
auto value = ( expressions.size() >= 2 ) ? expression( expressions.at( 1 ) )
|
|
|
|
|
: std::make_unique<UninitializedValue>( loc );
|
|
|
|
|
auto entry = std::make_unique<DictionaryEntry>( loc, std::move( key ), std::move( value ) );
|
|
|
|
|
entries.push_back( std::move( entry ) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
auto loc = location_for( *ctx );
|
|
|
|
|
|
|
|
|
|
return std::make_unique<DictionaryInitializer>( loc, std::move( entries ) );
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-06 14:03:02 -07:00
|
|
|
std::unique_ptr<ElementAccess> ExpressionBuilder::element_access(
|
|
|
|
|
std::unique_ptr<Expression> lhs, EscriptParser::ExpressionListContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
auto source_location = location_for( *ctx );
|
|
|
|
|
|
|
|
|
|
std::vector<std::unique_ptr<Expression>> indexes;
|
|
|
|
|
for ( auto expression_ctx : ctx->expression() )
|
|
|
|
|
{
|
|
|
|
|
indexes.push_back( expression( expression_ctx ) );
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-07 00:58:31 -07:00
|
|
|
auto xx = std::make_unique<ElementIndexes>( location_for( *ctx ), std::move( indexes ) );
|
2020-09-06 14:03:02 -07:00
|
|
|
|
|
|
|
|
return std::make_unique<ElementAccess>( source_location, std::move( lhs ), std::move( xx ) );
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-09 23:11:51 -07:00
|
|
|
std::unique_ptr<ElvisOperator> ExpressionBuilder::elvis_operator(
|
|
|
|
|
EscriptParser::ExpressionContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
auto source_location = location_for( *ctx );
|
|
|
|
|
auto expressions = ctx->expression();
|
|
|
|
|
auto lhs = expression( expressions[0] );
|
|
|
|
|
auto rhs = expression( expressions[1] );
|
|
|
|
|
return std::make_unique<ElvisOperator>( source_location, std::move( lhs ), std::move( rhs ) );
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-14 23:20:20 +01:00
|
|
|
std::unique_ptr<ConditionalOperator> ExpressionBuilder::conditional_operator(
|
|
|
|
|
EscriptParser::ExpressionContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
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] );
|
|
|
|
|
|
|
|
|
|
return std::make_unique<ConditionalOperator>( source_location, std::move( conditional ),
|
|
|
|
|
std::move( consequent ), std::move( alternate ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-09-07 00:58:31 -07:00
|
|
|
std::unique_ptr<ErrorInitializer> ExpressionBuilder::error(
|
|
|
|
|
EscriptParser::ExplicitErrorInitializerContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
auto source_location = location_for( *ctx );
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> identifiers;
|
|
|
|
|
std::vector<std::unique_ptr<Expression>> expressions;
|
|
|
|
|
|
|
|
|
|
if ( auto struct_initializer = ctx->structInitializer() )
|
|
|
|
|
{
|
|
|
|
|
if ( auto expression_list_ctx = struct_initializer->structInitializerExpressionList() )
|
|
|
|
|
{
|
|
|
|
|
for ( auto expression_ctx : expression_list_ctx->structInitializerExpression() )
|
|
|
|
|
{
|
|
|
|
|
auto expression_source_ctx = location_for( *expression_ctx );
|
|
|
|
|
std::string identifier;
|
|
|
|
|
if ( auto x = expression_ctx->IDENTIFIER() )
|
|
|
|
|
identifier = text( x );
|
|
|
|
|
else if ( auto string_literal = expression_ctx->STRING_LITERAL() )
|
|
|
|
|
identifier = unquote( string_literal );
|
|
|
|
|
else
|
|
|
|
|
expression_source_ctx.internal_error(
|
|
|
|
|
"Unable to determine identifier for struct initializer" );
|
|
|
|
|
|
2024-02-04 21:38:37 +07:00
|
|
|
auto value = expression_ctx->expression()
|
|
|
|
|
? expression( expression_ctx->expression() )
|
|
|
|
|
: std::make_unique<UninitializedValue>( expression_source_ctx );
|
2020-09-07 00:58:31 -07:00
|
|
|
|
|
|
|
|
identifiers.push_back( std::move( identifier ) );
|
|
|
|
|
expressions.push_back( std::move( value ) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return std::make_unique<ErrorInitializer>( source_location, std::move( identifiers ),
|
|
|
|
|
std::move( expressions ) );
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-06 00:13:49 -07:00
|
|
|
std::vector<std::unique_ptr<Expression>> ExpressionBuilder::expressions(
|
|
|
|
|
EscriptParser::ExpressionListContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::unique_ptr<Expression>> expressions;
|
|
|
|
|
if ( ctx )
|
|
|
|
|
{
|
|
|
|
|
for ( auto expression_ctx : ctx->expression() )
|
|
|
|
|
{
|
|
|
|
|
expressions.push_back( expression( expression_ctx ) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return expressions;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-11 22:48:16 +01:00
|
|
|
std::vector<std::unique_ptr<Expression>> ExpressionBuilder::expressions(
|
|
|
|
|
std::vector<EscriptGrammar::EscriptParser::InterpolatedStringPartContext*> ctx )
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::unique_ptr<Expression>> expressions;
|
|
|
|
|
|
|
|
|
|
for ( auto interstringPart_ctx : ctx )
|
|
|
|
|
{
|
|
|
|
|
if ( auto expression_ctx = interstringPart_ctx->expression() )
|
|
|
|
|
{
|
|
|
|
|
std::unique_ptr<Expression> expr = expression( expression_ctx );
|
|
|
|
|
if ( auto format = interstringPart_ctx->FORMAT_STRING() )
|
|
|
|
|
{
|
|
|
|
|
expr = format_expression( std::move( expr ), format );
|
|
|
|
|
}
|
|
|
|
|
expressions.push_back( std::move(expr) );
|
|
|
|
|
}
|
|
|
|
|
else if ( auto string_literal = interstringPart_ctx->STRING_LITERAL_INSIDE() )
|
|
|
|
|
{
|
|
|
|
|
expressions.push_back( string_value( string_literal, false ) );
|
|
|
|
|
}
|
|
|
|
|
else if ( auto lbrace = interstringPart_ctx->DOUBLE_LBRACE_INSIDE() )
|
|
|
|
|
{
|
|
|
|
|
auto loc = location_for( *lbrace );
|
|
|
|
|
expressions.push_back( std::make_unique<StringValue>( loc, "{" ) );
|
|
|
|
|
}
|
|
|
|
|
else if ( auto rbrace = interstringPart_ctx->DOUBLE_RBRACE() )
|
|
|
|
|
{
|
|
|
|
|
auto loc = location_for( *rbrace );
|
|
|
|
|
expressions.push_back( std::make_unique<StringValue>( loc, "}" ) );
|
|
|
|
|
}
|
|
|
|
|
else if ( auto escaped = interstringPart_ctx->REGULAR_CHAR_INSIDE() )
|
|
|
|
|
{
|
|
|
|
|
expressions.push_back( string_value( escaped, false ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
location_for( *interstringPart_ctx )
|
|
|
|
|
.internal_error( "unhandled context in interpolated string part" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return expressions;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-06 00:13:49 -07:00
|
|
|
std::vector<std::unique_ptr<Expression>> ExpressionBuilder::expressions(
|
|
|
|
|
EscriptParser::ArrayInitializerContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
if ( ctx )
|
|
|
|
|
{
|
|
|
|
|
if ( auto expression_list = ctx->expressionList() )
|
|
|
|
|
{
|
|
|
|
|
return expressions( expression_list );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-30 08:19:05 -07:00
|
|
|
std::unique_ptr<Expression> ExpressionBuilder::expression( EscriptParser::ExpressionContext* ctx,
|
|
|
|
|
bool consume )
|
2020-08-19 10:43:08 -07:00
|
|
|
{
|
2020-09-30 08:19:05 -07:00
|
|
|
std::unique_ptr<Expression> result;
|
2020-08-19 10:43:08 -07:00
|
|
|
if ( auto prim = ctx->primary() )
|
2020-09-30 08:19:05 -07:00
|
|
|
result = primary( prim );
|
2020-08-26 19:24:47 -07:00
|
|
|
else if ( ctx->prefix )
|
2020-09-30 08:19:05 -07:00
|
|
|
result = prefix_unary_operator( ctx );
|
2020-08-26 19:24:47 -07:00
|
|
|
else if ( ctx->postfix )
|
2020-09-30 08:19:05 -07:00
|
|
|
result = postfix_unary_operator( ctx );
|
2020-09-01 22:49:48 -07:00
|
|
|
else if ( ctx->bop && ctx->expression().size() == 2 )
|
|
|
|
|
{
|
2020-09-09 23:11:51 -07:00
|
|
|
if ( ctx->ELVIS() )
|
2020-09-30 08:19:05 -07:00
|
|
|
result = elvis_operator( ctx );
|
2020-09-08 00:48:17 -07:00
|
|
|
else
|
2020-09-30 08:19:05 -07:00
|
|
|
return binary_operator( ctx, consume );
|
2020-09-01 22:49:48 -07:00
|
|
|
}
|
2020-09-06 14:03:02 -07:00
|
|
|
else if ( auto suffix = ctx->expressionSuffix() )
|
|
|
|
|
{
|
2020-09-30 08:19:05 -07:00
|
|
|
result = expression_suffix( expression( ctx->expression()[0] ), suffix );
|
|
|
|
|
}
|
2021-08-28 22:26:15 +02:00
|
|
|
else if ( ctx->QUESTION() )
|
2021-03-14 23:20:20 +01:00
|
|
|
{
|
|
|
|
|
result = conditional_operator( ctx );
|
|
|
|
|
}
|
2020-09-30 08:19:05 -07:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
location_for( *ctx ).internal_error( "unhandled expression" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (consume)
|
|
|
|
|
{
|
|
|
|
|
result = consume_expression_result( std::move( result ) );
|
2020-09-06 14:03:02 -07:00
|
|
|
}
|
2020-08-19 10:43:08 -07:00
|
|
|
|
2020-09-30 08:19:05 -07:00
|
|
|
return result;
|
2020-08-19 10:43:08 -07:00
|
|
|
}
|
|
|
|
|
|
2020-08-24 01:47:38 -07:00
|
|
|
std::unique_ptr<FunctionCall> ExpressionBuilder::function_call(
|
|
|
|
|
EscriptParser::FunctionCallContext* ctx, const std::string& scope )
|
|
|
|
|
{
|
|
|
|
|
auto method_name = text( ctx->IDENTIFIER() );
|
|
|
|
|
|
|
|
|
|
auto arguments = value_arguments( ctx->expressionList() );
|
|
|
|
|
|
|
|
|
|
auto function_call = std::make_unique<FunctionCall>( location_for( *ctx ), scope, method_name,
|
|
|
|
|
std::move( arguments ) );
|
|
|
|
|
|
|
|
|
|
std::string key = scope.empty() ? method_name : ( scope + "::" + method_name );
|
|
|
|
|
workspace.function_resolver.register_function_link( key, function_call->function_link );
|
|
|
|
|
|
|
|
|
|
return function_call;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-08 01:24:57 -07:00
|
|
|
std::unique_ptr<MethodCall> ExpressionBuilder::method_call(
|
|
|
|
|
std::unique_ptr<Expression> lhs, EscriptParser::MethodCallSuffixContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
auto loc = location_for( *ctx );
|
|
|
|
|
auto methodname = text( ctx->IDENTIFIER() );
|
2020-09-27 13:08:09 -07:00
|
|
|
auto arguments = expressions( ctx->expressionList() );
|
2020-09-08 01:24:57 -07:00
|
|
|
|
|
|
|
|
auto argument_list = std::make_unique<MethodCallArgumentList>( loc, std::move( arguments ) );
|
|
|
|
|
return std::make_unique<MethodCall>( loc, std::move( lhs ), std::move( methodname ),
|
|
|
|
|
std::move( argument_list ) );
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-28 08:11:10 -07:00
|
|
|
std::unique_ptr<MemberAccess> ExpressionBuilder::navigation(
|
2020-09-07 00:00:26 -07:00
|
|
|
std::unique_ptr<Expression> lhs, EscriptGrammar::EscriptParser::NavigationSuffixContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
auto loc = location_for( *ctx );
|
|
|
|
|
|
|
|
|
|
std::string name;
|
|
|
|
|
if ( auto identifier = ctx->IDENTIFIER() )
|
|
|
|
|
name = text( identifier );
|
|
|
|
|
else if ( auto string_literal = ctx->STRING_LITERAL() )
|
|
|
|
|
name = unquote( string_literal );
|
|
|
|
|
else
|
|
|
|
|
loc.internal_error( "member_access: need string literal or identifier" );
|
2020-09-28 08:11:10 -07:00
|
|
|
return std::make_unique<MemberAccess>( loc, std::move( lhs ), std::move( name ) );
|
2020-09-07 00:00:26 -07:00
|
|
|
}
|
|
|
|
|
|
2020-09-06 14:03:02 -07:00
|
|
|
std::unique_ptr<Expression> ExpressionBuilder::expression_suffix(
|
|
|
|
|
std::unique_ptr<Expression> lhs, EscriptParser::ExpressionSuffixContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
if ( auto indexing = ctx->indexingSuffix() )
|
|
|
|
|
{
|
|
|
|
|
return element_access( std::move( lhs ), indexing->expressionList() );
|
|
|
|
|
}
|
2020-09-07 00:00:26 -07:00
|
|
|
else if ( auto member = ctx->navigationSuffix() )
|
|
|
|
|
{
|
|
|
|
|
return navigation( std::move( lhs ), member );
|
|
|
|
|
}
|
2020-09-08 01:24:57 -07:00
|
|
|
else if ( auto method = ctx->methodCallSuffix() )
|
|
|
|
|
{
|
|
|
|
|
return method_call( std::move( lhs ), method );
|
|
|
|
|
}
|
2020-09-06 14:03:02 -07:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
location_for( *ctx ).internal_error( "unhandled navigation suffix" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-26 19:24:47 -07:00
|
|
|
std::unique_ptr<Expression> ExpressionBuilder::prefix_unary_operator(
|
|
|
|
|
EscriptParser::ExpressionContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
auto expression_ctx = ctx->expression( 0 );
|
|
|
|
|
auto source_location = location_for( *expression_ctx );
|
|
|
|
|
auto expression_ast = expression( expression_ctx );
|
|
|
|
|
|
2020-12-01 02:23:03 -08:00
|
|
|
BTokenId token_id;
|
|
|
|
|
if ( ctx->ADD() )
|
|
|
|
|
token_id = TOK_UNPLUS;
|
|
|
|
|
else if ( ctx->SUB() )
|
|
|
|
|
token_id = TOK_UNMINUS;
|
|
|
|
|
else if ( ctx->INC() )
|
|
|
|
|
token_id = TOK_UNPLUSPLUS;
|
|
|
|
|
else if ( ctx->DEC() )
|
|
|
|
|
token_id = TOK_UNMINUSMINUS;
|
|
|
|
|
else if ( ctx->TILDE() )
|
|
|
|
|
token_id = TOK_BITWISE_NOT;
|
|
|
|
|
else if ( ctx->BANG_A() || ctx->BANG_B() )
|
|
|
|
|
token_id = TOK_LOG_NOT;
|
|
|
|
|
else
|
|
|
|
|
unhandled_operator( source_location );
|
2020-08-26 19:24:47 -07:00
|
|
|
|
|
|
|
|
if ( token_id == TOK_UNPLUS )
|
|
|
|
|
return expression_ast;
|
|
|
|
|
|
|
|
|
|
return std::make_unique<UnaryOperator>( source_location, ctx->prefix->getText(), token_id,
|
|
|
|
|
std::move( expression_ast ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<Expression> ExpressionBuilder::postfix_unary_operator(
|
|
|
|
|
EscriptParser::ExpressionContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
auto loc = location_for( *ctx );
|
|
|
|
|
auto expression_ctx = ctx->expression( 0 );
|
|
|
|
|
auto expression_ast = expression( expression_ctx );
|
|
|
|
|
|
2020-12-01 02:23:03 -08:00
|
|
|
BTokenId token_id;
|
|
|
|
|
if ( ctx->INC() )
|
|
|
|
|
token_id = TOK_UNPLUSPLUS_POST;
|
|
|
|
|
else if ( ctx->DEC() )
|
|
|
|
|
token_id = TOK_UNMINUSMINUS_POST;
|
|
|
|
|
else
|
|
|
|
|
unhandled_operator( loc );
|
2020-08-26 19:24:47 -07:00
|
|
|
|
|
|
|
|
return std::make_unique<UnaryOperator>( loc, ctx->postfix->getText(), token_id,
|
|
|
|
|
std::move( expression_ast ) );
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-19 10:43:08 -07:00
|
|
|
std::unique_ptr<Expression> ExpressionBuilder::primary( EscriptParser::PrimaryContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
if ( auto literal = ctx->literal() )
|
2020-08-24 01:47:38 -07:00
|
|
|
{
|
2020-08-19 10:43:08 -07:00
|
|
|
return value( literal );
|
2020-08-24 01:47:38 -07:00
|
|
|
}
|
|
|
|
|
else if ( auto par_expression = ctx->parExpression() )
|
|
|
|
|
{
|
|
|
|
|
return expression( par_expression->expression() );
|
|
|
|
|
}
|
2020-08-25 00:57:03 -07:00
|
|
|
else if ( auto identifier = ctx->IDENTIFIER() )
|
|
|
|
|
{
|
|
|
|
|
return std::make_unique<Identifier>( location_for( *ctx ), text( identifier ) );
|
|
|
|
|
}
|
2020-08-24 01:47:38 -07:00
|
|
|
else if ( auto f_call = ctx->functionCall() )
|
|
|
|
|
{
|
|
|
|
|
return function_call( f_call, "" );
|
|
|
|
|
}
|
|
|
|
|
else if ( auto scoped_f_call = ctx->scopedFunctionCall() )
|
|
|
|
|
{
|
|
|
|
|
return scoped_function_call( scoped_f_call );
|
|
|
|
|
}
|
2020-09-06 04:02:37 -07:00
|
|
|
else if ( auto dict_init = ctx->explicitDictInitializer() )
|
|
|
|
|
{
|
|
|
|
|
return dictionary_initializer( dict_init );
|
|
|
|
|
}
|
2020-09-06 23:24:53 -07:00
|
|
|
else if ( auto struct_init = ctx->explicitStructInitializer() )
|
|
|
|
|
{
|
|
|
|
|
return struct_initializer( struct_init );
|
|
|
|
|
}
|
2020-09-08 23:20:32 -07:00
|
|
|
else if ( auto fr = ctx->functionReference() )
|
|
|
|
|
{
|
|
|
|
|
return function_reference( fr );
|
|
|
|
|
}
|
2020-09-07 00:58:31 -07:00
|
|
|
else if ( auto error_init = ctx->explicitErrorInitializer() )
|
|
|
|
|
{
|
|
|
|
|
return error( error_init );
|
|
|
|
|
}
|
2020-09-06 00:13:49 -07:00
|
|
|
else if ( auto array_init = ctx->explicitArrayInitializer() )
|
|
|
|
|
{
|
|
|
|
|
return array_initializer( array_init );
|
|
|
|
|
}
|
|
|
|
|
else if ( auto bare_array = ctx->bareArrayInitializer() )
|
|
|
|
|
{
|
|
|
|
|
return array_initializer( bare_array );
|
|
|
|
|
}
|
2021-03-11 22:48:16 +01:00
|
|
|
else if ( auto inter_string = ctx->interpolatedString() )
|
|
|
|
|
{
|
|
|
|
|
return interpolate_string( inter_string );
|
|
|
|
|
}
|
2020-08-19 10:43:08 -07:00
|
|
|
|
|
|
|
|
location_for( *ctx ).internal_error( "unhandled primary expression" );
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-24 01:47:38 -07:00
|
|
|
std::unique_ptr<FunctionCall> ExpressionBuilder::scoped_function_call(
|
|
|
|
|
EscriptParser::ScopedFunctionCallContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
return function_call( ctx->functionCall(), text( ctx->IDENTIFIER() ) );
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-06 23:24:53 -07:00
|
|
|
std::unique_ptr<Expression> ExpressionBuilder::struct_initializer(
|
|
|
|
|
EscriptParser::ExplicitStructInitializerContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::unique_ptr<StructMemberInitializer>> initializers;
|
|
|
|
|
|
|
|
|
|
if ( auto struct_init = ctx->structInitializer() )
|
|
|
|
|
{
|
|
|
|
|
if ( auto expression_list_ctx = struct_init->structInitializerExpressionList() )
|
|
|
|
|
{
|
|
|
|
|
for ( auto initializer_expression_ctx : expression_list_ctx->structInitializerExpression() )
|
|
|
|
|
{
|
|
|
|
|
auto loc = location_for( *initializer_expression_ctx );
|
|
|
|
|
std::string identifier;
|
|
|
|
|
if ( auto x = initializer_expression_ctx->IDENTIFIER() )
|
|
|
|
|
identifier = text( x );
|
|
|
|
|
else if ( auto string_literal = initializer_expression_ctx->STRING_LITERAL() )
|
|
|
|
|
identifier = unquote( string_literal );
|
|
|
|
|
else
|
|
|
|
|
loc.internal_error( "Unable to determine identifier for struct initializer" );
|
|
|
|
|
|
|
|
|
|
if ( auto expression_ctx = initializer_expression_ctx->expression() )
|
|
|
|
|
{
|
|
|
|
|
auto initializer = expression( expression_ctx );
|
|
|
|
|
initializers.push_back( std::make_unique<StructMemberInitializer>(
|
|
|
|
|
loc, std::move( identifier ), std::move( initializer ) ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
initializers.push_back(
|
|
|
|
|
std::make_unique<StructMemberInitializer>( loc, std::move( identifier ) ) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return std::make_unique<StructInitializer>( location_for( *ctx ), std::move( initializers ) );
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-24 01:47:38 -07:00
|
|
|
std::vector<std::unique_ptr<Argument>> ExpressionBuilder::value_arguments(
|
|
|
|
|
EscriptGrammar::EscriptParser::ExpressionListContext* ctx )
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::unique_ptr<Argument>> arguments;
|
|
|
|
|
|
|
|
|
|
if ( ctx )
|
|
|
|
|
{
|
|
|
|
|
for ( auto argument_context : ctx->expression() )
|
|
|
|
|
{
|
|
|
|
|
auto loc = location_for( *argument_context );
|
|
|
|
|
|
|
|
|
|
std::string name;
|
|
|
|
|
auto value = expression( argument_context );
|
|
|
|
|
|
2020-09-01 22:49:48 -07:00
|
|
|
if ( auto binary_operator = dynamic_cast<BinaryOperator*>( value.get() ) )
|
|
|
|
|
{
|
|
|
|
|
if ( binary_operator->token_id == TOK_ASSIGN )
|
|
|
|
|
{
|
|
|
|
|
if ( auto identifier = dynamic_cast<Identifier*>( &binary_operator->lhs() ) )
|
|
|
|
|
{
|
|
|
|
|
name = identifier->name;
|
|
|
|
|
value = binary_operator->take_rhs();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-08-24 01:47:38 -07:00
|
|
|
auto argument = std::make_unique<Argument>( loc, std::move( name ), std::move( value ) );
|
|
|
|
|
arguments.push_back( std::move( argument ) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return arguments;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-18 03:07:51 -07:00
|
|
|
} // namespace Pol::Bscript::Compiler
|