Ejemplo n.º 1
0
            public void Parse()
            {
                (SourceCode.NotEmpty()).OrThrows("Null Source Code");

                // avoid re-parse
                if (state_ == State.Finished)
                {
                    return;
                }

                while (currentIdx_ < SourceCode.Length)
                {
                    var ch = SourceCode[currentIdx_];
                    switch (state_)
                    {
                    case State.Start:
                        parseStart(ch);
                        break;    // start

                    case State.InComment:
                        if (ch == '\n')
                        {
                            resetState();
                            lineCount_++;
                            currentLineIdx_ = currentIdx_ + 1;
                        }
                        break;

                    case State.InNote:
                        if (ch == '\n')
                        {
                            currentIdx_--;
                            addToken(TokenType.Note);
                            currentIdx_++;
                            resetState();
                        }
                        break;

                    case State.InInteger:
                        if (currentIdx_ != SourceCode.Count() - 1)
                        {
                            var next = SourceCode[currentIdx_ + 1];
                            if (ch == '.' && next.IsDigit())
                            {
                                state_ = State.InFloat;
                            }
                            else if (ch == 'E' || ch == 'e')
                            {
                                state_ = State.InSciNumber;
                            }
                            else if (!ch.IsDigit())
                            {
                                currentIdx_--;
                                addToken(TokenType.Integer);
                                resetState();
                            }
                        }
                        else if (ch.IsDigit())    // last char
                        {
                            addToken(TokenType.Integer);
                            resetState();
                        }
                        else     // last char is not digit
                        {
                            currentIdx_--;
                            addToken(TokenType.Integer);
                            currentIdx_++;
                            if (tryAddSingle(ch))
                            {
                                resetState();
                            }
                            else
                            {
                                addError("Illegal Ending Char[" + ch + "] Following Integer");
                            }
                        }
                        break;

                    case State.InFloat:
                        if (currentIdx_ != SourceCode.Count() - 1)
                        {
                            var next = SourceCode[currentIdx_ + 1];
                            if (next == 'E' || next == 'e')
                            {
                                state_ = State.InSciNumber;
                                currentIdx_++;
                            }
                            if (!ch.IsDigit())
                            {
                                currentIdx_--;
                                addToken(TokenType.Float);
                                resetState();
                            }
                        }
                        else if (ch.IsDigit())     // last char
                        {
                            addToken(TokenType.Float);
                            resetState();
                        }
                        else     // last char is not digit
                        {
                            currentIdx_--;
                            addToken(TokenType.Float);
                            currentIdx_++;
                            if (tryAddSingle(ch))
                            {
                                resetState();
                            }
                            else
                            {
                                addError("Illegal Ending Char[" + ch + "] Following Integer");
                            }
                        }
                        break;

                    case State.InSciNumber:
                        if (ch == '+' || ch == '-')
                        {
                            var prev = SourceCode[currentIdx_ - 1];
                            if (prev != 'E' && prev != 'e')
                            {
                                currentIdx_--;
                                addToken(TokenType.SciNumber);
                                resetState();
                                Console.WriteLine(" cur idx{0}", currentIdx_);
                            }
                        }
                        else if (!ch.IsDigit())
                        {
                            currentIdx_--;
                            addToken(TokenType.SciNumber);
                            resetState();
                        }
                        break;

                    case State.InIdentifier:
                        if (!ch.IsValidTailingIdCh())
                        {
                            currentIdx_--;
                            addToken(TokenType.Identifier);
                            resetState();
                        }

                        break;

                    case State.InString:
                    {
                        if (ch == '\"')
                        {
                            currentIdx_--;         // skip "
                            addToken(TokenType.String);
                            currentIdx_++;
                            resetState();
                            break;
                        }
                        else if (ch == '\\')
                        {
                            state_ = State.InEscapingString;
                            Console.WriteLine("escape");
                        }
                        else if (ch == '\n')
                        {
                            addError("Multi-line string");
                        }
                    }
                    break;

                    case State.InEscapingString:    // next char after
                        if (ch == '\n')
                        {
                            addError("Multi-line string");
                            resetState();
                        }
                        else
                        {
                            state_ = State.InString;
                        }

                        break;
                    } // while: foreach ch
                    currentIdx_++;
                }

                currentIdx_--;
                switch (state_)
                {
                case State.InInteger:
                    addToken(TokenType.Integer);
                    break;

                case State.InFloat:
                    addToken(TokenType.Float);
                    break;

                case State.InSciNumber:
                    addToken(TokenType.SciNumber);
                    break;

                case State.InIdentifier:
                    addToken(TokenType.Identifier);
                    break;

                case State.InString:
                case State.InEscapingString:
                    addError("Multi-Line String!");
                    break;
                }
                // ok we are done
                // mark as finished to prevent reparse
                // to re do parsing, see Reparse();
                state_ = State.Finished;
            }
