#include "lexer.h"

using namespace empathy;
using namespace empathy::util;
using namespace empathy::ir;

void Lexer::newLine()
{
    ++m_lineNum;
    m_lastLineBreakOffset = m_input.tellg();
}

void Lexer::skipSpacingIfAny()
{
    while( m_input.good() )
    {
        auto c = m_input.peek();

        if( isspace( c ) )
        {
            m_input.get();
            continue;
        }

        if( c == '\n' )
        {
            m_input.get();
            newLine();
            continue;
        }

        if( c == '/' )
        {
            m_input.get();
            c = m_input.peek();
            if( c == '/' )
                skipLineComment();
            else if( c == '*' )
            {
                m_input.get();
                skipBlockComment();
            }
            else
            {
                m_input.unget();
                return;
            }

            continue;
        }

        return;
    }
}

optional< Term > Lexer::readToken()
{
    skipSpacingIfAny();
    if( !m_input.good() )
        return nullopt;

    ir::Location loc( m_filename, m_lineNum, m_input.tellg() - m_lastLineBreakOffset );

    auto c = m_input.peek();
    switch( c )
    {
        case '{':
            m_input.get();
            return ir::Term( move( loc ), "{"_sid );

        case '}':
            m_input.get();
            return ir::Term( move( loc ), "}"_sid );

        case '(':
            m_input.get();
            return ir::Term( move( loc ), "("_sid );

        case ')':
            m_input.get();
            return ir::Term( move( loc ), ")"_sid );

        case '[':
            m_input.get();
            return ir::Term( move( loc ), "["_sid );

        case ']':
            m_input.get();
            return ir::Term( move( loc ), "]"_sid );
    }

    return nullopt;
}
