package osa.attribute.atgrammar.grammar.symbols;


import java.util.*;
import java.lang.*;

/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: </p>
 * <p>Company: </p>
 * @author not attributable
 * @version
 */

public class LexicalScanner
  {
  protected class AutomatonState
    {
    protected String name;
    protected ArrayList transitions=new ArrayList();
    protected boolean is_final;

    public AutomatonState(String name, boolean is_final)
      {
      this.name=name;
      this.is_final=is_final;
      }

    public void addTransition(AutomatonTransition transition)
      {
      transitions.add(transition);
      }

    public AutomatonTransition getTransitionAt(int index)
      {
      if(index>getTransitionsCount()||index<0)
        {
        System.err.println("Out of bounds!!!");
        return null;
        }
      return (AutomatonTransition)transitions.get(index);
      }

    public int getTransitionsCount()
      {
      return transitions.size();
      }
    }

  protected class AutomatonTransition
    {
    protected AutomatonState target_state;
    protected char input_symbol;
    protected char output_symbol;
    protected boolean is_shifting;

    public AutomatonTransition(AutomatonState target_state,
                               char input_symbol,
                               char output_symbol,
                               boolean is_shifting)
      {
      this.target_state=target_state;
      this.input_symbol=input_symbol;
      this.output_symbol=output_symbol;
      this.is_shifting=is_shifting;
      }

    public AutomatonState getTargetState()
      {
      return target_state;
      }

    public char getInputSymbol()
      {
      return input_symbol;
      }

    public boolean isShifting()
      {
      return is_shifting;
      }
    }

  protected class StringReader
    {
    protected String input_string;
    protected int position;
    protected int string_length;

    public StringReader(String input_string)
      {
      this.input_string=input_string;
      this.position=0;
      this.string_length=input_string.length();
      }

    public int getPosition()
      {
      return position;
      }

    public void setPosition(int position)
      {
      this.position=position;
      }

    public String getInputString()
      {
      return input_string;
      }

    public void setInputString(String input_string)
      {
      this.input_string=input_string;
      this.position=0;
      this.string_length=input_string.length();
      }


    protected char getCurrentChar()
      {
      if(position<this.string_length)
        {
        return input_string.charAt(position);
        }
      return 0;
      }

    protected char getNextChar()
        {
        position++;
        if(position<this.string_length)
          {
          return input_string.charAt(position);
          }
        return 0;
        }

    protected char lookForward()
      {
      if((position+1)<this.string_length)
        {
        return input_string.charAt(position+1);
        }
      return 0;
      }


    protected void needParseString()
      throws ScannerException
      {
      moveToToken();

      char c=lookForward();
      switch(c)
            {
            case '*':
              needTransition(true);
              break;
            case '(':
              needTransition(false);
              break;
            case '-':
              needComment();
            default:
            throw new ScannerException("Неверный символ в начале строки",getPosition());
            }
      }


    protected void needTransition(boolean is_shifting)
      throws ScannerException
      {
      String source_state_name;
      String target_state_name;
      char input_symbol;
      char output_symbol;

      ScannerException e;

      boolean is_target_state_final;

      // левая часть функции перехода

      // левая скобка

      if(!needLeftParenthesis())
        {
        throw new ScannerException("Пропущена открывающая скобка в начале функции",getPosition());
        }

      // исходное состояние
      source_state_name=needName();

      // запятая
      if(!needComma())
        {
        throw new ScannerException("Пропущена запятая в левой части функции",getPosition());
        }

      // передвигаемся к следующей лексеме
      moveToToken();

      // апостроф

      if(!needApostrophe())
        {
        throw new ScannerException("Входной символ должен быт заключён в апотрофы",getPosition());
        }

      // входной символ
      input_symbol=getNextChar();

      // апостроф

      if(!needApostrophe())
        {
        throw new ScannerException("Входной символ должен быт заключён в апотрофы",getPosition());
        }

      // правая скобка
      if(!needRightParenthesis())
        {
        throw new ScannerException("Пропущена закрывающая скобка в левой части функции",getPosition());
        }


      // символ :-
      needTransitionSymbol();

      // левая скобка
      if(!needLeftParenthesis())
        {
        throw new ScannerException("Пропущена открывающая скобка в правой части функции",getPosition());
        }

      // целевое состояние

      // если обнаружена кавычка, то это переход в конечное состояние
      // с генерацией терминала, являющегося
      moveToToken();

      if(lookForward()=='"')
        {
        getNextChar();
        is_target_state_final=true;
        target_state_name=needName();

        if(!needQuotationMark())
          {
          throw new ScannerException("Пропущена закрывающая кавычка в имени конечного состояния",getPosition());
          }
        }
      else
        {
        target_state_name=needName();

        // если запятая не обнаружена, то это "холостой переход"
        // т.е. выходной символ не генерируется

        moveToToken();
        if(this.lookForward()==',')
          {
          getNextChar();
          moveToToken();

          if(!needApostrophe())
            {
            throw new ScannerException("Выходной символ должен быть заключён в апострофы",getPosition());
            }

          output_symbol=getNextChar();

          if(!needApostrophe())
            {
            throw new ScannerException("Выходной символ должен быть заключён в апострофы",getPosition());
            }

          }
        else
          {
          output_symbol=0;
          }
        }

      // правая скобка
      if(!needRightParenthesis())
        {

        }

      // проверка на мусор

      moveToToken();
      if(getNextChar()=='-')
        {
        needComment();
        }
      else
        {
        throw new ScannerException("Пропущена закрывающая скобка в конце правила",getPosition());
        }

      // если всё в порядке начинаем строить правило...



      }


    protected void needComment()
      throws ScannerException
      {
      if(getNextChar()!='-')
        {
        throw new ScannerException("Пропущен второй знак '-' в префиксе комментария",getPosition());
        }
      }

    protected boolean needLeftParenthesis()
      {
      moveToToken();

      if(getNextChar()=='(')
        {
        return true;
        }
      return false;
      }

    protected boolean needRightParenthesis()
      {
      moveToToken();

      if(getNextChar()==')')
        {
        return true;
        }
      return false;
      }

    protected boolean needComma()
      {
      moveToToken();
      if(getNextChar()==',')
        {
        return true;
        }
      return false;
      }

    protected boolean needQuotationMark()
      {
      if(getNextChar()=='"')
        {
        return true;
        }
      return false;
      }

    protected boolean needApostrophe()
      {
      if(getNextChar()=='\'')
        {
        return true;
        }
      return false;
      }

    protected String needName()
      {
      StringBuffer buffer=new StringBuffer();
      moveToToken();

      char c;
      c=getNextChar();

      if(Character.isJavaIdentifierPart(c))
        {
        while(Character.isJavaIdentifierPart(c))
             {
             buffer.append(c);
             }
        }
      else
        {
        //throw
        }
      return buffer.toString();
      }

    protected String needString()
      {
      StringBuffer buffer=new StringBuffer();

      char c;


      c=getNextChar();

      boolean condition=true;

      while(condition)
           {
           switch(c)
                 {
                 case '\\':
                   char next_to_bkslash=getNextChar();
                   switch(next_to_bkslash)
                         {
                         case '"':
                         buffer.append('"');
                         break;
                         case '\\':
                         buffer.append('\\');
                         break;
                         default:
                         // throw
                         }
                   break;
                 case '"':
                   condition=false;
                   break;
                 default:
                   buffer.append(c);
                 }
           }
      return buffer.toString();
      }

    protected void needTransitionSymbol()
      throws ScannerException
      {
      moveToToken();

      if(getNextChar()!=':')
        {
        throw new ScannerException("Пропущен символ ':' знаке перехода ",getPosition());
        }
      if(getNextChar()!='-')
        {
        throw new ScannerException("Пропущен символ '-' знаке перехода ",getPosition());
        }
      }

    protected boolean isCharIsDelimiter(char c)
      {
      return Character.isWhitespace(c);
      }

    protected void moveToToken()
      {
      char c=lookForward();
      while(isCharIsDelimiter(c))
           {
           getNextChar();
           c=lookForward();
           }
      }

    }

  protected class ScannerException
    extends Exception
    {
    protected int error_position;

    public ScannerException(String message, int error_position)
      {
      super(message);
      this.error_position=error_position;
      }
    public int getErrorPosition()
      {
      return error_position;
      }
    }




  protected String textual_representation;
  protected AutomatonState start_state;
  protected TreeMap automaton_states;

  protected TreeMap _states;

  protected StringReader current_reader;

  protected StringBuffer buffer;

  public LexicalScanner()
    {
    }


  public void setTextualRepresentation(String textual_representation)
    {
    this.textual_representation=textual_representation;
    }

  public void buildScanner()
    {

    }

  publi

  }