コード例 #1
0
ファイル: loop.cs プロジェクト: stevewpalmer/jcom
 /// <summary>
 /// Creates a loop parse node.
 /// </summary>
 public LoopParseNode()
     : base(ParseID.LOOP)
 {
     StepExpression = new NumberParseNode(1);
 }
コード例 #2
0
ファイル: extfunc.cs プロジェクト: stevewpalmer/jcom
 /// <summary>
 /// Returns a ParametersParseNode object that represents the parameters defined
 /// for this external function using the values specified in the given control
 /// list dictionary. For parameters where no value is given, a default of 0 or
 /// NULL is substituted.
 /// </summary>
 /// <param name="cilist">A dictionary of control list values</param>
 /// <returns>A ParametersParseNode object.</returns>
 public ParametersParseNode ParametersNode(ControlList cilist)
 {
     if (cilist == null) {
         throw new ArgumentNullException("cilist");
     }
     ParametersParseNode paramList = new ParametersParseNode();
     foreach (FunctionDefinition def in _definitions) {
         if (def.Include) {
             ParseNode exprNode;
             if (!cilist.Has(def.Name)) {
                 if (Symbol.IsNumberType(def.Symbol.Type)) {
                     exprNode = new NumberParseNode(0);
                 } else if (Symbol.IsLogicalType(def.Symbol.Type)) {
                     exprNode = new NumberParseNode(new Variant(false));
                 } else {
                     exprNode = new NullParseNode();
                     exprNode.Type = def.Symbol.Type;
                 }
             } else {
                 exprNode = cilist[def.Name];
             }
             paramList.Add(exprNode, def.Symbol);
         }
     }
     return paramList;
 }
コード例 #3
0
ファイル: fileio.cs プロジェクト: stevewpalmer/jcom
        /// READ keyword
        /// Reads data into variables. Basically the run-time handles the I/O and the
        /// format list, and we provide the parameters.
        ParseNode KRead()
        {
            ReadParseNode node = new ReadParseNode();

            InitFunctionNodes();

            ControlList cilist = ParseCIList(_readFunctions.ParameterList);
            if (cilist == null) {
                SkipToEndOfLine();
                return null;
            }

            node.ArgList = ParseVarargReferenceList();
            node.EndLabel = (SymbolParseNode)cilist["END"];
            node.ErrLabel = (SymbolParseNode)cilist["ERR"];
            node.ReadParamsNode = _ioCoreFunctions.ParametersNode(cilist);

            // If this is internal storage, create an expression that
            // uses the given character string as the input source.
            ParseNode unit = cilist["UNIT"];

            if (unit != null && unit.ID == ParseID.IDENT && Symbol.IsCharType(unit.Type)) {
                if (cilist.Has("REC")) {
                    _messages.Error(MessageCode.CILISTNOTALLOWED, "Parameter REC not allowed here");
                    SkipToEndOfLine();
                    return null;
                }
                node.ReadManagerParamsNode = _readFunctionString.ParametersNode(cilist);
            } else {
                if (unit == null) {
                    cilist["UNIT"] = new NumberParseNode(new Variant(IOConstant.Stdin));
                }
                node.ReadManagerParamsNode = _readFunctions.ParametersNode(cilist);
            }
            return node;
        }
コード例 #4
0
ファイル: fileio.cs プロジェクト: stevewpalmer/jcom
        /// WRITE keyword
        ParseNode KWrite()
        {
            WriteParseNode node = new WriteParseNode();

            InitFunctionNodes();

            ControlList cilist = ParseCIList(_writeFunctions.ParameterList);
            if (cilist == null) {
                SkipToEndOfLine();
                return null;
            }

            node.ArgList = ParseVarargList();
            node.ErrLabel = (SymbolParseNode)cilist["ERR"];

            // First column is special for F77 only
            node.FirstColumnSpecial = (_opts.F77);

            // If this is internal storage, create an expression that
            // assigns the result to the character string
            ParseNode unit = cilist["UNIT"];

            if (unit != null && unit.ID == ParseID.IDENT && Symbol.IsCharType(unit.Type)) {
                node.WriteParamsNode = _ioCoreFunctions.ParametersNode(cilist);
                node.WriteManagerParamsNode = _writeFunctionString.ParametersNode(cilist);

                AssignmentParseNode assignNode = new AssignmentParseNode();
                assignNode.Identifier = (IdentifierParseNode)unit;
                assignNode.ValueExpression = node;
                return assignNode;
            }

            if (unit == null) {
                cilist["UNIT"] = new NumberParseNode(new Variant(IOConstant.Stdout));
            }
            node.WriteParamsNode = _ioCoreFunctions.ParametersNode(cilist);
            node.WriteManagerParamsNode = _writeFunctions.ParametersNode(cilist);
            return node;
        }
