#include "parse.h"
#include "builtins/builtins.h"
using namespace empathy;
using namespace empathy::parse;
using namespace empathy::builtins;
Parser* Parser::ms_pCurrentParser = nullptr;
Parser Parser::makeNestedParser()
{
Parser p( m_resolver );
p.m_introDelimiter = m_introDelimiter;
p.setCFG( cfg() );
p.setCurrentBB( currentBB() );
return p;
}
void Parser::parseSequence()
{
while( parseExpression( 0 ) )
m_resolver->consumeNewLines();
flushValue();
}
bool Parser::parseExpression( uint32_t precedence )
{
auto next = m_resolver->lookAhead();
if( !next )
return false;
if( !parsePrefix( next->first, precedence ) )
return false;
parsePostfixExpression( precedence );
return true;
}
void Parser::parsePostfixExpression( uint32_t precedence )
{
while( auto next = m_resolver->lookAhead() )
{
auto prec = getPrecedence( next->first );
if( !prec || precedence > *prec )
break;
if( !parseInfix( next->first, *prec ) )
break;
}
}
void Parser::flushValue()
{
// Flush the pending value, by invoking the DropValue
// extension point, where an overload will decide
// of the value's fate (or possibly emit an error
// if that value wasn't allowed to be discarded).
if( !m_lastValue )
return;
if( m_lastValue->isPoison() )
return;
InvokeOverloadSet( resolver()->context(), resolver()->context().env()->extDropValue(),
MakeTuple( *m_lastValue ) );
m_lastValue = nullopt;
}
optional< uint32_t > Parser::getPrecedence( const Term& t )
{
return visit( [&]( auto&& content )
{
return getPrecedence( t, content );
}, t );
}
bool Parser::parsePrefix( const Term& t, uint32_t precedence )
{
return visit( [&]( auto&& content )
{
return parsePrefix( content, precedence );
}, t );
}
bool Parser::parseInfix( const Term& t, uint32_t precedence )
{
return visit( [&]( auto&& content )
{
return parseInfix( content, precedence );
}, t );
}
bool Parser::parsePrefix( const BigInt& intlit, uint32_t )
{
auto tok = m_resolver->consume();
pushValue( ToValue( intlit ).setLocationId( tok->second ) );
return true;
}
bool Parser::parsePrefix( const string& strlit, uint32_t )
{
auto tok = m_resolver->consume();
pushValue( ToValue( strlit ).setLocationId( tok->second ) );
return true;
}
// Standalone (ie not part of a grammar construct that expects them such as a decl), unresolved identifiers
// end up here.
bool Parser::parsePrefix( const StringId& strid, uint32_t )
{
auto tok = m_resolver->consume();
DiagnosticsManager::GetInstance().emitSyntaxErrorMessage( tok->second,
"undefined identifier.", 0 );
return false;
}
// Infix identifiers: if the left value is a type, then we have a decl.
optional< uint32_t > Parser::getPrecedence( const Term&, const StringId& strid )
{
const auto& leftVal = peekLastValue();
if( !leftVal )
return nullopt;
// If leftVal is a type, this is a decl, so set the precedence to Application.
if( leftVal->isType() || IsTExpr( *leftVal ) )
return precedence::Application;
return nullopt;
}
// An unbound infix identifier
bool Parser::parseInfix( const StringId& strid, uint32_t prec )
{
const auto& leftVal = peekLastValue();
if( !leftVal )
return parsePrefix( strid, prec );
auto nameTerm = m_resolver->consume();
const auto* name = get_if< StringId >( &nameTerm->first );
// If the identifier is preceded by a TExpr or a Type,
// then this becomes a TDecl or a Decl, respectively.
if( IsTExpr( *leftVal ) )
{
auto loc = Location::CreateSpanningLocation( leftVal->locationId(), nameTerm->second );
auto texpr = ValueToIRExpr( *popValue() );
pushValue( ToValue( TNamedDecl( move( texpr ), *name ) ).setLocationId( loc ) );
return true;
}
else if( leftVal->isType() )
{
auto loc = Location::CreateSpanningLocation( leftVal->locationId(), nameTerm->second );
auto type = ValueToIRExpr( *popValue() );
pushValue( ToValue( Decl( move( type ), *name ) ).setLocationId( loc ) );
return true;
}
return parsePrefix( strid, prec );
}
bool Parser::parsePrefix( const pvec& vec, uint32_t prec )
{
auto t = *m_resolver->lookAhead();
auto val = ValueFromIRExpr( t.first );
if( !val )
return false;
if( val->isPoison() )
DiagnosticsManager::GetInstance().setCurrentVerbosityLevel( Verbosity::SilentLocally );
// If the term is a prefix rule value, invoke its parsePrefix() function.
auto rule = FromValue< Rule >( *val );
if( !rule )
{
m_resolver->consume();
pushValue( Value( move( *val ) ).setLocationId( t.second ) );
return true;
}
if( !( *rule )->isPrefix() )
return false;
m_resolver->consume();
return ( *rule )->parsePrefix( *this, t.second, prec );
}
optional< uint32_t > Parser::getPrecedence( const Term& t, const pvec& vec )
{
auto val = ValueFromIRExpr( t );
if( !val )
return nullopt;
if( val->type() == GetValueType< ptr< OverloadSet > >() )
{
if( !peekLastValue() )
return nullopt;
if( !peekLastValue()->isType() && !IsTExpr( *peekLastValue() ) )
return nullopt;
return getInfixOverloadSetPrecedence();
}
// If the term is an infix rule value, invoke its getPrecedence() function.
auto rule = FromValue< Rule >( *val );
if( !rule )
return nullopt;
if( !( *rule )->isInfix() )
return nullopt;
return ( *rule )->getPrecedence( *this );
}
bool Parser::parseInfix( const pvec& vec, uint32_t prec )
{
auto t = *m_resolver->lookAhead();
auto val = ValueFromIRExpr( t.first );
if( !val )
return false;
if( val->isPoison() )
DiagnosticsManager::GetInstance().setCurrentVerbosityLevel( Verbosity::SilentLocally );
if( val->type() == GetValueType< ptr< OverloadSet > >() )
return parseInfixOverloadSet( *FromValue< ptr< OverloadSet > >( *val ), prec );
// If the term is an infix rule value, invoke its parseInfix() function.
auto rule = FromValue< Rule >( *val );
if( !rule )
return false;
m_resolver->consume();
if( !( *rule )->isInfix() )
return false;
return ( *rule )->parseInfix( *this, t.second, prec );
}