#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#    This file is part of arena.
#   
#    arena is free software: you can redistribute it and/or modify it
#    under the terms of the GNU General Public License as published by the
#    Free Software Foundation; either version 3 of the License or, at your
#    option, any later version.
#
#    arena is distributed in the hope that it will be useful, but
#    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABLITY
#    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
#    License for more details.
#
#    You should have received a copy of the GNU General Public License along
#    with arena.  If not, see <http://www.gnu.org/licenses/>. 

## @file
#  This file defines a class that aids in determining the semantics of a 
#  computer language.

from Library.Base.Classwork import AnObject
from Library.Parse.Lex.Opcodes import AnOpcodeSet
from Library.Memory.Dictionaries import ADictionary

## Character types that are recognized by a parser
class CharacterType:
    dummy       = 0
    symbol      = 1
    letter      = 2
    alpha       = 3
    digit       = 4
    numeric     = 5
    quote       = 6
    space       = 7
    endOfLine   = 8
    endOfStream = 9
    error       = 10
    count       = 11

## Token types that are recognized by a parser
class TokenType:
    dummy          = 0
    identifier     = 0x00010000
    typeIdentifier = 0x00020000 
    keyword        = 0x00030000
    number         = 0x00040000
    string         = 0x00050000
    special        = 0x00060000
    operator       = 0x00070000
    space          = 0x00080000
    endOfLine      = 0x00090000
    endOfStream    = 0x000A0000
    error          = 0xEEEE0000

## The specifications for a computer language that will be parsed by a parser.
class AComputerLanguage(AnObject):
    ## Constructor
    def __init__(Self):
        AnObject.__init__(Self)
    
    ## Initializer    
    def init(Self):
        result = AnObject.init(Self)
        
        if result == True:
            # Establish private attributes
            # Whether or not the language is case-sensitive
            Self._caseAware = True
            # Opcodes recognized by the language
            Self._Opcodes = AnOpcodeSet()
            # Opcode sets used to define the syntax of the language
            Self._Rules = ADictionary()
            # Establish public attributes
            # Character sets recognized by the language
            Self.characters = list()
            for i in xrange(0, (CharacterType.count - 1)):
                Self.characters.append("")
            
        return result
     
    ## Destructor
    def __del__(Self):
        del Self.characters
        del Self._Rules
        del Self._Opcodes
        
        AnObject.__del__(Self)
        
    ## Register opcodes recognized by the language.
    #    
    #  The parameter values passed are inserted into the opcodes list for
    #  the language instance.  The number of opcodes successfully registered
    #  is returned by the call.
    def registerOpcodes(Self, **items):
        if len(items) > 0:
            return Self._Opcodes.update(**items)
            
        return 0
        
    ## Retrieve the type code for the specified character.
    def typeOf(Self, thisCharacter):
        result = CharacterType.dummy
        
        for i in xrange(0, (CharacterType.count - 1)):
            if thisCharacter in Self.characters[i]:
                result = i
                break
                    
        return result
        
    ## Retrieve the token type code for the specified token string.
    def meaningOf(Self, thisToken):
        result = TokenType.dummy
        
        if len(thisToken) > 0:
            if Self._caseAware == False:
                thisToken.lower()
                
            ThisOpcode = Self._Opcodes.fetch(thisToken)
            if ThisOpcode is not None:
                result = ThisOpcode.value
                
        return result
    
    # Properties ---------------------------------------------------------------
    ## Return whether or not the language is case-sensitive.
    def isCaseAware(Self):
        return Self._caseAware
        
    ## Retrieve the list of opcodes used by the language.
    def Opcodes(Self):
        return Self._Opcodes
        
    ## Retrieves the specified rule
    def Rule(Self, ruleName):
        
        return Self._Rules[ruleName]
        
    ## Retrieve the list of syntax rules used by the language.
    def Rules(Self):            
        return Self._Rules
