/* Objective Modula-2 Compiler (objm2c)
 *
 *  @file objm2_lexer.h
 *  Objective Modula-2 lexer interface
 *
 *  Lexical analysis for Objetive Modula-2 source files
 *
 *  Author: Benjamin Kowarsch
 *
 *  Copyright (C) 2009 The Objective Modula-2 Project. All rights reserved.
 *
 *  License:
 *
 *  Redistribution  and  use  in source  and  binary forms,  with  or  without
 *  modification, are permitted provided that the following conditions are met
 *
 *  1) This file,  or any part thereof,  may  NOT  be hosted on websites which
 *     contain advertising,  unless specific prior written permission has been
 *     obtained.  The licensor will grant such permission  upon request at its
 *     sole discretion to websites the licensor does  NOT  consider abusive in
 *     their  use  of advertising.  Small notices  in the footer  of a website
 *     naming corporate rights holders,  infrastructure providers  or sponsors
 *     are not considered advertising in the context of this license.
 *
 *  2) Redistributions  of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *
 *  3) Redistributions  in binary form  must  reproduce  the  above  copyright
 *     notice,  this list of conditions  and  the following disclaimer  in the
 *     documentation and other materials provided with the distribution.
 *
 *  4) Neither the author's name nor the names of any contributors may be used
 *     to endorse  or  promote  products  derived  from this software  without
 *     specific prior written permission.
 *
 *  5) Where this list of conditions  or  the following disclaimer, in part or
 *     as a whole is overruled  or  nullified by applicable law, no permission
 *     is granted to use the software.
 *
 * 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 HOLDER 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.
 *  
 *  Version history:
 *
 *   2.00   2009-01-31   BK   new file from various spin-offs of v.1.x
 *          2009-08-25   BK   simplified interface
 */


#ifndef OBJM2_LEXER_H
#define OBJM2_LEXER_H


#include "common_types.h"
#include "objm2_key_value_storage.h"


// --------------------------------------------------------------------------
// Opaque lexer handle type
// --------------------------------------------------------------------------
//
// WARNING: Objects of this opaque type should only be accessed through this
// public interface.  DO NOT EVER attempt to bypass the public interface.
//
// The internal data structure of this opaque type is HIDDEN  and  MAY CHANGE
// at any time WITHOUT NOTICE. Accessing the internal data structure directly
// other than through the  functions  in this public interface is  UNSAFE and
// may result in an inconsistent program state or a crash.

typedef opaque_t objm2_lexer_t;


// --------------------------------------------------------------------------
// Status codes
// --------------------------------------------------------------------------

typedef /* objm2_lexer_status_t */ enum {
    OBJM2_LEXER_STATUS_UNDEFINED = -1,
    
    // operation completed successfully
    OBJM2_LEXER_STATUS_SUCCESS = 0,
    
    // invalid pointer to lexer object passed
    OBJM2_LEXER_STATUS_INVALID_REFERENCE,
    
    // unable to allocate memory
    OBJM2_LEXER_STATUS_ALLOCATION_FAILED,
    
    // illegal character found
    OBJM2_LEXER_STATUS_ILLEGAL_CHARACTER,
    
    // literal exceeds maximum length
    OBJM2_LEXER_STATUS_LITERAL_TOO_LONG,

    // numeric literal is malformed
    OBJM2_LEXER_STATUS_MALFORMED_NUMBER,

    // string literal is missing delimiting quotation
    OBJM2_LEXER_STATUS_STRING_NOT_DELIMITED,
    
    // nested M2 comment exceeds maximum nesting level
    OBJM2_LEXER_STATUS_COMMENT_NESTING_LIMIT_REACHED
} objm2_lexer_status_t;


// --------------------------------------------------------------------------
// function:  objm2_new_lexer(infile, lextab, status)
// --------------------------------------------------------------------------
//
// Creates  and  returns  a  new  lexer object  associated  with  source file 
// <infile> and lexeme table <lextab>.  The status of the operation is passed
// back in <status> unless NULL is passed in for <status>.
//
// Returns NULL if the lexer object could not be created.

objm2_lexer_t objm2_new_lexer(FILE *infile,
                 objm2_kvs_table_t lextab,
              objm2_lexer_status_t *status);


// ---------------------------------------------------------------------------
// function:  objm2_lexer_getsym(lexer, lexeme, status)
// ---------------------------------------------------------------------------
//
// Reads one symbol from the input stream of lexer <lexer>, returns its token,
// and passes a key for its lexeme back in <lexeme> unless  NULL  is passed in
// for <lexeme>.  The  status  of  the  operation  is  passed back in <status>
// unless NULL is passed in for <status>.

objm2_token_t objm2_lexer_getsym(objm2_lexer_t lexer,
                                      cardinal *lexeme
                          objm2_lexer_status_t *status);


// ---------------------------------------------------------------------------
// function:  objm2_lexer_getpos(lexer, row, col, status)
// ---------------------------------------------------------------------------
//
// Obtains the position of the last symbol read from the input stream.  Passes
// the row back in <row>  unless NULL is passed in for <row>,  and the coloumn
// back in <col>  unless  NULL  is  passed  in  for <col>.  The status  of the
// operation is passed back in <status> unless NULL is passed in for <status>.

void objm2_lexer_getpos(objm2_lexer_t lexer,
                             cardinal *row,
                             cardinal *col,
                 objm2_lexer_status_t *status);


// ---------------------------------------------------------------------------
// function:  objm2_offending_char(lexer, row, col, status)
// ---------------------------------------------------------------------------
//
// Returns the offending character of the last read operation  and  passes its
// position  back  in  <row>  and <col>.  If no error occurred during the last
// read operation then ASCII NUL is returned  and zero is passed pack in <row>
// and <col>.  This function should only be called  after a preceeding call to
// function objm2_lexer_getsym()  returned an error indicating that an illegal
// or unexcpected character was found.  The status of the operation  is passed
// back in <status> unless NULL is passed in for <status>.

char objm2_offending_char(objm2_lexer_t lexer,
                               cardinal *row,
                               cardinal *col,
                   objm2_lexer_status_t *status);


// ---------------------------------------------------------------------------
// function:  objm2_dispose_lexer(lexer, status)
// ---------------------------------------------------------------------------
//
// Deallocates  lexer object <lexer>.  The function does  not  close the input
// stream  and  it  does  not  deallocate the lexeme table associated with the
// lexer object.  The  status  of  the  operation  is  passed back in <status>
// unless NULL is passed in for <status>.

void objm2_dispose_lexer(objm2_lexer_t lexer,
                         objm2_lexer_status_t *status);


#endif /* OBJM2_LEXER_H */

// END OF FILE