예제 #1
0
        public static IExpression BuildExpression(TokenList tokens, Stack<int?> precedenceStack)
        {
            if (tokens.Current == null)
                throw new TokenParserException("The script seems to have ended prematurely. Shouldn't there be something here?", tokens.Peek(-2));

            Token token = tokens.Current;
            IExpression expr = null;
            bool endGroupedExpression = false;
            switch (token.TokenType)
            {
                case TokenType.Number:
                    expr = new NumericExpression(tokens, precedenceStack);
                    break;

                case TokenType.QuotedString:
                    expr = new StringExpression(tokens, precedenceStack);
                    break;

                case TokenType.FreeText:
                    expr = new StringExpression(tokens, precedenceStack);
                    return expr;

                case TokenType.Word:
                    if (expressionCreators.ContainsKey(token.Value))
                    {
                        // find the appropriate handler for this keyword
                        expr = expressionCreators[token.Value].Create();
                    }
                    else // we don't recognise the word, so we can assume it's a variable and validate it at run-time
                    {
                        // don't allow instruction keywords to be used as variable names
                        if (instructionCreators.ContainsKey(token.Value))
                            throw new TokenParserException("This word is the name of an instruction. You can't use it here in this context.", token);
                        else
                            expr = new VariableExpression();
                    }

                    // if applicable, have the expression prepare itself according to its own rules
                    if (expr is IFlexibleSyntaxExpression)
                        ((IFlexibleSyntaxExpression)expr).PrepareExpression(tokens, precedenceStack);
                    else // otherwise just advance to the next token
                        tokens.Advance();

                    // chain together any properties and argument lists
                    expr = BuildDeepExpression(expr, tokens);

                    break;

                case TokenType.PropertyDesignator:
                    // property designators are handled elsewhere. if we found one here, it's a parsing error.
                    if (tokens.Previous.TokenType == TokenType.Word)
                        throw new TokenParserException("This type of expression doesn't allow you to specify a property.", tokens.Next);
                    throw new TokenParserException("You've got a property designator in a spot where it doesn't belong.", tokens.Next);

                case TokenType.GroupStart:
                    expr = BuildGroupedExpression(tokens);
                    break;

                case TokenType.GroupEnd:
                    endGroupedExpression = true;
                    break;

                default:
                    throw new TokenParserException("This part of the script should equate to a value but instead I got \"" + token.Value + "\", which doesn't really mean anything in this context.", token);
            }

            if (!endGroupedExpression)
            {
                int? precedence = precedenceStack.Peek();
                while (NextHasGreaterPrecedence(precedence, tokens))
                    expr = BuildBinaryExpression(tokens, expr, precedenceStack);
            }
            return expr;
        }
예제 #2
0
        public static IExpression BuildExpression(TokenList tokens, Stack <int?> precedenceStack)
        {
            if (tokens.Current == null)
            {
                throw new TokenParserException("The script seems to have ended prematurely. Shouldn't there be something here?", tokens.Peek(-2));
            }

            Token       token = tokens.Current;
            IExpression expr  = null;
            bool        endGroupedExpression = false;

            switch (token.TokenType)
            {
            case TokenType.Number:
                expr = new NumericExpression(tokens, precedenceStack);
                break;

            case TokenType.QuotedString:
                expr = new StringExpression(tokens, precedenceStack);
                break;

            case TokenType.FreeText:
                expr = new StringExpression(tokens, precedenceStack);
                return(expr);

            case TokenType.Word:
                if (expressionCreators.ContainsKey(token.Value))
                {
                    // find the appropriate handler for this keyword
                    expr = expressionCreators[token.Value].Create();
                }
                else                         // we don't recognise the word, so we can assume it's a variable and validate it at run-time
                {
                    // don't allow instruction keywords to be used as variable names
                    if (instructionCreators.ContainsKey(token.Value))
                    {
                        throw new TokenParserException("This word is the name of an instruction. You can't use it here in this context.", token);
                    }
                    else
                    {
                        expr = new VariableExpression();
                    }
                }

                // if applicable, have the expression prepare itself according to its own rules
                if (expr is IFlexibleSyntaxExpression)
                {
                    ((IFlexibleSyntaxExpression)expr).PrepareExpression(tokens, precedenceStack);
                }
                else                         // otherwise just advance to the next token
                {
                    tokens.Advance();
                }

                // chain together any properties and argument lists
                expr = BuildDeepExpression(expr, tokens);

                break;

            case TokenType.PropertyDesignator:
                // property designators are handled elsewhere. if we found one here, it's a parsing error.
                if (tokens.Previous.TokenType == TokenType.Word)
                {
                    throw new TokenParserException("This type of expression doesn't allow you to specify a property.", tokens.Next);
                }
                throw new TokenParserException("You've got a property designator in a spot where it doesn't belong.", tokens.Next);

            case TokenType.GroupStart:
                expr = BuildGroupedExpression(tokens);
                break;

            case TokenType.GroupEnd:
                endGroupedExpression = true;
                break;

            default:
                throw new TokenParserException("This part of the script should equate to a value but instead I got \"" + token.Value + "\", which doesn't really mean anything in this context.", token);
            }

            if (!endGroupedExpression)
            {
                int?precedence = precedenceStack.Peek();
                while (NextHasGreaterPrecedence(precedence, tokens))
                {
                    expr = BuildBinaryExpression(tokens, expr, precedenceStack);
                }
            }
            return(expr);
        }