using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.IO;

public struct SemanticInfo
{
    public int tokenId;
    public string tokenVal;
}

namespace analex
{
    class Analex
    {
        #region class fields, const, and enums

        /// <summary>
        /// ids of tokens obtained form the analizys
        /// </summary>
 
        /// <summary>
        /// used to determine where to go in th state machine.
        /// </summary>
        enum CharClass
        {
            Letter = 0,
            Digit,
            Dot,
            Slash,      // /
            Star,       // *
            BackSlash,  // \
            Add,
            Not,
            Comma,
            Colon,
            Equals,
            Less,       // <
            Greater,    // >
            RBracketL,  // (
            RBracketR,  // )
            SBracketL,  // [
            SBracketR,  // ]
            CBracketL,  // {
            CBracketR,  // }
            Underline,
            Semicolon,
            Quotation,  // "
            Others,
            Eof
        };
        private const int NumCharClasses = 24;

        /// <summary>
        /// state machine
        /// </summary>
        enum State
        {
            // nonterminal states:
            s0 = 0, // start pos
            s1,     
            s2,
            s3,
            s4,
            s5,
            s6,
            s7,
            s8,
            s9,
            s10,
            s11,
            s12,
            s13,    // for sId state

            sErr,
            sErrUnexpected,
            sErrEndOfFile,

            // terminal states:
            sId,
            sL1,    // left round bracket
            sL2,    // left square bracket
            sR1,    // right round bracket
            sR2,    // right square bracket
            sL3,    // curly bracket left {
            sR3,    // curly bracket right ]
            sStr,   // string found
            sComment,// comment
            sDot22,  // ".." - must return twice to read ".." as a token...
            sInt,   // integer, return once
            sSci,   // scientific ??
            sDot2,  // ".." - as a token
            sDot,   // "." - must return once
            sNot,
            sAdd,
            sMul,   // *
            sMul2,  // /
            sComma,
            sRel1,  // relation like "<"... - must return once
            sRel2,  // relation like "<="
            sXml,   // "</"
            sSet,   // "="
            sSemicolon
        };

        private const int NumNonterminalStates = 14;

        private String fileName;
        State[,] machineGraph;
        ArrayList nonterminalStates;
        ArrayList sourceLines;
        State currentState;
        CharClass currentCharClass;
        String currentLine;
        char currentChar;
        int lineNum;
        int headPos;
        int headStart;
        StringBuilder buffer;

        #endregion

        #region public mathods, interface

        public Analex()
        {
            nonterminalStates = new ArrayList(NumNonterminalStates);
            nonterminalStates.Add(State.s0);
            nonterminalStates.Add(State.s1);
            nonterminalStates.Add(State.s2);
            nonterminalStates.Add(State.s3);
            nonterminalStates.Add(State.s4);
            nonterminalStates.Add(State.s5);
            nonterminalStates.Add(State.s6);
            nonterminalStates.Add(State.s7);
            nonterminalStates.Add(State.s8);
            nonterminalStates.Add(State.s9);
            nonterminalStates.Add(State.s10);
            nonterminalStates.Add(State.s11);
            nonterminalStates.Add(State.s12);
            nonterminalStates.Add(State.s13);

            BuildMachineGraph();
        }

        public bool Init(String fname)
        {
            fileName = fname;

            currentState = State.s0;
            currentCharClass = CharClass.Others;

            sourceLines = new ArrayList();

            try
            {
                FileStream file = new FileStream(fname, FileMode.Open, FileAccess.Read);
                StreamReader reader = new StreamReader(file);

                // read all lines to the memory buffer, maybe it needs optimization?
                while (!reader.EndOfStream)
                {
                    sourceLines.Add(reader.ReadLine() + "\n");
                }
                if (sourceLines.Count == 0) throw new Exception("file is empty!");

                lineNum = 1;
                currentLine = sourceLines[0].ToString();
                headPos = 0;

                System.Console.WriteLine("File contains {0} lines of code... starting analizyng...", sourceLines.Count);
                reader.Close();
                file.Close();
            }
            catch (IOException e)
            {
                System.Console.WriteLine("\nIOException: " + e.Message);
                return false;
            }
            catch (Exception e)
            {
                System.Console.WriteLine("\nException: " + e.Message);
                return false;
            }

            buffer = new StringBuilder(0, 128);

            return true;
        }

