# -*- 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 represents a single statement parsed from a
#  source stream.

from Library.Base.Events import ALoggingEventfulObject
from Library.String.Utilities import IsPrintable

## Events generated by AStatement
stmtEvents = {
    ## Before the statement is parsed
    "parse": None
}

## A statement parsed from code. 
#    
#  This class is not meant to be instantiated directly; rather, it sets up an
#  environment for its descendant classes that makes it easy to focus on
#  parsing the statement.
class AStatement(ALoggingEventfulObject):
    ## Construct a statement instance.
    #
    #  In addition to the parameters expected by
    #  ALoggingEventfulObject.__init__(), this routine expects that \p params
    #  will contain the following items:
    #  - \p Parser -- The parser instance for which the statement will be parsed
    def __init__(Self, **params):
        ALoggingEventfulObject.__init__(Self, **params)
        
        if "Parser" in Self._params:
            Self._Parser = Self._params["Parser"]
            del Self._params["Parser"]
            
            Self._Source = Self._Parser.Scanner()
            Self._Output = Self._Parser.Output()
            Self._Log = Self._Parser.Log()
       
    ## Initializer
    def init(Self):
        result = ALoggingEventfulObject.init(Self)
        
        if result:
            # Establish private attributes
            # The value of the statement
            Self._value = None
            # The log used to output status and error messages
            Self._Log = None
            # The scanner used to scan source code
            Self._Source = None
            # The parser used to parse source code
            Self._Parser = None
            # The destination for parser output
            Self._Output = None
            
            # Update the events generated by the class
            Self._events.update(stmtEvents)
            
        return result
        
    ## Parse the statement.
    #    
    #  This method should be implemented by descendant classes.  It does 
    #  nothing in the base implementation of AStatement.
    def parse(Self):
        Event = Self.generate("parse")
        del Event
        
    ## Construct and parse a statement from the specified parser. 
    @classmethod
    def ParsedFrom(Self, ThisParser):
        NewStatement = None
        
        if ThisParser is not None:
            NewStatement = Self(ThisParser)
        
        return NewStatement
        
    # IsPrintable implementation -----------------------------------------------
    ## Construct a string representation of the statement.
    #
    #  In the base implementation of this method, the representation is
    #  simply the value of the statement.  Descendant classes may override this
    #  method to produce different output.
    def toString(Self):
        return str(Self._value)
        
    # Properties ---------------------------------------------------------------
    ## Retrieve the value of the statement.
    def value(Self):
        return Self._value
        
    ## Retrieve the log used by the statement.
    def Log(Self):
        return Self._Log
        
    ## Retrieve the scanner used by the statement.
    def Source(Self):
        return Self._Source

    ## Retrieve the parser used by the statement.
    def Parser(Self):
        return Self._Parser
        
    ## Retrieve the output used by the statement
    def Output(Self):
        return Self._Output
        
    ## Set the output used by the statement
    def OutputTo(Self, NewOutput):
        if Self._Parser is not None:
            PreviousOutput = Self._Parser.OutputTo(NewOutput)
            Self._Output = Self._Parser.Output()
            return PreviousOutput
            
        return None
