Пример #1
0
        // Parse an assignment statement.
        // Fairly straightforward.
        ParseNode KAssignment()
        {
            AssignmentParseNode node = new AssignmentParseNode();
            _ls.BackToken();

            IdentifierToken identToken = ExpectIdentifierToken();
            if (identToken == null) {
                SkipToEndOfLine();
                return null;
            }

            // Do a little work to see if this is a possible statement function. The logic
            // is: if the symbol is not already declared or it is but it isn't an array
            // then we're a statement function. Array element assignments here MUST have been
            // predefined.
            Symbol sym = _localSymbols.Get(identToken.Name);
            if (_ls.PeekToken().ID == TokenID.LPAREN && (sym == null || !sym.IsArray)) {
                return KStatementFunction(identToken);
            }

            IdentifierParseNode identNode = (IdentifierParseNode)ParseIdentifierFromToken(identToken);
            if (identNode != null) {

                // Can never assign to a constant
                if (identNode.Symbol.IsConstant) {
                    _messages.Error(MessageCode.CANNOTASSIGNTOCONST, "Cannot assign a value to a constant");
                    SkipToEndOfLine();
                    return null;
                }

                node.Identifier = identNode;
                ExpectToken(TokenID.EQUOP);
                ParseNode exprNode = Expression();
                if (exprNode != null) {
                    bool valid = ValidateAssignmentTypes(identNode.Type, exprNode.Type);
                    if (!valid) {
                        _messages.Error(MessageCode.TYPEMISMATCH, "Type mismatch in assignment");
                    }
                    node.ValueExpression = exprNode;
                }
            } else {
                SkipToEndOfLine();
            }
            return node;
        }
Пример #2
0
        /// 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;
        }
Пример #3
0
        // ASSIGN keyword.
        // This is a straight assignment of a label to an identifier. The
        // code generator will differentiate and construct the right code
        // to perform the assignment of the label's internal ID.
        ParseNode KAssign()
        {
            AssignmentParseNode assignNode = new AssignmentParseNode();
            SymbolParseNode label = ParseLabel();

            ExpectToken(TokenID.KTO);

            int index;
            for (index = 0; index < _currentProcedure.LabelList.Count; ++index) {
                SymbolParseNode thisLabel = (SymbolParseNode)_currentProcedure.LabelList[index];
                if (thisLabel.Symbol == label.Symbol) {
                    break;
                }
            }
            if (index == _currentProcedure.LabelList.Count) {
                _currentProcedure.LabelList.Add(label);
            }

            assignNode.Identifier = ParseBasicIdentifier();
            assignNode.ValueExpression = new NumberParseNode(index);
            return assignNode;
        }