Ejemplo n.º 2
0
            // start state
            private void parseStart(char ch)
            {
                if (ch.IsSkipChar())
                {
                    return;
                }
                if (tryAddSingle(ch))
                {
                    return;
                }
                switch (ch)
                {
                case '\n':
                {
                    lineCount_++;
                    tokenLeft_      = currentIdx_ + 1;
                    currentLineIdx_ = currentIdx_ + 1;
                }
                break;

                case '\"':
                    tokenLeft_ = currentIdx_ + 1;
                    state_     = State.InString;
                    break;

                case '\'':
                    if (currentIdx_ < SourceCode.Count() - 2)
                    {
                        var s1 = SourceCode[currentIdx_ + 1];
                        var s2 = SourceCode[currentIdx_ + 2];
                        if (s2 == '\'')
                        {
                            currentIdx_++;
                            addToken(1, TokenType.Char);
                            currentIdx_++;
                        }
                        else
                        {
                            addError("Cannot add Char[" + ch + "]");
                        }
                    }
                    break;

                case '+':
                    if (currentIdx_ != SourceCode.Count() - 1)
                    {
                        var next = SourceCode[currentIdx_ + 1];
                        if (next == '+')
                        {
                            currentIdx_++;
                            addToken(2, TokenType.Inc);
                        }
                        else if (next == '=')
                        {
                            currentIdx_++;
                            addToken(2, TokenType.AddAsign);
                        }
                        else
                        {
                            addToken(1, TokenType.Add);
                        }
                    }
                    else
                    {
                        addError("Illegal Ending Char[" + ch + "]");
                    }
                    break;

                case '-':
                    if (currentIdx_ != SourceCode.Count() - 1)
                    {
                        var next = SourceCode[currentIdx_ + 1];
                        if (next == '-')
                        {
                            currentIdx_++;
                            addToken(2, TokenType.Dec);
                        }
                        else if (next == '=')
                        {
                            currentIdx_++;
                            addToken(2, TokenType.SubAsign);
                        }
                        else if (next.IsDigit())
                        {
                            tokenLeft_ = currentIdx_;
                            state_     = State.InInteger;
                        }
                        else
                        {
                            addToken(1, TokenType.Sub);
                        }
                    }
                    else
                    {
                        addError("Illegal Ending Char[" + ch + "]");
                    }
                    break;

                case '*':
                    if (currentIdx_ != SourceCode.Count() - 1)
                    {
                        var next = SourceCode[currentIdx_ + 1];
                        if (next == '*')
                        {
                            currentIdx_++;
                            addToken(2, TokenType.NPow);
                        }
                        else if (next == '=')
                        {
                            currentIdx_++;
                            addToken(2, TokenType.MulAsign);
                        }
                        else
                        {
                            addToken(1, TokenType.Mul);
                        }
                    }
                    else
                    {
                        addError("Illegal Ending Char[" + ch + "]");
                    }
                    break;

                case '/':
                    if (currentIdx_ != SourceCode.Count() - 1)
                    {
                        var next = SourceCode[currentIdx_ + 1];
                        if (next == '/')
                        {
                            currentIdx_++;
                            this.state_ = State.InComment;
                        }
                        else if (next == '=')
                        {
                            currentIdx_++;
                            addToken(2, TokenType.DivAsign);
                        }
                        else
                        {
                            addToken(1, TokenType.Div);
                        }
                    }
                    else
                    {
                        addError("Illegal Ending Char[" + ch + "]");
                    }
                    break;

                case '%':
                    if (currentIdx_ != SourceCode.Count() - 1)
                    {
                        var next = SourceCode[currentIdx_ + 1];
                        if (next == '=')
                        {
                            currentIdx_++;
                            addToken(2, TokenType.ModAsign);
                        }
                        else
                        {
                            addToken(1, TokenType.Mod);
                        }
                    }
                    else
                    {
                        addError("Illegal Ending Char[" + ch + "]");
                    }
                    break;

                case '|':
                    if (currentIdx_ != SourceCode.Count() - 1)
                    {
                        var next = SourceCode[currentIdx_ + 1];
                        if (next == '=')
                        {
                            currentIdx_++;
                            addToken(2, TokenType.BitOrAsign);
                        }
                        else
                        {
                            addToken(1, TokenType.BitOr);
                        }
                    }
                    else
                    {
                        addError("Illegal Ending Char[" + ch + "]");
                    }
                    break;

                case '&':
                    if (currentIdx_ != SourceCode.Count() - 1)
                    {
                        var next = SourceCode[currentIdx_ + 1];
                        if (next == '=')
                        {
                            currentIdx_++;
                            addToken(2, TokenType.BitAndAsign);
                        }
                        else
                        {
                            addToken(1, TokenType.BitAnd);
                        }
                    }
                    else
                    {
                        addError("Illegal Ending Char[" + ch + "]");
                    }
                    break;

                case '^':
                    if (currentIdx_ != SourceCode.Count() - 1)
                    {
                        var next = SourceCode[currentIdx_ + 1];
                        if (next == '=')
                        {
                            currentIdx_++;
                            addToken(2, TokenType.BitXORAsign);
                        }
                        else
                        {
                            addToken(1, TokenType.BitXOR);
                        }
                    }
                    else
                    {
                        addError("Illegal Ending Char[" + ch + "]");
                    }
                    break;

                case '<':
                    if (currentIdx_ != SourceCode.Count() - 1)
                    {
                        var next = SourceCode[currentIdx_ + 1];
                        if (next == '=')
                        {
                            currentIdx_++;
                            addToken(2, TokenType.LE);
                        }
                        else if (next == '<')
                        {
                            currentIdx_++;
                            addToken(2, TokenType.BitSL);
                        }
                        else
                        {
                            addToken(1, TokenType.LT);
                        }
                    }
                    else
                    {
                        addError("Illegal Ending Char[" + ch + "]");
                    }
                    break;

                case '>':
                    if (currentIdx_ != SourceCode.Count() - 1)
                    {
                        var next = SourceCode[currentIdx_ + 1];
                        if (next == '=')
                        {
                            currentIdx_++;
                            addToken(2, TokenType.GE);
                        }
                        else if (next == '>')
                        {
                            currentIdx_++;
                            addToken(2, TokenType.BitSR);
                        }
                        else
                        {
                            addToken(1, TokenType.GT);
                        }
                    }
                    else
                    {
                        addError("Illegal Ending Char[" + ch + "]");
                    }
                    break;

                case '=':
                    if (currentIdx_ != SourceCode.Count() - 1)
                    {
                        var next = SourceCode[currentIdx_ + 1];
                        if (next == '=')
                        {
                            currentIdx_++;
                            addToken(2, TokenType.EQ);
                        }
                        else
                        {
                            addToken(1, TokenType.Assign);
                        }
                    }
                    else
                    {
                        addError("Illegal Ending Char[" + ch + "]");
                    }
                    break;

                case '!':
                    if (currentIdx_ != SourceCode.Count() - 1)
                    {
                        if (SourceCode[currentIdx_ + 1] == '=')
                        {
                            currentIdx_++;
                            addToken(2, TokenType.NE);
                        }
                        else
                        {
                            addToken(1, TokenType.Not);
                        }
                    }
                    else
                    {
                        addError("Illegal Ending Char[" + ch + "]");
                    }
                    break;

                case '@':
                    tokenLeft_ = currentIdx_ + 1;
                    state_     = State.InNote;
                    break;

                default:
                {
                    if (ch.IsDigit())
                    {
                        tokenLeft_ = currentIdx_;
                        state_     = State.InInteger;
                    }
                    else if (ch.IsValidLeadingIdCh())
                    {
                        tokenLeft_ = currentIdx_;
                        state_     = State.InIdentifier;
                    }
                    else
                    {
                        addError("Unknown Char[" + ch + "]");
                    }
                }
                break;
                }// switch ch
            }