#include "parse.h"
#include "builtins/builtins.h"
#include "precedence.h"
using namespace empathy;
using namespace empathy::parse;
using namespace empathy::builtins;
optional< uint32_t > Parser::getPrecedence( const Term& t, const Delimiter& d )
{
if( d == Delimiter::OpenParen )
return getPostfixParenBlockPrecedence();
return nullopt;
}
bool Parser::parsePrefix( const Delimiter& d, uint32_t prec )
{
switch( d )
{
case Delimiter::OpenParen:
{
auto result = parseParenBlock( d );
if( result )
push( *result );
return !!result;
}
case Delimiter::OpenBrace:
return parseBraceBlock( d );
case Delimiter::OpenBracket:
// TODO
break;
case Delimiter::CloseParen:
// TODO ERROR MGMT
if( !m_introDelimiter || m_introDelimiter != Delimiter::OpenParen )
cout << "mismatched ')'.\n";
break;
case Delimiter::CloseBrace:
// TODO ERROR MGMT
if( !m_introDelimiter || m_introDelimiter != Delimiter::OpenBrace )
cout << "mismatched '}'.\n";
break;
case Delimiter::CloseBracket:
// TODO
break;
}
return false;
}
bool Parser::parseInfix( const Delimiter& d, uint32_t prec )
{
switch( d )
{
case Delimiter::OpenParen:
return parsePostfixParenBlock( d, prec );
case Delimiter::OpenBrace:
// TODO
break;
case Delimiter::OpenBracket:
// TODO
break;
case Delimiter::CloseParen:
// TODO ERROR MGMT
if( !m_introDelimiter || m_introDelimiter != Delimiter::OpenParen )
cout << "mismatched ')'.\n";
break;
case Delimiter::CloseBrace:
// TODO ERROR MGMT
if( !m_introDelimiter || m_introDelimiter != Delimiter::OpenBrace )
cout << "mismatched '}'.\n";
break;
case Delimiter::CloseBracket:
// TODO
break;
}
return false;
}
optional< Value > Parser::parseParenBlock( Delimiter delim )
{
m_resolver->consume();
Parser p( resolver(), delim );
p.parseExpression();
auto content = p.result();
auto next = m_resolver->consume();
if( !next )
{
// TODO ERROR MGMT
cout << "')' expected.\n";
return nullopt;
}
auto decomp = Decompose( *next, Val< Delimiter >() );
if( !decomp || *decomp != Delimiter::CloseParen )
{
// TODO ERROR MGMT
cout << "')' expected.\n";
return nullopt;
}
// If the paren block was empty, return an empty closed tuple.
if( !content )
return EmptyClosedTuple();
// If the content is an open tuple, turn it into a closed (parenthesized) tuple.
if( IsOpenTuple( *content ) )
return CloseTuple( *content );
// Otherwise wrap the content into a tuple: we prefer to treat single elements enclosed in parentheses
// as tuples for consistency. An unification rule takes care of peeling off single element tuples
// where applicable.
auto tup = EmptyClosedTuple();
return AppendToTuple( tup, *content );
}
// If the left value is invocable or is a type, the postfix paren block is a call or
// a function type expression and have application precedence.
// Otherwise, it is an implicit separator and have separator precedence.
optional< uint32_t > Parser::getPostfixParenBlockPrecedence()
{
const auto& leftVal = lastValue();
if( !leftVal )
return nullopt;
if( leftVal->type() == TSID( type ) || IsDecl( *leftVal )
|| IsTNamedDecl( *leftVal ) || IsTExpr( *leftVal ) )
return precedence::Application;
if( sema::CanBeInvoked( m_resolver->context(), *leftVal ) )
return precedence::Application;
return nullopt;
}
// Essentially the same thing as a prefix paren block, except that after parsing the block
// we check if this is actually an invocation or a function type expression, depending on
// whether the left value is invocable or if it is a type.
bool Parser::parsePostfixParenBlock( Delimiter delim, uint32_t prec )
{
auto val = parseParenBlock( delim );
if( !val )
{
push();
return false;
}
const auto& leftVal = lastValue();
if( !leftVal )
return false;
// If leftVal is a type, this is a func type or function expression (aka lambda).
if( leftVal->type() == TSID( type ) )
return parseFunctionExpression( *pop(), *val );
// If leftVal is a decl, this is a func declaration.
if( IsDecl( *leftVal ) )
return parseFunctionDeclaration( *pop(), *val );
// If leftVal is a TNamedDecl, this is a template func declaration.
if( IsTNamedDecl( *leftVal ) )
return parseTemplateFunctionTNamedDecl( *pop(), *val );
// If leftVal is a TExpr, this is a template type or a template function expression.
if( IsTExpr( *leftVal ) )
return parseTemplateFunctionExpression( *pop(), *val );
// If leftVal is something that can be invoked, resolve the invocation.
if( sema::CanBeInvoked( m_resolver->context(), *leftVal ) )
{
auto call = sema::ResolveInvocation( m_resolver->context(), *pop(), *val );
if( !call )
{
push();
return false;
}
push( *call );
return true;
}
push( *val );
return true;
}
bool Parser::parseBraceBlock( Delimiter delim )
{
m_resolver->consume();
Parser p( resolver(), delim );
p.parseSequence();
auto content = p.result();
auto next = m_resolver->consumeUnresolved();
if( !next )
{
// TODO ERROR MGMT
cout << "'}' expected.\n";
return false;
}
auto decomp = Decompose( *next, Val< Delimiter >() );
if( !decomp || *decomp != Delimiter::CloseBrace )
{
// TODO ERROR MGMT
cout << "'}' expected.\n";
return false;
}
if( content )
push( *content );
else
push();
return true;
}