예제 #1
0
        public override Production Parse(List <Token> tokens)
        {
            var firstParen = tokens.First();

            if (firstParen.TokenClass != TokenClass.StartScope)
            {
                return(new Production(null, tokens));
            }
            var current   = new ScopeExpression().Parse(tokens);
            var remaining = current.RemainingTokens.ToList();

            while (remaining.Any() && remaining.FirstOrDefault() != null && remaining[0].TokenClass != TokenClass.EndScope)
            {
                Expression parsed;
                switch (remaining.First().TokenClass)
                {
                case TokenClass.ReplacementSymbol:
                    current = new OperationExpression().Parse(remaining);
                    if (current.Expression != null)
                    {
                        break;
                    }
                    if (Constituents.Count > 0)
                    {
                        return(new Production(null, tokens));                            //cannot have multiple value types in a row
                    }
                    current = new ReplacementSymbolExpression().Parse(remaining);
                    break;

                case TokenClass.Integer:
                case TokenClass.Float:
                    current = new OperationExpression().Parse(remaining);
                    if (current.Expression != null)
                    {
                        break;
                    }
                    if (Constituents.Count > 0)
                    {
                        return(new Production(null, tokens));
                    }
                    current = NumericExpression.TryParseNumeric(remaining);
                    break;

                case TokenClass.String:
                    current = new OperationExpression().Parse(remaining);
                    if (current.Expression != null)
                    {
                        break;
                    }
                    if (Constituents.Count > 0)
                    {
                        return(new Production(null, tokens));
                    }
                    current = new StringExpression().Parse(remaining);
                    break;

                case TokenClass.Boolean:
                    current = new OperationExpression().Parse(remaining);
                    if (current.Expression != null)
                    {
                        break;
                    }
                    if (Constituents.Count > 0)
                    {
                        return(new Production(null, tokens));
                    }
                    current = new BooleanExpression().Parse(remaining);
                    break;

                case TokenClass.Symbol:
                    current = new FunctionExpression().Parse(remaining);
                    if (current.Expression != null)
                    {
                        break;
                    }
                    if (Constituents.Count > 0)
                    {
                        return(new Production(null, tokens));
                    }
                    current = new SymbolExpression().Parse(remaining);
                    break;

                case TokenClass.StartScope:
                    current = new SeparatedExpression().Parse(remaining);
                    if (current.Expression != null)
                    {
                        break;
                    }
                    if (Constituents.Count > 0)
                    {
                        return(new Production(null, tokens));
                    }
                    current = new ScopedExpression().Parse(remaining);
                    break;

                case TokenClass.Whitespace:
                    current = new WhitespaceExpression().Parse(remaining);
                    break;

                case TokenClass.Operator:
                    if (Constituents.Count != 1)
                    {
                        return(new Production(null, remaining));
                    }
                    current = new OperationExpression().Parse(Constituents.First(), remaining);
                    if (current.Expression == null)
                    {
                        break;
                    }
                    Constituents.Clear();
                    break;

                default:
                    return(new Production(null, remaining));

                    break;
                }
                if (current.Expression == null)
                {
                    return(new Production(null, tokens));
                }
                if (!(current.Expression is WhitespaceExpression))
                {
                    Constituents.Add(current.Expression);
                }
                remaining = current.RemainingTokens;
            }
            if (remaining.None())
            {
                return(new Production(null, tokens));
            }
            if (remaining[0].TokenClass != TokenClass.EndScope)
            {
                return(new Production(null, tokens));
            }
            return(new Production(this, remaining.Skip(1).ToList()));
        }
