示例#1
0
        static public Token LexNext()
        {
            int       state       = 0;
            string    value       = string.Empty;
            int       startOffset = 0;
            ErrorKind errorKind   = ErrorKind.DEFAULT;
            char?     cQuestion;
            char      c;

            while (true)
            {
                cQuestion = SourceViewModel.NextChar();
                if (cQuestion.HasValue)
                {
                    c = cQuestion.Value;
                    switch (state)
                    {
                    case 0:
                        startOffset = SourceViewModel.GetOffset();
                        if (char.IsLetter(c) || c == '_')
                        {
                            state  = 1;
                            value += c;
                            break;
                        }

                        if (char.IsDigit(c))
                        {
                            state  = 2;
                            value += c;
                            break;
                        }

                        if (char.IsWhiteSpace(c))
                        {
                            break;
                        }

                        if (c == '>')
                        {
                            value = c.ToString();
                            return(new Token(startOffset, value, TokenKind.GT));
                        }

                        if (c == '+')
                        {
                            value = c.ToString();
                            return(new Token(startOffset, value, TokenKind.ADD));;
                        }

                        if (c == '-')
                        {
                            value = c.ToString();
                            return(new Token(startOffset, value, TokenKind.SUB));
                        }

                        if (c == '*')
                        {
                            value = c.ToString();
                            return(new Token(startOffset, value, TokenKind.MULT));
                        }

                        if (c == '/')
                        {
                            state  = 7;
                            value += c;
                            break;
                        }

                        if (c == '=')
                        {
                            value = c.ToString();
                            return(new Token(startOffset, value, TokenKind.EQU));
                        }

                        if (c == '<')
                        {
                            value = c.ToString();
                            return(new Token(startOffset, value, TokenKind.LT));
                        }

                        if (c == '{')
                        {
                            value = c.ToString();
                            return(new Token(startOffset, value, TokenKind.LBRA));
                        }

                        if (c == '}')
                        {
                            value = c.ToString();
                            return(new Token(startOffset, value, TokenKind.RBRA));
                        }

                        if (c == '(')
                        {
                            value = c.ToString();
                            return(new Token(startOffset, value, TokenKind.LPAR));
                        }

                        if (c == ')')
                        {
                            value = c.ToString();
                            return(new Token(startOffset, value, TokenKind.RPAR));
                        }

                        if (c == ';')
                        {
                            value = c.ToString();
                            return(new Token(startOffset, value, TokenKind.SEMI));
                        }

                        if (c == '.')
                        {
                            state     = 4;
                            value    += c;
                            errorKind = ErrorKind.NUMBERERROR;
                            break;
                        }

                        //ERROR
                        state     = 4;
                        value    += c;
                        errorKind = ErrorKind.INVALIDCHAR;
                        break;

                    case 1:
                        if (char.IsLetterOrDigit(c))
                        {
                            value += c;
                            break;
                        }

                        SourceViewModel.putBack();

                        if (KeyWords.ContainsKey(value))
                        {
                            return(new Token(startOffset, value, KeyWords[value]));
                        }
                        else
                        {
                            return(new Token(startOffset, value, TokenKind.ID));
                        }

                    case 2:
                        if (char.IsDigit(c))
                        {
                            value += c;
                            break;
                        }

                        if (c == '.')
                        {
                            state  = 5;
                            value += c;
                            break;
                        }

                        SourceViewModel.putBack();
                        return(new Token(startOffset, value, TokenKind.NUM));

                    case 3:
                        if (c == '*')
                        {
                            state = 9;
                        }
                        value += c;
                        break;

                    case 4:
                        switch (errorKind)
                        {
                        case ErrorKind.NUMBERERROR:
                            if (char.IsDigit(c) || c == '.')
                            {
                                value += c;
                            }
                            else
                            {
                                SourceViewModel.putBack();
                                HandleError(startOffset, value, errorKind);
                                return(new Token(startOffset, value, TokenKind.ERROR));
                            }
                            break;

                        case ErrorKind.INVALIDCHAR:
                            if (char.IsLetterOrDigit(c) || symbols.Contains(c) || char.IsWhiteSpace(c))
                            {
                                SourceViewModel.putBack();
                                HandleError(startOffset, value, errorKind);
                                return(new Token(startOffset, value, TokenKind.ERROR));
                            }
                            else
                            {
                                value += c;
                            }
                            break;

                        default:
                            if (char.IsWhiteSpace(c))
                            {
                                HandleError(startOffset, value, errorKind);
                                return(new Token(startOffset, value, TokenKind.ERROR));
                            }
                            else
                            {
                                value += c;
                            }
                            break;
                        }
                        break;

                    case 5:
                        if (char.IsDigit(c))
                        {
                            state  = 6;
                            value += c;
                            break;
                        }

                        if (c == '.')
                        {
                            state     = 4;
                            value    += c;
                            errorKind = ErrorKind.NUMBERERROR;
                            break;
                        }

                        SourceViewModel.putBack();

                        HandleError(startOffset, value, ErrorKind.NUMBERERROR);
                        return(new Token(startOffset, value, TokenKind.ERROR));

                    case 6:
                        if (char.IsDigit(c))
                        {
                            state  = 6;
                            value += c;
                            break;
                        }

                        if (c == '.')
                        {
                            state     = 4;
                            value    += c;
                            errorKind = ErrorKind.NUMBERERROR;
                            break;
                        }

                        SourceViewModel.putBack();
                        return(new Token(startOffset, value, TokenKind.NUM));

                    case 7:
                        if (c == '*')
                        {
                            value += c;
                            state  = 3;
                            break;
                        }

                        if (c == '/')
                        {
                            value += c;
                            state  = 8;
                            break;
                        }

                        SourceViewModel.putBack();
                        return(new Token(startOffset, value, TokenKind.DIV));

                    case 8:
                        if (c == '\r' || c == '\n')                               //for the case "\r\n" and "\n";
                        {
                            return(new Token(startOffset, value, TokenKind.ANNO));
                        }

                        value += c;
                        break;

                    case 9:
                        if (c == '/')
                        {
                            value += c;
                            return(new Token(startOffset, value, TokenKind.ANNO));
                        }

                        value += c;
                        state  = 3;
                        break;
                    }
                }
                else
                {
                    switch (state)
                    {
                    case 0:
                        return(new Token(SourceViewModel.GetEndOffset(), value, TokenKind.END));

                    case 1:
                        if (KeyWords.ContainsKey(value))
                        {
                            return(new Token(startOffset, value, KeyWords[value]));
                        }
                        else
                        {
                            return(new Token(startOffset, value, TokenKind.ID));
                        }

                    case 2:
                    case 6:
                        return(new Token(startOffset, value, TokenKind.NUM));

                    case 3:
                    case 9:
                        HandleError(startOffset, value, ErrorKind.ANNONOTCLOSED);
                        return(new Token(startOffset, value, TokenKind.ERROR));

                    case 4:
                        HandleError(startOffset, value, errorKind);
                        return(new Token(startOffset, value, TokenKind.ERROR));

                    case 5:
                        HandleError(startOffset, value, ErrorKind.NUMBERERROR);
                        return(new Token(startOffset, value, TokenKind.ERROR));

                    case 7:
                        return(new Token(startOffset, value, TokenKind.DIV));

                    case 8:
                        return(new Token(startOffset, value, TokenKind.ANNO));
                    }
                }
            }
        }