/* Objective Modula-2 Compiler (objm2c)
 *
 *  @file objm2_tokenset.h
 *  ObjM2 token set interface
 *
 *  Syntax analysis for ObjM2 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-08-10   BK   new file
 *          2009-09-20   BK   amended for use with gen_first_and_follow_sets.c
 *          2009-09-23   BK   changed all instances of enumerator to iterator
 */


#ifndef OBJM2_TOKENSET_H
#define OBJM2_TOKENSET_H

#include "common_types.h"
#include "objm2_tokens.h"
#include "objm2_productions.h"


// ---------------------------------------------------------------------------
// Tokenset segmentation
// ---------------------------------------------------------------------------

// IMPLEMENTATION DEPENDENT DATA - DO NOT MODIFY !!!
#define OBJM2_TOKENSET_BITS_PER_SEGMENT 32

// IMPLEMENTATION DEPENDENT DATA - DO NOT MODIFY !!!
#define OBJM2_TOKENSET_SEGMENTS_PER_SET \
    ((OBJM2_NUMBER_OF_TOKENS / OBJM2_TOKENSET_BITS_PER_SEGMENT) + 1)


// --------------------------------------------------------------------------
// Opaque tokenset 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_tokenset_t;


// --------------------------------------------------------------------------
// Opaque tokenset iterator 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_tokenset_iterator_t;


// ---------------------------------------------------------------------------
// Empty token set
// ---------------------------------------------------------------------------

#define OBJM2_EMPTY_TOKENSET objm2_tokenset_from_list(0)


// --------------------------------------------------------------------------
// function:  objm2_tokenset_from_list( token_list )
// --------------------------------------------------------------------------
//
// Returns a new token set with the tokens passed as parameters included.  At
// least one token must be passed.  Further tokens  may be passed as variadic
// parameters.  The list of tokens must always be terminated  by passing zero
// as the last argument in the function call.  Values passed in that are out-
// side of the range of defined tokens are ignored.  If zero is passed as the
// only argument,  an empty token set is returned.

objm2_tokenset_t objm2_tokenset_from_list(objm2_token_t first_token, ...);


// --------------------------------------------------------------------------
// function:  objm2_tokenset_is_element( set, token )
// --------------------------------------------------------------------------
//
// Tests membership of token <token> in token set <set>.  Returns true if the
// token is a member,  token ∈ set,  returns false  otherwise.  If a value is
// passed that is outside the range of defined tokens,  false is returned.

bool objm2_tokenset_is_element(objm2_tokenset_t set, objm2_token_t token);


// --------------------------------------------------------------------------
// function:  objm2_tokenset_is_subset( set1, set2 )
// --------------------------------------------------------------------------
//
// Returns true if token set <set2> is a subset of token set <set1>,  that is
// if all elements of token set <set2> are also elements of token set <set1>,
// set2 ⊆ set1,  returns false otherwise.

bool objm2_tokenset_is_subset(objm2_tokenset_t set1, objm2_tokenset_t set2);


// --------------------------------------------------------------------------
// function:  objm2_tokenset_is_disjunct( set1, set2 )
// --------------------------------------------------------------------------
//
// Tests if token sets <set1>  and <set2>  are disjunct,  Returns true if the
// sets are disjunct,  set1 ∩ set2 = {},  returns false otherwise.

bool objm2_tokenset_is_disjunct(objm2_tokenset_t set1, objm2_tokenset_t set2);


// --------------------------------------------------------------------------
// function:  objm2_tokenset_incl( set, token )
// --------------------------------------------------------------------------
//
// Includes token  <token>  in token set  <set>.  Any value passed in that is
// outside of the range of defined tokens is ignored.

void objm2_tokenset_incl(objm2_tokenset_t set, objm2_token_t token);


// --------------------------------------------------------------------------
// function:  objm2_tokenset_excl( set, token )
// --------------------------------------------------------------------------
//
// Excludes token  <token>  in token set  <set>.  Any value passed in that is
// outside of the range of defined tokens is ignored.

void objm2_tokenset_excl(objm2_tokenset_t set, objm2_token_t token);


// --------------------------------------------------------------------------
// function:  objm2_tokenset_incl_list( set, token_list )
// --------------------------------------------------------------------------
//
// Includes  the tokens  passed as  variadic parameters  in token set  <set>.
// The list of tokens must be terminated by passing zero as the last argument
// in the function call.  Any value passed in that is outside of the range of
// defined tokens is ignored.