コード例 #5
0
ファイル: expr.cs プロジェクト: stevewpalmer/jcom
        // Optimise a subtraction expression where both nodes are literal
        // values. Substitute the node with the result of the subtraction.
        ParseNode OptimiseSubtraction(ParseNode node)
        {
            BinaryOpParseNode tokenNode = (BinaryOpParseNode)node;
            tokenNode.Left = OptimiseExpressionTree(tokenNode.Left);
            tokenNode.Right = OptimiseExpressionTree(tokenNode.Right);

            if (tokenNode.IsNumber) {
                NumberParseNode op1 = (NumberParseNode)tokenNode.Left;
                NumberParseNode op2 = (NumberParseNode)tokenNode.Right;
                node = new NumberParseNode(op1.Value - op2.Value);
            }

            // Check for zero simplification
            if (tokenNode.Right.IsNumber) {
                if (tokenNode.Right.Value.IsZero) {
                    return tokenNode.Left;
                }
            }
            return node;
        }
コード例 #6
0
ファイル: fileio.cs プロジェクト: stevewpalmer/jcom
        /// PRINT keyword
        ParseNode KPrint()
        {
            WriteParseNode node = new WriteParseNode();

            InitFunctionNodes();

            ControlList cilist = new ControlList();
            cilist["FMT"] = ParseFormatSpecifier();
            cilist["UNIT"] = new NumberParseNode(new Variant(IOConstant.Stdout));

            // First column is special for F77 only
            node.FirstColumnSpecial = (_opts.F77);

            if (!IsAtEndOfLine()) {
                SimpleToken token;

                ExpectToken(TokenID.COMMA);
                VarArgParseNode varargs = new VarArgParseNode();
                do {
                    varargs.Add(ParseExpressionWithImpliedDo());
                    token = _ls.GetToken();
                } while (token.ID == TokenID.COMMA);
                _ls.BackToken();
                node.ArgList = varargs;
            }

            node.WriteParamsNode = _ioCoreFunctions.ParametersNode(cilist);
            node.WriteManagerParamsNode = _writeFunctions.ParametersNode(cilist);
            return node;
        }
コード例 #7
0
ファイル: expr.cs プロジェクト: stevewpalmer/jcom
 // Optimise a negation expression where both nodes are literal
 // values. Substitute the node with the result of the negation.
 ParseNode OptimiseMinus(ParseNode node)
 {
     UnaryOpParseNode tokenNode = (UnaryOpParseNode)node;
     tokenNode.Operand = OptimiseExpressionTree(tokenNode.Operand);
     if (tokenNode.Operand.IsNumber) {
         NumberParseNode op1 = (NumberParseNode)tokenNode.Operand;
         node = new NumberParseNode(-op1.Value);
     }
     return node;
 }
コード例 #8
0
ファイル: expr.cs プロジェクト: stevewpalmer/jcom
        // Optimise an exponentation expression where both nodes are literal
        // values. Substitute the node with the result of the exponentation.
        ParseNode OptimiseExponentation(ParseNode node)
        {
            BinaryOpParseNode tokenNode = (BinaryOpParseNode)node;
            tokenNode.Left = OptimiseExpressionTree(tokenNode.Left);
            tokenNode.Right = OptimiseExpressionTree(tokenNode.Right);

            if (tokenNode.IsNumber) {
                NumberParseNode op1 = (NumberParseNode)tokenNode.Left;
                NumberParseNode op2 = (NumberParseNode)tokenNode.Right;
                node = new NumberParseNode(op1.Value.Pow(op2.Value));
            }

            // x raised to the powers of -1, 0 and 1 all yield constant expressions
            // so we can simplify that right now.
            if (tokenNode.Right.IsNumber) {
                Variant rightValue = tokenNode.Right.Value;
                if (rightValue.Compare(-1)) {
                    BinaryOpParseNode divNode = new BinaryOpParseNode(ParseID.DIVIDE);
                    divNode.Left = new NumberParseNode(new Variant(1));
                    divNode.Right = tokenNode.Left;
                    divNode.Type = tokenNode.Left.Type;
                    return divNode;
                }
                if (rightValue.IsZero) {
                    return new NumberParseNode(1);
                }
                if (rightValue.Compare(1)) {
                    return tokenNode.Left;
                }
            }
            return node;
        }
コード例 #9
0
ファイル: expr.cs プロジェクト: stevewpalmer/jcom
        // Optimise a division expression where both nodes are literal
        // values. Substitute the node with the result of the division.
        ParseNode OptimiseDivision(ParseNode node)
        {
            BinaryOpParseNode tokenNode = (BinaryOpParseNode)node;
            tokenNode.Left = OptimiseExpressionTree(tokenNode.Left);
            tokenNode.Right = OptimiseExpressionTree(tokenNode.Right);

            if (tokenNode.IsNumber) {
                NumberParseNode op1 = (NumberParseNode)tokenNode.Left;
                NumberParseNode op2 = (NumberParseNode)tokenNode.Right;
                try {
                    node = new NumberParseNode(op1.Value / op2.Value);
                } catch (DivideByZeroException) {
                    _messages.Error(MessageCode.DIVISIONBYZERO, "Constant division by zero");
                }
            }
            return node;
        }