예제 #2
0
        public override Production Parse(List <Token> tokens)
        {
            var nonWhitespace = tokens.NextNonWhitespace();

            if (nonWhitespace.TokenClass != TokenClass.Boolean &&
                nonWhitespace.TokenClass != TokenClass.Float &&
                nonWhitespace.TokenClass != TokenClass.Integer &&
                nonWhitespace.TokenClass != TokenClass.ReplacementSymbol &&
                nonWhitespace.TokenClass != TokenClass.StartScope &&
                nonWhitespace.TokenClass != TokenClass.String &&
                nonWhitespace.TokenClass != TokenClass.Symbol)
            {
                return(new Production(null, tokens));
            }
            var remainder = tokens.ToList();

            while (remainder.Any() && Constituents.Count < 3) // An operation must have exactly three items: value op value
            {
                var        currentToken = remainder.First().TokenClass;
                Production current      = null;
                //check whether the right hand side of the operation is another operation
                if (Constituents.Count == 2)
                {
                    current = new OperationExpression().Parse(remainder);
                }
                if (Constituents.Count != 2 || current?.Expression == null)
                {
                    switch (currentToken)
                    {
                    case TokenClass.StartScope:
                        current = new ScopedExpression().Parse(remainder);
                        break;

                    case TokenClass.Whitespace:
                        current = new WhitespaceExpression().Parse(remainder);
                        break;

                    case TokenClass.ReplacementSymbol:
                        current = new ReplacementSymbolExpression().Parse(remainder);
                        break;

                    case TokenClass.Symbol:
                        current = new FunctionExpression().Parse(remainder);
                        if (current.Expression == null)
                        {
                            current = new SymbolExpression().Parse(remainder);
                        }
                        break;

                    case TokenClass.Operator:
                        if (Constituents.Count == 2)
                        {
                            current = NumericExpression.TryParseNumeric(remainder);
                            break;
                        }
                        current = new OperatorExpression().Parse(remainder);
                        break;

                    case TokenClass.Integer:
                    case TokenClass.Float:
                        current = NumericExpression.TryParseNumeric(remainder);
                        break;

                    case TokenClass.String:
                        current = new StringExpression().Parse(remainder);
                        break;

                    case TokenClass.Boolean:
                        current = new BooleanExpression().Parse(remainder);
                        break;

                    default:
                        return(new Production(null, tokens));
                    }
                }
                if (current == null || current.Expression == null)
                {
                    return(new Production(null, tokens));
                }
                remainder = current.RemainingTokens;
                if (!(current.Expression is WhitespaceExpression))
                {
                    Constituents.Add(current.Expression);
                }
            }
            if (Constituents.None(c => c is OperatorExpression))
            {
                return(new Production(null, tokens));
            }
            if (Constituents.Count != 3)
            {
                return(new Production(null, tokens));
            }
            return(new Production(this, remainder));
        }
예제 #3
0
        //constant:
        //    Integer
        //    Float
        //    String
        //    Boolean

        //symbol:
        //    ReplacementSymbol
        //    Symbol

        //value:
        //    constant
        //    symbol
        //    operation
        //    scope

        //operation: value Operator value

        //list-expression: value-source , value-source

        //scope: StartScope value-source EndScope

        //value-source:
        //    value
        //    scope
        //    function
        //    operation

        //function: symbol StartScope list-expression EndScope | symbol StartScope value-source EndScope
        public static Expression Parse(List <Token> tokens)
        {
            if (tokens == null || tokens.None())
            {
                return(new NullExpression());
            }
            var        remainder = tokens.ToList();
            Expression program   = null;

            while (remainder.Any())
            {
                Production parsed  = null;
                var        current = remainder.First();
                switch (current.TokenClass)
                {
                case TokenClass.StartScope:
                    parsed = new ScopedExpression().Parse(remainder);
                    if (parsed.Expression != null)
                    {
                        break;
                    }
                    parsed = new SeparatedExpression().Parse(remainder);
                    if (parsed.Expression != null)
                    {
                        break;
                    }
                    parsed = new ErrorExpression().Parse(program, remainder);
                    break;

                case TokenClass.Whitespace:
                    parsed = new WhitespaceExpression().Parse(remainder);
                    break;

                case TokenClass.Symbol:
                    parsed = new OperationExpression().Parse(remainder);
                    if (parsed.Expression != null)
                    {
                        break;
                    }
                    parsed = new FunctionExpression().Parse(remainder);
                    if (parsed.Expression != null)
                    {
                        break;
                    }
                    parsed = new SymbolExpression().Parse(remainder);
                    if (parsed.Expression != null)
                    {
                        break;
                    }
                    parsed = new ErrorExpression().Parse(program, remainder);
                    break;

                case TokenClass.ReplacementSymbol:
                    parsed = new OperationExpression().Parse(remainder);
                    if (parsed.Expression != null)
                    {
                        break;
                    }
                    parsed = new ReplacementSymbolExpression().Parse(remainder);
                    break;

                case TokenClass.Float:
                case TokenClass.Integer:
                    parsed = new OperationExpression().Parse(remainder);
                    if (parsed.Expression != null)
                    {
                        break;
                    }
                    parsed = NumericExpression.TryParseNumeric(remainder);
                    break;

                case TokenClass.String:
                    parsed = new OperationExpression().Parse(remainder);
                    if (parsed.Expression != null)
                    {
                        break;
                    }
                    parsed = new StringExpression().Parse(remainder);
                    break;

                case TokenClass.Boolean:
                    parsed = new OperationExpression().Parse(remainder);
                    if (parsed.Expression != null)
                    {
                        break;
                    }
                    parsed = new BooleanExpression().Parse(remainder);
                    break;

                case TokenClass.Operator:
                    parsed = NumericExpression.TryParseNumeric(remainder);
                    if (parsed.Expression != null)
                    {
                        break;
                    }
                    parsed = new OperationExpression().Parse(program, remainder);
                    if (parsed.Expression != null)
                    {
                        break;
                    }
                    parsed = new ErrorExpression().Parse(program, remainder);
                    break;

                case TokenClass.Error:
                    throw new Exception("Unexpected sequence: " + remainder.First().Lexeme);

                default:
                    throw new ArgumentOutOfRangeException();
                }
                if (parsed.Expression != null && !(parsed.Expression is WhitespaceExpression))
                {
                    program = parsed.Expression;
                }
                remainder = parsed.RemainingTokens;
            }
            if (program == null || remainder.Any())
            {
                throw new ParserException(remainder.Select(c => c.Lexeme).StringConcat());
            }
            return(program);
        }
