#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's llr as a standalone instruction,
// if any. If it is a constant, complain about discarding it.
if( !m_lastValue )
return;
if( m_lastValue->isConstant() )
return;
assert( m_currentBB );
auto llr = move( *m_lastValue->llr() );
m_lastValue = nullopt;
emitInstruction( move( llr ) );
}
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 )
{
m_resolver->consume();
pushValue( ToValue( intlit ) );
return true;
}
bool Parser::parsePrefix( const string& strlit, uint32_t )
{
m_resolver->consume();
pushValue( ToValue( strlit ) );
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 )
{
m_resolver->consume();
// TODO location, poisoning
cout << "undefined identifier '" << strid.c_str() << "'\n";
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;
}
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( IsTExpr( *leftVal ) )
{
auto texpr = ValueToIRExpr( *popValue() );
pushValue( ToValue( TNamedDecl( move( texpr ), *name ) ) );
return true;
}
else if( leftVal->isType() )
{
auto type = ValueToIRExpr( *popValue() );
pushValue( ToValue( Decl( move( type ), *name ) ) );
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 the term is a prefix rule value, invoke its parsePrefix() function.
auto rule = FromValue< Rule >( *val );
if( !rule )
{
m_resolver->consume();
pushValue( *val );
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->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 );
}