private ISymbolicExpressionTreeNode ParseBinaryFactor(Queue <Token> tokens)
        {
            Token tok = tokens.Dequeue();

            Debug.Assert(tok.StringValue == "BINFACTOR");
            var t          = (BinaryFactorVariableTreeNode)binFactorVar.CreateTreeNode();
            var varNameTok = tokens.Dequeue();

            Debug.Assert(varNameTok.Symbol == TokenSymbol.SYMB);
            t.VariableName = varNameTok.StringValue;

            var varValTok = tokens.Dequeue();

            Debug.Assert(varValTok.Symbol == TokenSymbol.SYMB);
            t.VariableValue = varValTok.StringValue;

            var weightTok = tokens.Dequeue();

            Debug.Assert(weightTok.Symbol == TokenSymbol.NUMBER);
            t.Weight = weightTok.DoubleValue;

            return(t);
        }
Beispiel #2
0
        /// SimpleFact   = '(' Expr ')'
        ///                 | '{' Expr '}'
        ///                 | 'LAG' '(' varId ',' ['+' | '-' ] number ')'
        ///                 | funcId '(' ArgList ')
        ///                 | VarExpr
        ///                 | number
        /// ArgList       = Expr { ',' Expr }
        /// VarExpr       = varId OptFactorPart
        /// OptFactorPart = [ ('=' varVal | '[' ['+' | '-' ] number {',' ['+' | '-' ] number } ']' ) ]
        /// varId         =  ident | ' ident ' | " ident "
        /// varVal        =  ident | ' ident ' | " ident "
        /// ident         =  '_' | letter { '_' | letter | digit }
        private ISymbolicExpressionTreeNode ParseSimpleFact(Queue <Token> tokens)
        {
            var next = tokens.Peek();

            if (next.TokenType == TokenType.LeftPar)
            {
                var initPar = tokens.Dequeue(); // match par type
                var expr    = ParseExpr(tokens);
                var rPar    = tokens.Dequeue();
                if (rPar.TokenType != TokenType.RightPar)
                {
                    throw new ArgumentException("expected closing parenthesis");
                }
                if (initPar.strVal == "(" && rPar.strVal == "}")
                {
                    throw new ArgumentException("expected closing )");
                }
                if (initPar.strVal == "{" && rPar.strVal == ")")
                {
                    throw new ArgumentException("expected closing }");
                }
                return(expr);
            }
            else if (next.TokenType == TokenType.Identifier)
            {
                var idTok = tokens.Dequeue();
                if (tokens.Peek().TokenType == TokenType.LeftPar)
                {
                    // function identifier or LAG
                    var funcId = idTok.strVal.ToUpperInvariant();

                    var funcNode = GetSymbol(funcId).CreateTreeNode();
                    var lPar     = tokens.Dequeue();
                    if (lPar.TokenType != TokenType.LeftPar)
                    {
                        throw new ArgumentException("expected (");
                    }

                    // handle 'lag' specifically
                    if (funcNode.Symbol is LaggedVariable)
                    {
                        var varId = tokens.Dequeue();
                        if (varId.TokenType != TokenType.Identifier)
                        {
                            throw new ArgumentException("Identifier expected. Format for lagged variables: \"lag(x, -1)\"");
                        }
                        var comma = tokens.Dequeue();
                        if (comma.TokenType != TokenType.Comma)
                        {
                            throw new ArgumentException("',' expected, Format for lagged variables: \"lag(x, -1)\"");
                        }
                        double sign = 1.0;
                        if (tokens.Peek().strVal == "+" || tokens.Peek().strVal == "-")
                        {
                            // read sign
                            var signTok = tokens.Dequeue();
                            if (signTok.strVal == "-")
                            {
                                sign = -1.0;
                            }
                        }
                        var lagToken = tokens.Dequeue();
                        if (lagToken.TokenType != TokenType.Number)
                        {
                            throw new ArgumentException("Number expected, Format for lagged variables: \"lag(x, -1)\"");
                        }
                        if (!lagToken.doubleVal.IsAlmost(Math.Round(lagToken.doubleVal)))
                        {
                            throw new ArgumentException("Time lags must be integer values");
                        }
                        var laggedVarNode = funcNode as LaggedVariableTreeNode;
                        laggedVarNode.VariableName = varId.strVal;
                        laggedVarNode.Lag          = (int)Math.Round(sign * lagToken.doubleVal);
                        laggedVarNode.Weight       = 1.0;
                    }
                    else
                    {
                        // functions
                        var args = ParseArgList(tokens);
                        // check number of arguments
                        if (funcNode.Symbol.MinimumArity > args.Length || funcNode.Symbol.MaximumArity < args.Length)
                        {
                            throw new ArgumentException(string.Format("Symbol {0} requires between {1} and  {2} arguments.", funcId,
                                                                      funcNode.Symbol.MinimumArity, funcNode.Symbol.MaximumArity));
                        }
                        foreach (var arg in args)
                        {
                            funcNode.AddSubtree(arg);
                        }
                    }

                    var rPar = tokens.Dequeue();
                    if (rPar.TokenType != TokenType.RightPar)
                    {
                        throw new ArgumentException("expected )");
                    }


                    return(funcNode);
                }
                else
                {
                    // variable
                    if (tokens.Peek().TokenType == TokenType.Eq)
                    {
                        // binary factor
                        tokens.Dequeue(); // skip Eq
                        var valTok = tokens.Dequeue();
                        if (valTok.TokenType != TokenType.Identifier)
                        {
                            throw new ArgumentException("expected identifier");
                        }
                        var binFactorNode = (BinaryFactorVariableTreeNode)binaryFactorVar.CreateTreeNode();
                        binFactorNode.Weight        = 1.0;
                        binFactorNode.VariableName  = idTok.strVal;
                        binFactorNode.VariableValue = valTok.strVal;
                        return(binFactorNode);
                    }
                    else if (tokens.Peek().TokenType == TokenType.LeftBracket)
                    {
                        // factor variable
                        var factorVariableNode = (FactorVariableTreeNode)factorVar.CreateTreeNode();
                        factorVariableNode.VariableName = idTok.strVal;

                        tokens.Dequeue(); // skip [
                        var weights = new List <double>();
                        // at least one weight is necessary
                        var sign = 1.0;
                        if (tokens.Peek().TokenType == TokenType.Operator)
                        {
                            var opToken = tokens.Dequeue();
                            if (opToken.strVal == "+")
                            {
                                sign = 1.0;
                            }
                            else if (opToken.strVal == "-")
                            {
                                sign = -1.0;
                            }
                            else
                            {
                                throw new ArgumentException();
                            }
                        }
                        if (tokens.Peek().TokenType != TokenType.Number)
                        {
                            throw new ArgumentException("number expected");
                        }
                        var weightTok = tokens.Dequeue();
                        weights.Add(sign * weightTok.doubleVal);
                        while (tokens.Peek().TokenType == TokenType.Comma)
                        {
                            // skip comma
                            tokens.Dequeue();
                            if (tokens.Peek().TokenType == TokenType.Operator)
                            {
                                var opToken = tokens.Dequeue();
                                if (opToken.strVal == "+")
                                {
                                    sign = 1.0;
                                }
                                else if (opToken.strVal == "-")
                                {
                                    sign = -1.0;
                                }
                                else
                                {
                                    throw new ArgumentException();
                                }
                            }
                            weightTok = tokens.Dequeue();
                            if (weightTok.TokenType != TokenType.Number)
                            {
                                throw new ArgumentException("number expected");
                            }
                            weights.Add(sign * weightTok.doubleVal);
                        }
                        var rightBracketToken = tokens.Dequeue();
                        if (rightBracketToken.TokenType != TokenType.RightBracket)
                        {
                            throw new ArgumentException("closing bracket ] expected");
                        }
                        factorVariableNode.Weights = weights.ToArray();
                        return(factorVariableNode);
                    }
                    else
                    {
                        // variable
                        var varNode = (VariableTreeNode)variable.CreateTreeNode();
                        varNode.Weight       = 1.0;
                        varNode.VariableName = idTok.strVal;
                        return(varNode);
                    }
                }
            }
            else if (next.TokenType == TokenType.Number)
            {
                var numTok    = tokens.Dequeue();
                var constNode = (ConstantTreeNode)constant.CreateTreeNode();
                constNode.Value = numTok.doubleVal;
                return(constNode);
            }
            else
            {
                throw new ArgumentException(string.Format("unexpected token in expression {0}", next.strVal));
            }
        }