        public SemanticInfo Analize(int line)
        {
            line = lineNum;
                currentState = State.s0;
                currentCharClass = CharClass.Others;
                currentChar = ' ';

                buffer.Remove(0, buffer.Length);

                while ((currentChar == ' ' || currentChar == '\n' || currentChar == '\t') && currentCharClass == CharClass.Others && !EndOfFile())
                {
                    currentCharClass = NextChar();
                }

                if (EndOfFile())
                {
                    SemanticInfo se = new SemanticInfo();
                    se.tokenId = (int)Tokens.EOF;
                    return se;
                }

                currentState = machineGraph[(int)currentState, (int)currentCharClass];

                while (nonterminalStates.Contains(currentState))
                {
                    buffer.Append(currentChar);
                    currentCharClass = NextChar();
                    currentState = machineGraph[(int)currentState, (int)currentCharClass];
                }

                headStart = headPos - buffer.Length;
                return ProcessTerminalState(buffer.ToString());
        }

        #endregion

        #region private methods

        /// <summary>
        /// simple way to show the result of the analizys, must be reimplemented
        /// </summary>
        /// <param name="id">token obtained</param>
        /// <param name="buf">semantic data for the token</param>

        private SemanticInfo AddToken(Tokens id, String buf)
        {
            SemanticInfo ret;
            ret.tokenId = (int)id;
            ret.tokenVal = (string)buf;
         //   Console.WriteLine( "Token recognised: (" + id.ToString() + " , " + buf + ")" );
            return ret;
        }

        /// <summary>
        /// prints out the error message, shows line and row where the error occured
        /// </summary>
        /// <param name="err">message for the user</param>
        private void ReportError(String err)
        {
            System.Console.WriteLine("Error!! " + lineNum + ","+headStart + ": " + err);
        }

        private SemanticInfo ProcessTerminalState(String buffer)
        {
            String last = currentChar.ToString();

            switch (currentState)
            {
                case State.sAdd: return AddToken(Tokens.qAdd, last);
                case State.sComma: return AddToken(Tokens.qComma, buffer+last);
                case State.sComment: return AddToken(Tokens.qComment, buffer + last);
                case State.sDot: MoveBack();  return AddToken(Tokens.qDot, buffer);
                case State.sDot2: return AddToken(Tokens.qDot2, buffer + last);
                case State.sSemicolon: return AddToken(Tokens.qSemicolon, buffer+last);
                case State.sDot22:
                    {
                        MoveBack(); 
                        MoveBack();
                        buffer = buffer.Remove(buffer.Length - 1);
                        return AddToken(Tokens.qValInt, buffer);
                    }
                case State.sId:
                    {
                        MoveBack();
                        buffer = buffer.ToLower();
                        switch (buffer)
                        {
                            case "for": return AddToken(Tokens.qFor, buffer);
                            case "to":
                            case "downto": return AddToken(Tokens.qFor2, buffer);
                            case "do": return AddToken(Tokens.qDo, buffer);
                            case "if": return AddToken(Tokens.qIf, buffer);
                            case "then": return AddToken(Tokens.qThen, buffer);
                            case "else": return AddToken(Tokens.qElse, buffer);
                            case "return": return AddToken(Tokens.qRet, buffer);
                            case "action": return AddToken(Tokens.qKeyAction, buffer);
                            case "function": return AddToken(Tokens.qKeyFunction, buffer);
                            case "var": return AddToken(Tokens.qKeyVar, buffer);
                            case "const": return AddToken(Tokens.qKeyConst, buffer);
                            case "main": return AddToken(Tokens.qKeyMain, buffer);
                            case "extern": return AddToken(Tokens.qKeyExtern, buffer);
                            case "inparams": return AddToken(Tokens.qKeyParam, buffer);
                            case "codename": return AddToken(Tokens.qKeyCode, buffer);
                            case "int": return AddToken(Tokens.qInt, buffer);
                            case "char": return AddToken(Tokens.qChar, buffer);
                            case "bool": return AddToken(Tokens.qBool, buffer);
                            case "real": return AddToken(Tokens.qReal, buffer);
                            case "string": return AddToken(Tokens.qString, buffer);
                            case "void": return AddToken(Tokens.qVoid, buffer);
                            case "and":
                            case "mod":
                            case "div": return AddToken(Tokens.qMul, buffer);
                            case "or": return AddToken(Tokens.qOr, buffer);
                            case "true":
                            case "false": return AddToken(Tokens.qLogical, buffer);
                            default: return AddToken(Tokens.qIdentifier, buffer);
                        }
                    }
                case State.sInt: MoveBack(); return AddToken(Tokens.qValInt, buffer);
                case State.sL1: return AddToken(Tokens.qLeft1, buffer+last);
                case State.sL2: return AddToken(Tokens.qLeft2, buffer+last);
                case State.sL3: return AddToken(Tokens.qLeft5, buffer + last);
                case State.sR1: return AddToken(Tokens.qRight1, buffer+last);
                case State.sR2: return AddToken(Tokens.qRight2, buffer+last);
                case State.sR3: return AddToken(Tokens.qRight5, buffer + last);
                case State.sMul: return AddToken(Tokens.qMul, buffer + last);
                case State.sMul2: MoveBack(); return AddToken(Tokens.qMul, buffer);
                case State.sNot: return AddToken(Tokens.qNot, buffer + last);
                case State.sRel1: return AddToken(Tokens.qRel, buffer + last);
                case State.sRel2: MoveBack(); return AddToken(Tokens.qRel, buffer);
                case State.sSci: MoveBack(); return AddToken(Tokens.qValReal, buffer);
                case State.sSet: MoveBack(); return AddToken(Tokens.qSet, buffer);
                case State.sStr: return AddToken(Tokens.qValString, buffer + last);
                case State.sXml: return AddToken(Tokens.qXml, buffer + last);
              //  case State.sErr: ReportError(buffer); break;
              //  case State.sErrUnexpected: ReportError("Unexpected \"" + buffer + last + "\", such construction does not exist!"); break;
             // case State.sErrEndOfFile: ReportError("Unexpected end of file!"); break;
                default:
                    {
                        ReportError("symbol not recognised!! -> " + last);
                        return AddToken(Tokens.qERROR, buffer);
                    }
            }
        }

