#include "builtins/builtins.h"
#include "parse/parse.h"
#include "precedence.h"
using namespace empathy;
using namespace empathy::ir;
using namespace empathy::parse;
using namespace empathy::builtins;
// Colon is a low level operator: it doesn't necessarily expect a value rhs operand,
// it can also accept an identifier.
// So we can't use the convenient operator wrapper rule.
namespace
{
optional< uint32_t > InfixColonPrecedence( const Parser& p, const Term& t )
{
return precedence::ColonOp;
}
bool ParseInfixColonOperator( Parser& p, const Term& t, uint32_t prec )
{
const auto& leftVal = p.lastValue();
if( !leftVal )
return false;
const auto& next = p.resolver()->lookAhead();
const auto* name = get_if< StringId >( &next->content() );
if( name )
{
// The rhs is an identifier: build either a Decl or a TNamedDecl.
if( leftVal->type() == TSID( type ) )
{
p.resolver()->consumeUnresolved();
auto type = ValueToIRExpr( *p.pop() );
p.push( ToValue( builtins::Decl( move( type ), *name ) ) );
return true;
}
else if( builtins::IsTExpr( *leftVal ) )
{
p.resolver()->consumeUnresolved();
auto texpr = ValueToIRExpr( *p.pop() );
p.push( ToValue( builtins::TNamedDecl( move( texpr ), *name ) ) );
return true;
}
return false;
}
// Parse the right hand side, if it's a TExpr build a TDecl.
// Otherwise, error out.
auto np = p.makeNestedParser();
if( !np.parseExpression( prec + 1 ) )
{
// TODO error mgmt
cout << "expected an identifier or a template expression as the right hand side of the ':' operator.";
return false;
}
auto rightVal = np.result();
if( !rightVal || !IsTExpr( *rightVal ) )
{
// TODO error mgmt
cout << "expected an identifier or a template expression as the right hand side of the ':' operator.";
return false;
}
p.push( ToValue( TDecl( ValueToIRExpr( *p.pop() ), ValueToIRExpr( *rightVal ) ) ) );
return true;
}
}
namespace empathy::builtins
{
void SetupColonOp( Env& e )
{
Rule r( InfixColonPrecedence, ParseInfixColonOperator );
RegisterRule( e, ":"_sid, move( r ) );
}
}