/*
 * Copyright (c) 2014, Sandia Corporation.
 * Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
 * the U.S. Government retains certain rights in this software.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *
 *     * Neither the name of Sandia Corporation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
#ifndef EXAMPLE_SCANNER_H
#define EXAMPLE_SCANNER_H

// Flex expects the signature of yylex to be defined in the macro YY_DECL, and
// the C++ parser expects it to be declared. We can factor both as follows.

#ifndef YY_DECL

#define YY_DECL SEAMS::Parser::token_type SEAMS::Scanner::lex(SEAMS::Parser::semantic_type *yylval)
#endif

#ifndef __FLEX_LEXER_H
#define yyFlexLexer SEAMSFlexLexer
#include "FlexLexer.h"
#undef yyFlexLexer
#endif

#include "aprepro_parser.h"

namespace SEAMS {

  /** Scanner is a derived class to add some extra function to the scanner
   * class. Flex itself creates a class named yyFlexLexer, which is renamed using
   * macros to SEAMSFlexLexer. However we change the context of the generated
   * yylex() function to be contained within the Scanner class. This is required
   * because the yylex() defined in SEAMSFlexLexer has no parameters. */
  class Scanner : public SEAMSFlexLexer
  {
  public:
    friend class Parser;

    /** Create a new scanner object. The streams arg_yyin and arg_yyout default
     * to cin and cout, but that assignment is only made when initializing in
     * yylex(). */
    Scanner(Aprepro &aprepro_yyarg, std::istream *arg_yyin = nullptr,
            std::ostream *arg_yyout = nullptr);
    /** Required for virtual functions */
    virtual ~Scanner();

    void add_include_file(const std::string &filename, bool file_must_exist);
    int  yywrap() override;
    void yyerror(const char *s);
    void LexerOutput(const char *buf, int size) override;
    int LexerInput(char *buf, int max_size) override;

    /** This is the main lexing function. It is generated by flex according to
     * the macro declaration YY_DECL above. The generated bison parser then
     * calls this virtual function to fetch new tokens. */
    virtual Parser::token_type lex(Parser::semantic_type *yylval);

    char *rescan(char *string);
    char *execute(char *string);
    char *if_handler(double x);
    char *elseif_handler(double x);
    char *switch_handler(double x);
    char *case_handler(double x);

    /** Enable debug output (via arg_yyout) if compiled into the scanner. */
    void set_debug(bool b);

    /* User arguments.  */
    class Aprepro &aprepro;

    /* save the original string for substitution history */
    void save_history_string();
  };

} // namespace SEAMS

#endif // EXAMPLE_SCANNER_H