        private bool EndOfFile()
        {
            if (headPos >= currentLine.Length && lineNum >= sourceLines.Count)
                return true;

            return false;
        }

        private void MoveBack()
        {
            --headPos;

            if (headPos < 0)
            {
                --lineNum;
                currentLine = sourceLines[lineNum - 1].ToString();
                headPos = currentLine.Length - 1;
            }
        }

        private CharClass NextChar()
        {
            if (!EndOfFile())
            {
                if (headPos >= currentLine.Length)
                {
                    headPos = 0;
                    currentLine = sourceLines[lineNum++].ToString();
                }
            }
            else 
                return CharClass.Eof;

            currentChar = currentLine[headPos++];

            if (Char.IsDigit(currentChar)) return CharClass.Digit;
            else if (Char.IsLetter(currentChar)) return CharClass.Letter;
            else
            {
                switch (currentChar)
                {
                    case '+': return CharClass.Add;
                    case '-': return CharClass.Add;
                    case '\\': return CharClass.BackSlash;
                    case ':': return CharClass.Colon;
                    case ',': return CharClass.Comma;
                    case '.': return CharClass.Dot;
                    //case ' ': return CharClass.Eof;
                    case '=': return CharClass.Equals;
                    case '>': return CharClass.Greater;
                    case '<': return CharClass.Less;
                    case '!': return CharClass.Not;
                    case '\"': return CharClass.Quotation;
                    case '(': return CharClass.RBracketL;
                    case ')': return CharClass.RBracketR;
                    case '[': return CharClass.SBracketL;
                    case ']': return CharClass.SBracketR;
                    case '{': return CharClass.CBracketL;
                    case '}': return CharClass.CBracketR;
                    case ';': return CharClass.Semicolon;
                    case '/': return CharClass.Slash;
                    case '*': return CharClass.Star;
                    case '_': return CharClass.Underline;
                    default: return CharClass.Others;
                }
            }
        }

