// This is a very simple parser, that only verifies if the input is correct.
        //
        public bool ParseExpression(string input)
        {
            var tokenStream = _tokenizer.CreateTokenStream(input);

            if (tokenStream.Peek().TokenType != EExpressionTokenType.Digit &&
                tokenStream.Peek().TokenType != EExpressionTokenType.ParenthesesOpen &&
                tokenStream.Peek().TokenType != EExpressionTokenType.End)
            {
                throw new ParseException(EExceptionReason.StartExpressionError, tokenStream.Peek().StartIndex);
            }

            int parenthesesCounter = 0;

            while (tokenStream.IsFinshed == false)
            {
                var token = tokenStream.Next();
                switch (token.TokenType)
                {
                case EExpressionTokenType.ParenthesesOpen:     // next token must be a digit or another paranthesis open
                    parenthesesCounter++;
                    {
                        var peeked = tokenStream.Peek();
                        if (peeked.TokenType != EExpressionTokenType.Digit && peeked.TokenType != EExpressionTokenType.ParenthesesOpen)
                        {
                            throw new ParseException(EExceptionReason.StartExpressionError, token.Data, token.StartIndex);
                        }
                    }

                    break;

                case EExpressionTokenType.ParenthesesClose:     // next token must be an operator or end or paranthesis close
                    parenthesesCounter--;
                    if (parenthesesCounter < 0)
                    {
                        throw new ParseException(EExceptionReason.UnmatchedError, token.Data, token.StartIndex);     // unmatched )
                    }
                    {
                        var peeked = tokenStream.Peek();
                        if (peeked.TokenType != EExpressionTokenType.Div && peeked.TokenType != EExpressionTokenType.Mult &&
                            peeked.TokenType != EExpressionTokenType.Add && peeked.TokenType != EExpressionTokenType.Sub &&
                            peeked.TokenType != EExpressionTokenType.End && peeked.TokenType != EExpressionTokenType.ParenthesesClose)
                        {
                            throw new InvalidTokenException(peeked.Data, token.StartIndex, token.Data);
                        }
                    }
                    break;

                case EExpressionTokenType.Digit:     // next token must be parantheses close or an operation or end
                {
                    var peeked = tokenStream.Peek();

                    if (peeked.TokenType != EExpressionTokenType.Add &&
                        peeked.TokenType != EExpressionTokenType.Sub &&
                        peeked.TokenType != EExpressionTokenType.Mult &&
                        peeked.TokenType != EExpressionTokenType.Div &&
                        peeked.TokenType != EExpressionTokenType.ParenthesesClose &&
                        peeked.TokenType != EExpressionTokenType.End)
                    {
                        throw new InvalidTokenException(peeked.Data, token.StartIndex, token.Data);
                    }
                }
                break;

                case EExpressionTokenType.Add:     // next token must be parantheses or digit
                case EExpressionTokenType.Sub:
                case EExpressionTokenType.Mult:
                case EExpressionTokenType.Div:
                {
                    var peeked = tokenStream.Peek();
                    if (
                        peeked.TokenType != EExpressionTokenType.ParenthesesOpen &&
                        peeked.TokenType != EExpressionTokenType.Digit)
                    {
                        throw new ParseException(EExceptionReason.UnmatchedError, token.Data, token.StartIndex);
                    }
                }
                break;
                }
            }

            if (parenthesesCounter != 0)
            {
                throw new ParseException(EExceptionReason.UnmatchedError, "(", input.Length); // unclosed parantheses
            }

            return(true);
        }