コード例 #10
0
ファイル: parser.cs プロジェクト: stevewpalmer/jcom
        // Parse an identifier parse node from the specified token.
        IdentifierParseNode ParseIdentifierParseNode()
        {
            IdentifierParseNode node = new IdentifierParseNode(null);
            Collection<ParseNode> indices = null;
            SimpleToken token = _ls.GetToken();
            bool isSubstring = false;

            while (token.ID == TokenID.LPAREN) {
                if (indices == null) {
                    indices = new Collection<ParseNode>();
                }
                if (_ls.PeekToken().ID != TokenID.RPAREN) {
                    do {
                        ParseNode item = null;

                        if (_ls.PeekToken().ID == TokenID.RPAREN) {
                            SkipToken(TokenID.RPAREN);
                            break;
                        }
                        if (_ls.PeekToken().ID != TokenID.COLON) {
                            item = Expression();
                        }
                        token = _ls.GetToken();
                        if (token.ID == TokenID.COLON) {
                            isSubstring = true;
                            if (item == null) {
                                item = new NumberParseNode(1);
                            }
                            node.SubstringStart = item;
                            token = new SimpleToken(TokenID.COMMA);
                            continue;
                        }
                        if (isSubstring) {
                            node.SubstringEnd = item;
                            break;
                        }
                        indices.Add(item);
                    } while (token.ID == TokenID.COMMA);
                    _ls.BackToken();
                }
                ExpectToken(TokenID.RPAREN);
                token = _ls.GetToken();
            }

            node.Indexes = indices;
            _ls.BackToken();
            return node;
        }
コード例 #11
0
ファイル: parser.cs プロジェクト: stevewpalmer/jcom
        // Parse set of array dimensions if one is found.
        Collection<SymDimension> ParseArrayDimensions()
        {
            Collection<SymDimension> dimensions = new Collection<SymDimension>();
            SimpleToken token = _ls.PeekToken();
            bool hasAssumedBound = false;

            if (token.ID == TokenID.LPAREN) {
                ExpectToken(TokenID.LPAREN);
                do {
                    do {
                        ParseNode intVal;
                        if (_ls.PeekToken().ID == TokenID.STAR) {
                            SkipToken(TokenID.STAR);
                            intVal = new NumberParseNode(0);
                            hasAssumedBound = true;
                        } else {
                            intVal = IntegerExpression();
                            if (intVal == null) {
                                SkipToEndOfLine();
                                return null;
                            }

                            // Assumed size declaration, which must be the last in
                            // the list. We use a value of 0 for this since the array
                            // calculations disregard it. However we need to make sure
                            // this IS the last dimension.
                            if (hasAssumedBound) {
                                _messages.Error(MessageCode.ARRAYENDEXPECTED, "Dimensions not permitted after assumed bound");
                                SkipToEndOfLine();
                                return null;
                            }
                        }

                        SymDimension dim = new SymDimension();

                        // Fortran arrays lower bounds start from 1 but one can
                        // specify a custom bound range with the lower:upper syntax.
                        ParseNode in1 = new NumberParseNode(1);
                        ParseNode in2 = intVal;
                        token = _ls.GetToken();
                        if (token.ID == TokenID.COLON) {
                            if (_ls.PeekToken().ID == TokenID.STAR) {
                                SkipToken(TokenID.STAR);
                                intVal = new NumberParseNode(0);
                                hasAssumedBound = true;
                            } else {
                                intVal = IntegerExpression();
                            }
                            if (intVal != null) {
                                in1 = in2;
                                in2 = intVal;
                            }
                        } else {
                            _ls.BackToken();
                        }
                        if (in2.IsConstant && in1.IsConstant) {
                            if (in2.Value.IntValue > 0 && in2.Value.IntValue < in1.Value.IntValue) {
                                _messages.Error(MessageCode.ARRAYILLEGALBOUNDS, "Illegal bounds in array");
                            }
                        }
                        dim.LowerBound = in1;
                        dim.UpperBound = in2;
                        if (dimensions.Count == 7) {
                            _messages.Error(MessageCode.TOOMANYDIMENSIONS, "Too many dimensions in array");
                        } else {
                            dimensions.Add(dim);
                        }
                        token = _ls.GetToken();
                    } while (token.ID == TokenID.COMMA);
                    _ls.BackToken();
                    ExpectToken(TokenID.RPAREN);
                    token = _ls.GetToken();
                } while (token.ID == TokenID.LPAREN);
                _ls.BackToken();
            }
            return dimensions;
        }