void objm2_tokenset_incl_list(objm2_tokenset_t set, ...);


// --------------------------------------------------------------------------
// function:  objm2_tokenset_excl_list( set, token_list )
// --------------------------------------------------------------------------
//
// Excludes the tokens  passed as variadic parameters  from token set  <set>.
// The list of tokens must be terminated by passing zero as the last argument
// in the function call.  Any value passed in that is outside of the range of
// defined tokens is ignored.

void objm2_tokenset_excl_list(objm2_tokenset_t set, ...);


// --------------------------------------------------------------------------
// function:  objm2_tokenset_union( set1, set2 )
// --------------------------------------------------------------------------
//
// Returns the union of token sets <set1> and <set2>,  set1 ∪ set2.

objm2_tokenset_t objm2_tokenset_union(objm2_tokenset_t set1,
                                      objm2_tokenset_t set2);


// --------------------------------------------------------------------------
// function:  objm2_tokenset_intersection( set1, set2 )
// --------------------------------------------------------------------------
//
// Returns the intersection of token sets <set1> and <set2>,  set1 ∩ set2.

objm2_tokenset_t objm2_tokenset_intersection(objm2_tokenset_t set1,
                                             objm2_tokenset_t set2);


// --------------------------------------------------------------------------
// function:  objm2_tokenset_difference( set1, set2 )
// --------------------------------------------------------------------------
//
// Returns the difference of token sets <set1> and <set2>,  set1 \ set 2.

objm2_tokenset_t objm2_tokenset_difference(objm2_tokenset_t set1, 
                                           objm2_tokenset_t set2);


// ---------------------------------------------------------------------------
// function:  objm2_tokenset_first_set( production )
// ---------------------------------------------------------------------------
//
// Returns the FIRST set of production <production>.

objm2_tokenset_t objm2_tokenset_first_set(objm2_production_t production);


// ---------------------------------------------------------------------------
// function:  objm2_tokenset_follow_set( production )
// ---------------------------------------------------------------------------
//
// Returns the FOLLOW set of production <production>.

objm2_tokenset_t objm2_tokenset_follow_set(objm2_production_t production);


// ---------------------------------------------------------------------------
// function:  objm2_tokenset_dispose( set )
// ---------------------------------------------------------------------------
//
// Disposes of tokenset <set>.

void objm2_tokenset_dispose(objm2_tokenset_t set);


// ---------------------------------------------------------------------------
// function:  objm2_tokenset_iterator( set )
// ---------------------------------------------------------------------------
//
// Returns a new iterator for tokenset <set>.

objm2_tokenset_iterator_t objm2_tokenset_iterator(objm2_tokenset_t set);


// ---------------------------------------------------------------------------
// function:  objm2_tokenset_iterator_token_count( iterator )
// ---------------------------------------------------------------------------
//
// Returns the number of tokens in tokenset iterator <iterator>.

cardinal
    objm2_tokenset_iterator_token_count(objm2_tokenset_iterator_t iterator);


// ---------------------------------------------------------------------------
// function:  objm2_tokenset_iterator_token_at_index( iterator, index )
// ---------------------------------------------------------------------------
//
// Returns the token at index <index> in tokenset iterator <iterator>.

objm2_token_t
    objm2_tokenset_iterator_token_at_index(objm2_tokenset_iterator_t iterator,
                                                            cardinal index);


// ---------------------------------------------------------------------------
// function:  objm2_tokenset_iterator_for_first_set( production )
// ---------------------------------------------------------------------------
//
// Returns an iterator for the FIRST set of production <production>.

objm2_tokenset_iterator_t
    objm2_tokenset_iterator_for_first_set(objm2_production_t production);


// ---------------------------------------------------------------------------
// function:  objm2_tokenset_iterator_follow_set( production )
// ---------------------------------------------------------------------------
//
// Returns an iterator for the FOLLOW set of production <production>.

objm2_tokenset_iterator_t
    objm2_tokenset_iterator_for_follow_set(objm2_production_t production);


// ---------------------------------------------------------------------------
// function:  objm2_tokenset_iterator_dispose( iterator )
// ---------------------------------------------------------------------------
//
// Disposes of tokenset iterator <iterator>.

void objm2_tokenset_iterator_dispose(objm2_tokenset_iterator_t iterator);


#endif /* OBJM2_TOKENSET_H */

// END OF FILE