Esempio n. 2
0
        // This is a very simple parser, that only verifies if the input is correct.
        //
        public bool ParseExpression(string input)
        {
            var tokenStream = _tokenizer.CreateTokenStream(input);

            if (tokenStream.Peek().TokenType != EExpressionTokenType.Digit &&
                tokenStream.Peek().TokenType != EExpressionTokenType.ParenthesesOpen &&
                tokenStream.Peek().TokenType != EExpressionTokenType.End)
            {
                var peeked = tokenStream.Peek();
                throw new ParseException(String.Format("Parser error at position {0}: An expression must start with a digit or \"(\"", peeked.StartIndex + 1)); // unmatched )
            }

            while (tokenStream.IsFinshed == false)
            {
                var token = tokenStream.Next();
                switch (token.TokenType)
                {
                case EExpressionTokenType.ParenthesesOpen:     // next token must be a digit or another paranthesis open
                    _parenthesesCounter++;
                    {
                        var peeked = tokenStream.Peek();
                        if (peeked.TokenType != EExpressionTokenType.Digit && peeked.TokenType != EExpressionTokenType.ParenthesesOpen)
                        {
                            throw new Exception();
                        }
                    }

                    break;

                case EExpressionTokenType.ParenthesesClose:     // next token must be an operator or end or paranthesis close
                    _parenthesesCounter--;
                    if (_parenthesesCounter < 0)
                    {
                        int countClosingParethesis    = input.Count(f => f == ')');
                        int countOpeneninggParethesis = input.Count(f => f == '(');
                        if (countClosingParethesis != countOpeneninggParethesis)
                        {
                            int    i      = 1;
                            var    peeked = tokenStream.Peek();
                            string s      = input[peeked.StartIndex - i].ToString();
                            while (s.Equals(" "))
                            {
                                s = input[peeked.StartIndex - ++i].ToString();
                            }
                            throw new ParseException(String.Format("Parser error at position {0}: unmatched \")\" in expression", peeked.StartIndex - 1));     // unmatched )
                        }
                        //int i = 1;
                        //var peeked = tokenStream.Peek();
                        //string s = input[peeked.StartIndex - i].ToString();
                        //while (s.Equals(" "))
                        //{
                        //    s = input[peeked.StartIndex - ++i].ToString();
                        //}
                        //throw new ParseException(String.Format("Unexpected input after \"{0}\" at position {1}: expected \")\",\"+\",\"-\",\"*\",\"\\\" or end of expression but found \"(\". ", s, peeked.StartIndex));
                    }
                    {
                        var peeked = tokenStream.Peek();
                        if (peeked.TokenType != EExpressionTokenType.Div && peeked.TokenType != EExpressionTokenType.Mult &&
                            peeked.TokenType != EExpressionTokenType.Add && peeked.TokenType != EExpressionTokenType.Sub &&
                            peeked.TokenType != EExpressionTokenType.End && peeked.TokenType != EExpressionTokenType.ParenthesesClose)
                        {
                            peeked = tokenStream.Peek();
                            throw new ParseException(String.Format("Parser error at position {0}: unmatched \")\" in expression", peeked.StartIndex));     // unmatched )
                        }
                    }
                    break;

                case EExpressionTokenType.Digit:     // next token must be parantheses close or an operation or end
                {
                    var peeked = tokenStream.Peek();

                    if (peeked.TokenType != EExpressionTokenType.Add &&
                        peeked.TokenType != EExpressionTokenType.Sub &&
                        peeked.TokenType != EExpressionTokenType.Mult &&
                        peeked.TokenType != EExpressionTokenType.Div &&
                        peeked.TokenType != EExpressionTokenType.ParenthesesClose &&
                        peeked.TokenType != EExpressionTokenType.End)
                    {
                        int    i = 1;
                        string s = input[peeked.StartIndex - i].ToString();
                        while (s.Equals(" "))
                        {
                            s = input[peeked.StartIndex - ++i].ToString();
                        }
                        throw new ParseException(String.Format("Unexpected input after \"{0}\" at position {1}: expected \")\",\"+\",\"-\",\"*\",\"\\\" or end of expression but found \"(\". ", s, peeked.StartIndex));
                    }
                }
                break;

                case EExpressionTokenType.Add:     // next token must be parantheses or digit
                case EExpressionTokenType.Sub:
                case EExpressionTokenType.Mult:
                case EExpressionTokenType.Div:
                {
                    var peeked = tokenStream.Peek();
                    if (
                        peeked.TokenType != EExpressionTokenType.ParenthesesOpen &&
                        peeked.TokenType != EExpressionTokenType.Digit)
                    {
                        throw new Exception();
                    }
                }
                break;
                }
            }

            if (_parenthesesCounter != 0)
            {
                int countClosingParethesis    = input.Count(f => f == ')');
                int countOpeneninggParethesis = input.Count(f => f == '(');
                if (countClosingParethesis != countOpeneninggParethesis)
                {
                    throw new ParseException(String.Format("Parser error at position {0}: unmatched \"(\" in expression", input.Length)); // unclosed parantheses
                }
            }

            return(true);
        }