예제 #4
0
        public override Production Parse(List <Token> tokens)
        {
            var firstParen = tokens.First();

            if (firstParen.TokenClass != TokenClass.StartScope)
            {
                return(new Production(null, tokens));
            }
            var current   = new ScopeExpression().Parse(tokens);
            var remaining = current.RemainingTokens.ToList();

            while (remaining.Any() && remaining.FirstOrDefault() != null && remaining[0].TokenClass != TokenClass.EndScope)
            {
                switch (remaining.First().TokenClass)
                {
                case TokenClass.ReplacementSymbol:
                    if (Constituents.Count > 1 && !(Constituents.Last() is SeparatorExpression))
                    {
                        return(new Production(null, tokens));
                    }
                    current = new ReplacementSymbolExpression().Parse(remaining);
                    break;

                case TokenClass.Integer:
                case TokenClass.Float:
                    if (Constituents.Count > 1 && !(Constituents.Last() is SeparatorExpression))
                    {
                        return(new Production(null, tokens));
                    }
                    current = NumericExpression.TryParseNumeric(remaining);
                    break;

                case TokenClass.String:
                    if (Constituents.Count > 1 && !(Constituents.Last() is SeparatorExpression))
                    {
                        return(new Production(null, tokens));
                    }
                    current = new StringExpression().Parse(remaining);
                    break;

                case TokenClass.Boolean:
                    if (Constituents.Count > 1 && !(Constituents.Last() is SeparatorExpression))
                    {
                        return(new Production(null, tokens));
                    }
                    current = new BooleanExpression().Parse(remaining);
                    break;

                case TokenClass.Symbol:
                    if (Constituents.Count > 1 && !(Constituents.Last() is SeparatorExpression))
                    {
                        return(new Production(null, tokens));
                    }
                    current = new FunctionExpression().Parse(remaining);;
                    if (current.Expression != null)
                    {
                        break;
                    }
                    current = new SymbolExpression().Parse(remaining);
                    break;

                case TokenClass.StartScope:
                    if (Constituents.Count > 1 && !(Constituents.Last() is SeparatorExpression))
                    {
                        return(new Production(null, tokens));
                    }
                    current = new SeparatedExpression().Parse(remaining);
                    if (current.Expression != null)
                    {
                        break;
                    }
                    current = new ScopedExpression().Parse(remaining);
                    if (current.Expression != null)
                    {
                        break;
                    }
                    break;

                case TokenClass.EndScope:
                    current = new ScopeExpression().Parse(remaining);
                    break;

                case TokenClass.Whitespace:
                    current = new WhitespaceExpression().Parse(remaining);
                    break;

                case TokenClass.Separator:
                    current = new SeparatorExpression().Parse(remaining);
                    break;

                case TokenClass.Operator:
                    if (Constituents.Count < 1 || (Constituents.Last() is SeparatorExpression))
                    {
                        return(new Production(null, remaining));
                    }
                    current = new OperationExpression().Parse(Constituents.Last(), remaining);
                    if (current.Expression == null)
                    {
                        break;
                    }
                    Constituents.RemoveAt(Constituents.Count - 1);
                    break;

                default:
                    return(new Production(null, remaining));
                }
                if (current.Expression == null)
                {
                    return(new Production(null, tokens));
                }
                if (!(current.Expression is WhitespaceExpression))
                {
                    Constituents.Add(current.Expression);
                }
                remaining = current.RemainingTokens;
            }
            //parenthesis must be closed
            if (remaining.FirstOrDefault() == null || remaining.First().TokenClass != TokenClass.EndScope)
            {
                return(new Production(null, remaining));
            }
            var separators = Constituents.Count(c => c is SeparatorExpression);
            var values     = Constituents.Count(c => !(c is SeparatorExpression));

            //cannot be a separated expression without separators
            if (separators == 0)
            {
                return(new Production(null, tokens));
            }
            //separated expressions require exactly n - 1 separators to values
            if (separators != (values - 1))
            {
                return(new Production(null, tokens));
            }
            var valuesOnly = Constituents.ToList().Aggregate(new List <Expression>(), (acc, i) =>
            {
                if (i is ScopeExpression || i is SeparatorExpression)
                {
                    return(acc);
                }
                acc.Add(i);
                return(acc);
            }).ToList();

            Constituents = valuesOnly;
            return(new Production(this, remaining.Skip(1).ToList()));
        }