/*
 * Lexan.java
 *
 * Created on October 29, 2005, 7:56 PM
 *
 * To change this template, choose Tools | Options and locate the template under
 * the Source Creation and Management node. Right-click the template and choose
 * Open. You can then make changes to the template in the Source Editor.
 */

package cz.pcland.functions.lexan;

import cz.pcland.functions.nodes.*;
import cz.pcland.functions.syntax.*;

/**
 *
 * @author Petr Benhak
 */



public class Lexan {
    LexanInput inputReader;
    Token currentToken;

    String Functions[] = {"SIN", "COS", "TG", "LN", "LOG", "SQRT", "MODULO", "ABS"};
    
    public Lexan(String expr) {
        inputReader = new LexanInput(expr);
    }

    public boolean isFunction(String str) {
        boolean result = false;
        for(int i=0;i<Functions.length; i++){
            if(Functions[i].equalsIgnoreCase(str)){
                result = true;
            }
        }
        return result;
    }
    

    public Token getCurrentToken() {
        return currentToken;
    }
    
    public Token readToken(){
        Token result = null; //result token
        int state = 0; //current state of FSA
        int symbol; //input symbol from inputReader
        String stringValue = ""; //Value for keyWords
        //char charValue = ' '; //Value for Variables
        String intValue=""; //Value for NumberToken
        //int currentDigitPlace = 0;
        boolean done = false; //current token is not loaded
        
        while(!done){
            symbol = inputReader.read();
            //   System.out.println(inputReader.getCurrentChar());
            switch(state){
                case 0:
                    switch(symbol) {
                        case InputSymbol.INPUT_SPACE:
                            state = 0;
                            break;
                        case InputSymbol.INPUT_CHAR:
                            stringValue = String.valueOf(inputReader.getCurrentChar());
                            state = 1;
                            break;
                        case InputSymbol.INPUT_NUMBER:
                            // System.out.println("number");
                            intValue += String.valueOf(inputReader.getCurrentChar());
                            state = 2;
                            break;
                        case InputSymbol.INPUT_PLUS:
                            state = 4;
                            break;
                        case InputSymbol.INPUT_MINUS:
                            state = 5;
                            break;
                        case InputSymbol.INPUT_ASTERISK:
                            state = 6;
                            break;
                        case InputSymbol.INPUT_SLASH:
                            state = 7;
                            break;
                        case InputSymbol.INPUT_LEFT_PARENTHESIS:
                            state = 8;
                            break;
                        case InputSymbol.INPUT_RIGHT_PARENTHESIS:
                            state = 9;
                            break;
                        case InputSymbol.INPUT_POWER:
                            state = 10;
                            break;
                        case InputSymbol.INPUT_COMMA:
                            state = 11;
                            break;
                        case InputSymbol.INPUT_EQUAL:
                            state = 12;
                            break;
                        /*case INPUT_SCREAMER:
                            state = 13;
                            break;    */
                        case InputSymbol.INPUT_POINT:
                            state = 14;
                            break;
                        case InputSymbol.INPUT_UNKNOWN:
                            result = new Token(TokenType.TOKEN_UNKNOWN);
                            done = true;
                            break;
                        case InputSymbol.INPUT_END:
                            result = new Token(TokenType.TOKEN_END);
                            done = true;
                            break;
                            
                            
                        default:
                    }
                    break;
                case 1: //last input was char
                    if(symbol == InputSymbol.INPUT_CHAR){
                        state = 3;
                        stringValue += String.valueOf(inputReader.getCurrentChar());
                    }else {
                        //System.out.println("variable token creating ..." +stringValue);
                        inputReader.putCharBack();
                        result = new VariableToken(stringValue);
                        done = true;
                    }
                    break;
                    
                case 2:
                    //System.out.println("state 2");
                    if(symbol == InputSymbol.INPUT_NUMBER){
                        intValue += String.valueOf(inputReader.getCurrentChar());
                    }else {
                        inputReader.putCharBack();
                        result = new NumberToken(Integer.parseInt(intValue));
                        done = true;
                    }
                    break;
                    
                case 3:
                    if(symbol == InputSymbol.INPUT_CHAR){
                        stringValue += String.valueOf(inputReader.getCurrentChar());
                    }else {
                        inputReader.putCharBack();
                        
                        if(isFunction(stringValue))
                            result = new FunctionToken(stringValue);
                        else result = new StringToken(stringValue);
                        
                        done = true;
                    }
                    break;
                    
                case 4:
                    inputReader.putCharBack();
                    //System.out.println("plus ..." );
                    result = new Token(TokenType.TOKEN_PLUS);
                    done = true;
                    break;
                    
                case 5:
                    inputReader.putCharBack();
                    result = new Token(TokenType.TOKEN_MINUS);
                    done = true;
                    break;
                    
                case 6:
                    inputReader.putCharBack();
                    result = new Token(TokenType.TOKEN_ASTERISK);
                    done = true;
                    break;
                    
                case 7:
                    inputReader.putCharBack();
                    result = new Token(TokenType.TOKEN_SLASH);
                    done = true;
                    break;
                    
                case 8:
                    inputReader.putCharBack();
                    result = new Token(TokenType.TOKEN_CLOSE_PARENTHESIS);
                    done = true;
                    break;
                    
                case 9:
                    inputReader.putCharBack();
                    result = new Token(TokenType.TOKEN_OPEN_PARENTHESIS);
                    done = true;
                    break;
                case 10:
                    inputReader.putCharBack();
                    result = new Token(TokenType.TOKEN_POWER);
                    done = true;
                    break;
                case 11:
                    inputReader.putCharBack();
                    result = new Token(TokenType.TOKEN_COMMA);
                    done = true;
                    break;
                case 12:
                    inputReader.putCharBack();
                    result = new Token(TokenType.TOKEN_EQUAL);
                    done = true;
                    break;
                case 13:
                    inputReader.putCharBack();
                    result = new Token(TokenType.TOKEN_SCREAMER);
                    done = true;
                    break;
                case 14:
                    inputReader.putCharBack();
                    result = new Token(TokenType.TOKEN_POINT);
                    done = true;
                    break;
                default:
                    
                    
            }
        }
        // System.out.println("Vracim token: ");
        //result.print();
        currentToken = result;
        return result;
        
    }
    
    
    
}
