Скачиваний:
11
Добавлен:
01.05.2014
Размер:
4.87 Кб
Скачать

// File:        SyntaxAn.cpp

#include "StdAfx.h"
#include "SyntaxAn.h"
#include "ErrorHandler.h"
#include "PASCAL.h"
#include "Interfaces.h"
//-----------------------------------------------------------------------------

CSyntAnalyzer::CSyntAnalyzer()
{ 
    InitTokens(PASCAL_Terms, PASCAL_RulesCount);
    InitRules(PASCAL_Rules,  PASCAL_RulesCount);
    InitTables(PASCAL_Action, PASCAL_FCount, PASCAL_Goto, PASCAL_GCount);
}

//-----------------------------------------------------------------------------
// Достаточно дорогая операция...
// так что я бы не стал её на лету делать по несколько раз
void CSyntAnalyzer::InitTables(FInfo FV[], unsigned FVLen, GInfo GV[], unsigned GVLen)
{
    unsigned i;
    CSymbol sym;
    for (i = 0; i < FVLen; ++i)
    {
        m_TableAct.At(FV[i].StackSym, FV[i].Terminal) = FV[i].Action;
    }
    for (i = 0; i < GVLen; ++i)
    {
        if (GV[i].bIsTerm)
             sym = CSymbol((EnumT)  GV[i].Symbol );
        else sym = CSymbol((EnumNT) GV[i].Symbol );
        m_TableTrans.At(GV[i].StackSym, sym) = CStackSymbol(GV[i].State);
    }
}

//-----------------------------------------------------------------------------

void CSyntAnalyzer::InitRules(RuleInfo RI[], unsigned RulesCount)
{
    m_vRulesInfo.assign(RI, RI + RulesCount);
}

//-----------------------------------------------------------------------------

void CSyntAnalyzer::InitTokens(ENUM_TOKENS Tokens[], unsigned Count)
{
    for (unsigned i = 0; i < Count; ++i)
        m_Tokens.insert(Tokens[i]);
}

//-----------------------------------------------------------------------------

int CSyntAnalyzer::f(const CSymbol &sym)
{
    int res;
    if (!m_TableAct.Find(m_Stack.top(), sym, res)) return ACT_ERROR;
    bool bActionFound = m_TableAct.Find(m_Stack.top(), sym, res);
    return res;
}

//-----------------------------------------------------------------------------

bool CSyntAnalyzer::FindToken(ENUM_TOKENS Tkn)
{
    return (m_Tokens.find(Tkn) != m_Tokens.end());
}

//-----------------------------------------------------------------------------
// Если соответствующий магазинный символ не найден возвращается символ дна

CStackSymbol CSyntAnalyzer::g( const CSymbol& sym )
{
    CStackSymbol res(STACK_BOTTOM);
    m_TableTrans.Find(m_Stack.top(), sym, res);
    return res;
}

//-----------------------------------------------------------------------------
// Мегаалгоритм, описанный в методе про восходящие методы, стр. 51

bool CSyntAnalyzer::Analyze(CTokenStream::iterator it_token, CTokenStream::iterator it_end)
{
    ENUM_TOKENS CurToken;
    CStackSymbol StSym( STACK_BOTTOM );
    // предварительно нужно занести в стэк специальный символ - дно магазина !!!
    m_Stack.push( StSym );

    // Пока всё не сделаем домой не пойдём :)
    while (true)
    {
        CurToken = (ENUM_TOKENS)(*it_token);
        CSymbol Sym = CSymbol(CurToken);

        int action  = f( Sym );
        assert(action >= -3);
        switch( action )
        {
            case ACT_OK: return true;

            case ACT_ERROR:
                // тут должна быть некоторая обработка ошибок
                g_ErrorHandler.Error(CError(ERR_SYNTAX_ERROR, it_token->Line()));
                return false;
            break;

            case ACT_TRANSFER:  // ПЕРЕНОС ---------
                if (!m_TableTrans.Find(m_Stack.top(), Sym, StSym))
                {
                    // ОШИБКА, тоже надо как-то обработать
                    g_ErrorHandler.Error(CError(ERR_SYNTAX_ERROR, it_token->Line()));
                    return false; 
                }
                // Инициализируем атрибуты
                StSym.Attributes().pToken  = it_token;
                m_Stack.push(StSym);
                it_token++;
            break;

            default:    // СВЁРТКА -----------------
                // Если мы попали сюда, значение action должно быть >= 0
                assert(action >= 0); 

                // Выполняем вычисление атрибутов и прочее и прочее...
                SAttrSet AttrSet;
                Operation(action, AttrSet);

                // неким образом делаем свёртку по правилу с номером action
                // сначала удаляем из стека нужное число символов
                for (int i = 0; i < m_vRulesInfo[action].Length; ++i)
                    m_Stack.pop();

                // Определяем новый символ T"=g(A)
                StSym = g(m_vRulesInfo[action].LeftSide);
                // Копируем аттрибуты
                StSym.Attributes() = AttrSet;
                // Пихаем в стек
                m_Stack.push( StSym );
            break;
        }
    }
    return true;
}
//-----------------------------------------------------------------------------
Соседние файлы в папке Курсовая работа2