# Copyright (C) 2003, 2004 Gregoire Lejeune <gregoire.lejeune@free.fr>
#
# This program 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 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA

class AspCompiler
  require "asp/subsmatch"

  AspTag = /(<%%[\t ]*)|([\t ]*%%>)|(<%=[\t ]*)|(<%#[\t ]*)|(<%[\t ]*)|([\t ]*%>)/
  
  private
  def _addCode( code, state, last, inline )
    xCode = "# ERROR"
    case state
      when 0
        if last == 1
          xCode = ", " + code.dump
        else
          xCode = ((inline == true)?"; ":"") + @put_cmd + " " + code.dump
          @print_mode = true
        end
      when 1
        if last == 0
          if inline == true
            xCode = ", " + code
          else
            xCode = @put_cmd + " " + code
            @print_mode = true
          end
        else
          xCode = ((inline == true)?"; ":"") + @put_cmd + " " + code
          @print_mode = true
        end
      when 2
        xCode = ((inline == true)?"; ":"") + code
      when 3
        xCode = "# " + code + "\n"
      when 4
        xCode = "# -IGN- " + code + "\n"
      else
        @error = true
        @error_message = sprintf( "Add code status #%d", state )
        return nil
    end
   
    return xCode 
  end

  public
  def compile( data )
    @init_code = data
    
    data = submatch( data )
    if data.nil? == true
      return nil
    end
    @subm_code = data
    
    xCode = ""
    iLine = 0
    ## 
    # Rem: Status := 0 = undef
    #                1 = print
    #                2 = code
    #                3 = comment
    #                4 = ignore
    #
    iStatus = 0
    bOpenTag = false

    data.each do |line|
      xKeepLine = line
      line.chomp!
      
      iLine = iLine + 1
      iLast = 0
      bInLine = false
      @print_mode = false
      
      xAddToCompile = ""

      while res = AspTag.match( line )
        preTag = xAddToCompile + res.pre_match
        xAddToCompile = ""
        
        aspTagKeep = res[0]
        aspTag = aspTagKeep.strip
        
        line = res.post_match

        iAddCodeStatus = iStatus
        iAddCodeLast = iLast
        bAddCode = true
        
        case aspTag
          when "<%="
            if bOpenTag == false
              iStatus = 1
              bOpenTag = true
            else
              bAddCode = false
            end
          when "<%#"
            if bOpenTag == false
              iStatus = 3
              bOpenTag = true
            else
              bAddCode = false
            end
          when "<%%"
            if bOpenTag == false
              iStatus = 4
              bOpenTag = true
            else
              bAddCode = false
            end
          when "<%"
            if bOpenTag == false
              iStatus = 2
              bOpenTag = true
            else
              bAddCode = false
            end
          when "%>"
            if bOpenTag == true
              iLast = iStatus
              iStatus = 0
              bOpenTag = false
            else
              bAddCode = false
            end
          else
            @error = true
            @error_line = iLine
            @error_code = @subm_code
            @error_message = sprintf( "Tag %s unknow", aspTag )
            iStatus = -1
            return nil
        end
        
        if preTag.nil? == false and preTag.length > 0 and bAddCode == true 
          xAddCode = _addCode( preTag, iAddCodeStatus, iAddCodeLast, bInLine )
          if xAddCode.nil? == true
            @error_line = iLine
            @error_code = @subm_code
            return nil
          end
          xCode = xCode + xAddCode
          bInLine = true
        elsif bAddCode == false
          xAddToCompile = preTag + aspTagKeep
        end

      end
      
      line = xAddToCompile + line
      if line.nil? == false and line.length > 0
        xAddCode = _addCode( line, iStatus, iLast, bInLine )
        if xAddCode.nil? == true
          @error_line = iLine
          @error_code = @subm_code
          return nil
        end
        xCode = xCode + xAddCode
      end
     
      xCode = xCode + ((iStatus != 3 and @print_mode == true)?'; print "\n"':'')
      xCode = xCode + ((iStatus != 3)?"\n":"")
    end

    @comp_code = xCode
    return xCode
  end
  
  def initialize
    @print_mode = false
    @put_cmd = 'print'
    @pre_cmd = []
    @post_cmd = []

    @init_code = ""
    @subm_code = ""
    @comp_code = ""

    @error = false
    @error_line = 0
    @error_code = ""
    @error_message = ""
  end

  attr :put_cmd, true
  attr :pre_cmd, true
  attr :post_cmd, true 

  attr :init_code, true
  attr :subm_code, true
  attr :comp_code, true
  
  attr :error, true
  attr :error_line, true
  attr :error_code, true
  attr :error_message, true
end
