/// 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; }
// Parse a variable length argument list of references. CollectionParseNode ParseVarargReferenceList() { VarArgParseNode varargs = null; if (!IsAtEndOfLine()) { varargs = new VarArgParseNode(); SimpleToken token; // Optional comma. SkipToken(TokenID.COMMA); do { varargs.Add(ParseIdentifierWithImpliedDo()); token = _ls.GetToken(); } while (token.ID == TokenID.COMMA); _ls.BackToken(); } return varargs; }
// Parse an intrinsic function call ParseNode IntrinsicOperand(string name, IdentifierParseNode node) { ExtCallParseNode tokenNode = new ExtCallParseNode("JComLib.Intrinsics,jcomlib", name); IntrDefinition intrDefinition = Intrinsics.IntrinsicDefinition(name); Debug.Assert(intrDefinition != null); SymType argType = SymType.NONE; int countOfParams = 0; bool isVarArg = (intrDefinition.Count == ArgCount.TwoOrMore); ParametersParseNode paramsNode = new ParametersParseNode(); VarArgParseNode argList = new VarArgParseNode(); // Parameters to inlined instrinsics are always passed by value. bool useByRef = !(_opts.Inline) || !tokenNode.CanInline(); if (!intrDefinition.IsPermittedInIntrinsic) { useByRef = false; } for (int c = 0; c < node.Indexes.Count; ++c) { ParseNode exprNode = node.Indexes[c]; if (c > 0 && !ValidateAssignmentTypes(exprNode.Type, argType)) { _messages.Error(MessageCode.TYPEMISMATCH, string.Format("All arguments to {0} must be of the same type", name)); } argType = exprNode.Type; if (!intrDefinition.IsValidArgType(argType)) { _messages.Error(MessageCode.TYPEMISMATCH, String.Format("Invalid argument type for {0}", name)); } if (intrDefinition.RequiredType != SymType.GENERIC) { exprNode.Type = intrDefinition.RequiredType; } if (isVarArg) { argList.Add(exprNode); } else { paramsNode.Add(exprNode, useByRef); } ++countOfParams; } if (isVarArg) { paramsNode.Add(argList, useByRef); } tokenNode.Parameters = paramsNode; // Make sure actual and expected arguments match bool match = false; switch (intrDefinition.Count) { case ArgCount.One: match = (countOfParams == 1); break; case ArgCount.OneOrTwo: match = (countOfParams == 1 || countOfParams == 2); break; case ArgCount.Two: match = (countOfParams == 2); break; case ArgCount.TwoOrMore: match = (countOfParams >= 2); break; default: Debug.Assert(false, "Unhandled ArgCount!"); break; } if (!match) { _messages.Error(MessageCode.WRONGNUMBEROFARGUMENTS, String.Format("Wrong number of arguments for {0}", name)); } // Set return type. GENERIC means use the type of the argument Debug.Assert(!(intrDefinition.ReturnType == SymType.GENERIC && argType == SymType.NONE), "argType cannot be null here!"); tokenNode.Type = (intrDefinition.ReturnType == SymType.GENERIC) ? argType : intrDefinition.ReturnType; tokenNode.Inline = _opts.Inline; return tokenNode; }
// Parse a variable length argument list. CollectionParseNode ParseVarargList() { VarArgParseNode varargs = null; if (!IsAtEndOfLine()) { varargs = new VarArgParseNode(); SimpleToken token; // Optional comma. SkipToken(TokenID.COMMA); do { if (_ls.PeekToken().ID == TokenID.LPAREN) { _ls.GetToken(); varargs.Add(ParseImpliedDo()); } else { varargs.Add(Expression()); } token = _ls.GetToken(); } while (token.ID == TokenID.COMMA); _ls.BackToken(); } return varargs; }