Пример #4
0
        // DATA keyword
        // Syntax: DATA list-of-vars/values/
        ParseNode KData()
        {
            SimpleToken token;

            do {
                List<ParseNode> idList = new List<ParseNode>();
                List<Variant> valueList = new List<Variant>();
                do {
                    // BUGBUG: Check for duplicate identifier in ANY data
                    // statement. Need to set a symbol flag.
                    ParseNode node = ParseIdentifierWithImpliedDo();
                    if (node == null) {
                        SkipToEndOfLine();
                        return null;
                    }
                    idList.Add(node);
                    token = _ls.GetToken();
                } while(token.ID == TokenID.COMMA);
                _ls.BackToken();

                Variant repeatNode;
                Variant valueNode;

                ExpectToken(TokenID.DIVIDE);
                do {
                    valueNode = ParseConstant();
                    repeatNode = new Variant(1);

                    token = _ls.GetToken();
                    if (token.ID == TokenID.STAR) {
                        if (valueNode.IntValue < 1) {
                            _messages.Error(MessageCode.BADREPEATCOUNT, "Repeat count must be positive and non-zero");
                        } else {
                            repeatNode = valueNode;
                        }
                        valueNode = ParseConstant();
                        token = _ls.GetToken();
                    }
                    valueList.Add(repeatNode);
                    valueList.Add(valueNode);
                } while(token.ID == TokenID.COMMA);
                _ls.BackToken();
                ExpectToken(TokenID.DIVIDE);

                IdentifierParseNode idNode = null;
                int idIndex = 0;
                int valueIndex = 0;
                int repeatCount = 0;
                int offset = 0;

                while (idIndex < idList.Count || valueIndex < valueList.Count) {
                    if (idIndex < idList.Count) {
                        ParseNode parseNode = idList[idIndex++];
                        if (parseNode.ID == ParseID.LOOP) {
                            LoopParseNode loopNode = (LoopParseNode)parseNode;

                            // Make sure the loop range evaluates to a constant.
                            int loopCount = loopNode.IterationCount();
                            if (loopCount == -1) {
                                _messages.Error(MessageCode.NONCONSTANTDATALOOP, "Implied DO loop in DATA must be a constant");
                                SkipToEndOfLine();
                                return null;
                            }

                            // Also make sure that the loop control is an identifier. It should be an
                            // array identifier but we don't particularly check for this. Maybe we should?
                            if (loopNode.LoopValue.ID != ParseID.IDENT) {
                                _messages.Error(MessageCode.NONCONSTANTDATALOOP, "Implied DO loop in DATA must be an identifier");
                                SkipToEndOfLine();
                                return null;
                            }

                            // Generate the implied DO loop as a sequence of assignment statements that are
                            // executed during the procedure initialisation phase. All the different value
                            // representations should be handled here.
                            //
                            // 1. If the value is a sequence, then there should be as many values as
                            //    required by the loop count. If there are less, the remainder of the loop
                            //    is ignored.
                            // 2. If the value has a repeat count, we expand the value by the repeat count
                            //    and use subsequent values if there are still iterations left in the loop
                            //    counter.
                            // 3. Values beyond the end of the loop count are assigned to the other identifiers
                            //    specified in the DATA statement, if any.
                            //
                            IdentifierParseNode loopIdent = (IdentifierParseNode)loopNode.LoopValue;
                            Symbol loopSymbol = loopIdent.Symbol;

                            int loopIndex = loopNode.StartExpression.Value.IntValue;
                            while (loopCount > 0) {
                                if (repeatCount == 0 && valueIndex < valueList.Count) {
                                    repeatNode = valueList[valueIndex++];
                                    valueNode = valueList[valueIndex++];
                                }

                                AssignmentParseNode assignNode = new AssignmentParseNode();
                                assignNode.Identifier = new IdentifierParseNode(loopSymbol, loopIndex);
                                assignNode.ValueExpression = new NumberParseNode(valueNode);
                                AddInit(assignNode);

                                if (repeatCount > 0) {
                                    --repeatCount;
                                }
                                loopIndex += loopNode.StepExpression.Value.IntValue;
                                --loopCount;
                            }
                            continue;
                        }
                        Debug.Assert(parseNode.ID == ParseID.IDENT);
                        idNode = (IdentifierParseNode)parseNode;
                        offset = 0;
                    }
                    if (repeatCount == 0 && valueIndex < valueList.Count) {
                        repeatNode = valueList[valueIndex++];
                        valueNode = valueList[valueIndex++];
                        repeatCount = repeatNode.IntValue;
                    }
                    Debug.Assert(idNode != null);
                    Symbol sym = idNode.Symbol;
                    if (sym.IsArray) {
                        ArrayParseNode arrayNode = new ArrayParseNode();
                        arrayNode.Identifier = idNode;
                        if (idNode.Indexes != null) {
                            arrayNode.StartRange = 0;
                            arrayNode.EndRange = 0;
                            arrayNode.RangeValue = valueNode;
                            AddInit(arrayNode);
                        } else {
                            arrayNode.StartRange = offset;
                            arrayNode.EndRange = offset + (repeatCount - 1);
                            arrayNode.RangeValue = valueNode;
                            AddInit(arrayNode);
                            offset += repeatCount;
                            repeatCount = 1;
                        }
                    } else if (idNode.HasSubstring) {
                        AssignmentParseNode assignNode = new AssignmentParseNode();
                        assignNode.Identifier = idNode;
                        assignNode.ValueExpression = new StringParseNode(valueNode.StringValue);
                        AddInit(assignNode);
                    } else {
                        sym.Value = valueNode;
                    }
                    --repeatCount;
                }
                token = _ls.GetToken();
            } while (token.ID == TokenID.COMMA);
            _ls.BackToken();
            return null;
        }