/*
 * Copyright (c) 2008-2015 Freescale Semiconductor, Inc.
 * Copyright 2016-2018 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

// This header just wraps the standard flex C++ header to make it easier to include
// without having to worry about redefinitions of the class name every time.

#if !defined(_ElftosbLexer_h_)
#define _ElftosbLexer_h_

#include "ElftosbAST.h"
#include "FlexLexer.h"
#include "elftosb_parser.tab.hpp"
#include <vector>
#include <string>
#include <stdexcept>
#include "Blob.h"

using namespace std;

namespace elftosb
{
/*!
 * \brief Exception class for syntax errors.
 */
class syntax_error : public std::runtime_error
{
public:
    explicit syntax_error(const std::string &__arg)
        : std::runtime_error(__arg)
    {
    }
};

/*!
 * \brief Exception class for lexical errors.
 */
class lexical_error : public std::runtime_error
{
public:
    explicit lexical_error(const std::string &__arg)
        : std::runtime_error(__arg)
    {
    }
};

/*!
 * \brief Lexical scanner class for elftosb command files.
 *
 * This class is a subclass of the standard C++ lexer class produced by
 * Flex. It's primary purpose is to provide a clean way to report values
 * for symbols, without using the yylval global. This is necessary because
 * the parser produced by Bison is a "pure" parser.
 *
 * In addition, this class manages a list of source names generated by
 * parsing. The lexer uses this list to determine if an identifier is
 * a source name or a constant identifier.
 */
class ElftosbLexer : public yyFlexLexer
{
public:
    //! \brief Constructor.
    ElftosbLexer(istream &inputStream);

    //! \brief Lexer interface. Returns one token.
    virtual int yylex();

    //! \brief Returns the value for the most recently produced token in \a value.
    virtual void getSymbolValue(YYSTYPE *value);

    //! \brief Returns the current token's location in \a loc.
    inline token_loc_t &getLocation() { return m_location; }
    //! \name Source names
    //@{
    void addSourceName(std::string *ident);
    bool isSourceName(std::string *ident);
    //@}

protected:
    YYSTYPE m_symbolValue;  //!< Value for the current token.
    int m_line;             //!< Current line number.
    token_loc_t m_location; //!< Location for the current token.
    Blob *m_blob;           //!< The binary object value as its being constructed.
    int m_blobFirstLine;    //!< Line number for the first character of a blob.

    typedef std::vector<std::string> string_vector_t;
    string_vector_t m_sources; //!< Vector of source identifiers;

    //! \brief Throw an elftosb::lexical_error exception.
    virtual void LexerError(const char *msg);

    //! \brief Process a string containing escape sequences.
    int processStringEscapes(const char *in, char *out);
};

}; // namespace elftosb

#endif // _ElftosbLexer_h_