        private void BuildMachineGraph()
        {
            machineGraph = new State[NumNonterminalStates, NumCharClasses];

            machineGraph[(int)State.s0, (int)CharClass.Add]          = State.sAdd;
            machineGraph[(int)State.s0, (int)CharClass.BackSlash]    = State.sErrUnexpected;
            machineGraph[(int)State.s0, (int)CharClass.Colon]        = State.sErrUnexpected;  // unexpected!
            machineGraph[(int)State.s0, (int)CharClass.Comma]        = State.sComma;
            machineGraph[(int)State.s0, (int)CharClass.Digit]        = State.s5;
            machineGraph[(int)State.s0, (int)CharClass.Dot]          = State.s4;
            machineGraph[(int)State.s0, (int)CharClass.Eof]          = State.sErr;  // end of analizis?
            machineGraph[(int)State.s0, (int)CharClass.Equals]       = State.s1;
            machineGraph[(int)State.s0, (int)CharClass.Greater]      = State.s2;
            machineGraph[(int)State.s0, (int)CharClass.Less]         = State.s3;
            machineGraph[(int)State.s0, (int)CharClass.Letter]       = State.s13;
            machineGraph[(int)State.s0, (int)CharClass.Not]          = State.sNot;
            machineGraph[(int)State.s0, (int)CharClass.Others]       = State.sErrUnexpected;  // unexpected character?
            machineGraph[(int)State.s0, (int)CharClass.RBracketL]    = State.sL1;
            machineGraph[(int)State.s0, (int)CharClass.SBracketL]    = State.sL2;
            machineGraph[(int)State.s0, (int)CharClass.CBracketL]    = State.sL3;
            machineGraph[(int)State.s0, (int)CharClass.RBracketR]    = State.sR1;
            machineGraph[(int)State.s0, (int)CharClass.SBracketR]    = State.sR2;
            machineGraph[(int)State.s0, (int)CharClass.CBracketR]    = State.sR3;
            machineGraph[(int)State.s0, (int)CharClass.Semicolon]    = State.sSemicolon;
            machineGraph[(int)State.s0, (int)CharClass.Slash]        = State.s11;
            machineGraph[(int)State.s0, (int)CharClass.Quotation]    = State.s12;
            machineGraph[(int)State.s0, (int)CharClass.Star]         = State.sMul;
            machineGraph[(int)State.s0, (int)CharClass.Underline]    = State.s13;

            machineGraph[(int)State.s1, (int)CharClass.Add] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.BackSlash] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.Colon] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.Comma] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.Digit] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.Dot] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.Eof] = State.sErr;
            machineGraph[(int)State.s1, (int)CharClass.Equals] = State.sRel1;
            machineGraph[(int)State.s1, (int)CharClass.Greater] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.Less] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.Letter] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.Not] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.Others] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.RBracketL] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.SBracketL] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.RBracketR] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.SBracketR] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.CBracketL] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.CBracketR] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.Semicolon] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.Slash] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.Quotation] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.Star] = State.sSet;
            machineGraph[(int)State.s1, (int)CharClass.Underline] = State.sSet;

            machineGraph[(int)State.s2, (int)CharClass.Add] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.BackSlash] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.Colon] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.Comma] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.Digit] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.Dot] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.Eof] = State.sErr;
            machineGraph[(int)State.s2, (int)CharClass.Equals] = State.sRel1;
            machineGraph[(int)State.s2, (int)CharClass.Greater] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.Less] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.Letter] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.Not] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.Others] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.RBracketL] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.SBracketL] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.RBracketR] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.SBracketR] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.Semicolon] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.CBracketL] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.CBracketR] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.Slash] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.Quotation] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.Star] = State.sRel2;
            machineGraph[(int)State.s2, (int)CharClass.Underline] = State.sRel2;

            machineGraph[(int)State.s3, (int)CharClass.Add] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.BackSlash] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.Colon] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.Comma] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.Digit] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.Dot] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.Eof] = State.sErr;
            machineGraph[(int)State.s3, (int)CharClass.Equals] = State.sRel1;
            machineGraph[(int)State.s3, (int)CharClass.Greater] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.Less] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.Letter] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.Not] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.Others] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.RBracketL] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.SBracketL] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.RBracketR] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.SBracketR] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.Semicolon] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.CBracketL] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.CBracketR] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.Slash] = State.sXml;
            machineGraph[(int)State.s3, (int)CharClass.Quotation] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.Star] = State.sRel2;
            machineGraph[(int)State.s3, (int)CharClass.Underline] = State.sRel2;

            machineGraph[(int)State.s4, (int)CharClass.Add] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.BackSlash] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.Colon] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.Comma] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.Digit] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.Dot] = State.sDot2;
            machineGraph[(int)State.s4, (int)CharClass.Eof] = State.sErr;
            machineGraph[(int)State.s4, (int)CharClass.Equals] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.Greater] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.Less] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.Letter] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.Not] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.Others] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.RBracketL] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.SBracketL] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.RBracketR] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.SBracketR] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.CBracketL] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.CBracketR] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.Semicolon] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.Slash] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.Quotation] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.Star] = State.sDot;
            machineGraph[(int)State.s4, (int)CharClass.Underline] = State.sDot;

            machineGraph[(int)State.s5, (int)CharClass.Add] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.BackSlash] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.Colon] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.Comma] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.Digit] = State.s5;
            machineGraph[(int)State.s5, (int)CharClass.Dot] = State.s6;
            machineGraph[(int)State.s5, (int)CharClass.Eof] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.Equals] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.Greater] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.Less] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.Letter] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.Not] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.Others] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.RBracketL] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.SBracketL] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.RBracketR] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.SBracketR] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.CBracketL] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.CBracketR] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.Semicolon] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.Slash] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.Quotation] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.Star] = State.sInt;
            machineGraph[(int)State.s5, (int)CharClass.Underline] = State.sInt;

            machineGraph[(int)State.s6, (int)CharClass.Add] = State.sErr;       // bad number syntax
            machineGraph[(int)State.s6, (int)CharClass.BackSlash] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.Colon] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.Comma] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.Digit] = State.s7;
            machineGraph[(int)State.s6, (int)CharClass.Dot] = State.sDot22;
            machineGraph[(int)State.s6, (int)CharClass.Eof] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.Equals] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.Greater] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.Less] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.Letter] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.Not] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.Others] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.RBracketL] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.SBracketL] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.RBracketR] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.SBracketR] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.CBracketL] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.CBracketR] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.Semicolon] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.Slash] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.Quotation] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.Star] = State.sErr;
            machineGraph[(int)State.s6, (int)CharClass.Underline] = State.sErr;

            machineGraph[(int)State.s7, (int)CharClass.Add] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.BackSlash] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.Colon] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.Comma] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.Digit] = State.s7;
            machineGraph[(int)State.s7, (int)CharClass.Dot] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.Eof] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.Equals] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.Greater] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.Less] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.Letter] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.Not] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.Others] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.RBracketL] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.SBracketL] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.RBracketR] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.SBracketR] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.CBracketL] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.CBracketR] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.Semicolon] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.Slash] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.Quotation] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.Star] = State.sSci;
            machineGraph[(int)State.s7, (int)CharClass.Underline] = State.sSci;

            machineGraph[(int)State.s8, (int)CharClass.Add] = State.s9;       // comment not ended!
            machineGraph[(int)State.s8, (int)CharClass.BackSlash] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.Colon] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.Comma] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.Digit] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.Dot] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.Eof] = State.sErrEndOfFile;
            machineGraph[(int)State.s8, (int)CharClass.Equals] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.Greater] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.Less] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.Letter] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.Not] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.Others] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.RBracketL] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.SBracketL] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.RBracketR] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.SBracketR] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.CBracketL] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.CBracketR] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.Semicolon] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.Slash] = State.sComment;
            machineGraph[(int)State.s8, (int)CharClass.Quotation] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.Star] = State.s9;
            machineGraph[(int)State.s8, (int)CharClass.Underline] = State.s9;

            machineGraph[(int)State.s9, (int)CharClass.Add] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.BackSlash] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.Colon] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.Comma] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.Digit] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.Dot] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.Eof] = State.sErrEndOfFile;
            machineGraph[(int)State.s9, (int)CharClass.Equals] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.Greater] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.Less] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.Letter] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.Not] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.Others] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.RBracketL] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.SBracketL] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.RBracketR] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.SBracketR] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.CBracketL] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.CBracketR] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.Semicolon] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.Slash] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.Quotation] = State.s9;
            machineGraph[(int)State.s9, (int)CharClass.Star] = State.s8;
            machineGraph[(int)State.s9, (int)CharClass.Underline] = State.s9;

            machineGraph[(int)State.s10, (int)CharClass.Add] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.BackSlash] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.Colon] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.Comma] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.Digit] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.Dot] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.Eof] = State.sErr;
            machineGraph[(int)State.s10, (int)CharClass.Equals] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.Greater] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.Less] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.Letter] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.Not] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.Others] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.RBracketL] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.SBracketL] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.RBracketR] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.SBracketR] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.CBracketL] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.CBracketR] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.Semicolon] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.Slash] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.Quotation] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.Star] = State.s9;
            machineGraph[(int)State.s10, (int)CharClass.Underline] = State.s9;

            machineGraph[(int)State.s11, (int)CharClass.Add] = State.sErrUnexpected;           // replace for s9?
            machineGraph[(int)State.s11, (int)CharClass.BackSlash] = State.sErrUnexpected;
            machineGraph[(int)State.s11, (int)CharClass.Colon] = State.sErrUnexpected;
            machineGraph[(int)State.s11, (int)CharClass.Comma] = State.sErrUnexpected;
            machineGraph[(int)State.s11, (int)CharClass.Digit] = State.sMul2;
            machineGraph[(int)State.s11, (int)CharClass.Dot] = State.sErrUnexpected;
            machineGraph[(int)State.s11, (int)CharClass.Eof] = State.sErr;
            machineGraph[(int)State.s11, (int)CharClass.Equals] = State.sErrUnexpected;
            machineGraph[(int)State.s11, (int)CharClass.Greater] = State.sErrUnexpected;
            machineGraph[(int)State.s11, (int)CharClass.Less] = State.sErrUnexpected;
            machineGraph[(int)State.s11, (int)CharClass.Letter] = State.sMul2;
            machineGraph[(int)State.s11, (int)CharClass.Not] = State.sErrUnexpected;
            machineGraph[(int)State.s11, (int)CharClass.Others] = State.sMul2;
            machineGraph[(int)State.s11, (int)CharClass.RBracketL] = State.sMul2;
            machineGraph[(int)State.s11, (int)CharClass.SBracketL] = State.sErrUnexpected;
            machineGraph[(int)State.s11, (int)CharClass.RBracketR] = State.sErrUnexpected;
            machineGraph[(int)State.s11, (int)CharClass.SBracketR] = State.sErrUnexpected;
            machineGraph[(int)State.s11, (int)CharClass.CBracketL] = State.sErrUnexpected;
            machineGraph[(int)State.s11, (int)CharClass.CBracketR] = State.sErrUnexpected;
            machineGraph[(int)State.s11, (int)CharClass.Semicolon] = State.sErrUnexpected;
            machineGraph[(int)State.s11, (int)CharClass.Slash] = State.sErrUnexpected;
            machineGraph[(int)State.s11, (int)CharClass.Quotation] = State.sErrUnexpected;
            machineGraph[(int)State.s11, (int)CharClass.Star] = State.s10;
            machineGraph[(int)State.s11, (int)CharClass.Underline] = State.sMul2;

            machineGraph[(int)State.s12, (int)CharClass.Add] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.BackSlash] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.Colon] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.Comma] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.Digit] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.Dot] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.Eof] = State.sErrEndOfFile;
            machineGraph[(int)State.s12, (int)CharClass.Equals] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.Greater] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.Less] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.Letter] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.Not] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.Others] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.RBracketL] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.SBracketL] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.RBracketR] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.SBracketR] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.CBracketL] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.CBracketR] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.Semicolon] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.Slash] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.Quotation] = State.sStr;
            machineGraph[(int)State.s12, (int)CharClass.Star] = State.s12;
            machineGraph[(int)State.s12, (int)CharClass.Underline] = State.s12;

            machineGraph[(int)State.s13, (int)CharClass.Add] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.BackSlash] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.Colon] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.Comma] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.Digit] = State.s13;
            machineGraph[(int)State.s13, (int)CharClass.Dot] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.Eof] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.Equals] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.Greater] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.Less] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.Letter] = State.s13;
            machineGraph[(int)State.s13, (int)CharClass.Not] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.Others] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.RBracketL] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.SBracketL] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.RBracketR] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.SBracketR] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.CBracketL] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.CBracketR] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.Semicolon] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.Slash] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.Quotation] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.Star] = State.sId;
            machineGraph[(int)State.s13, (int)CharClass.Underline] = State.s13;
        }

        #endregion
    }
}
