// Concatenate two literal strings ParseNode OptimiseConcatenation(ParseNode node) { BinaryOpParseNode tokenNode = (BinaryOpParseNode)node; tokenNode.Left = OptimiseExpressionTree(tokenNode.Left); tokenNode.Right = OptimiseExpressionTree(tokenNode.Right); if ((tokenNode.Left.ID == ParseID.STRING) && (tokenNode.Right.ID == ParseID.STRING)) { StringParseNode op1 = (StringParseNode)tokenNode.Left; StringParseNode op2 = (StringParseNode)tokenNode.Right; node = new StringParseNode(op1.Value + op2.Value); } return node; }
// Parse a control list. // The return value is a dictionary of parsenodes where the key value is // the parameter name. The parse node may either be an expression or a // literal value depending on context. ControlList ParseCIList(Collection<string> allowedSpecifiers) { ControlList cilist = new ControlList(); ParseNode node = null; int index = 0; // Check for the simple format first if (_ls.PeekToken().ID != TokenID.LPAREN) { if (allowedSpecifiers.Contains("FMT")) { cilist["FMT"] = ParseFormatSpecifier(); } else if (allowedSpecifiers.Contains("UNIT")) { cilist["UNIT"] = ParseUnitSpecifier(); } } else { ExpectToken(TokenID.LPAREN); SimpleToken token; do { string paramName; token = _ls.GetToken(); if (token.ID == TokenID.IDENT && _ls.PeekToken().ID == TokenID.EQUOP) { IdentifierToken identToken = (IdentifierToken)token; paramName = identToken.Name; ExpectToken(TokenID.EQUOP); } else { _ls.BackToken(); if (index == 0) { paramName = "UNIT"; } else if (index == 1) { paramName = "FMT"; } else { _messages.Error(MessageCode.CILISTERROR, String.Format("Parameter at position {0} must be named", index)); return null; } } if (cilist.Has(paramName)) { _messages.Error(MessageCode.CILISTSPECIFIED, String.Format("Parameter {0} already specified", paramName)); return null; } if (!allowedSpecifiers.Contains(paramName)) { _messages.Error(MessageCode.CILISTNOTALLOWED, String.Format("Parameter {0} not allowed here", paramName)); return null; } switch (paramName) { case "UNIT": if (_ls.PeekToken().ID != TokenID.STAR) { node = Expression(); } else { _ls.GetToken(); } break; case "FMT": node = ParseFormatSpecifier(); break; case "ACCESS": case "FILE": case "FORM": case "STATUS": case "BLANK": node = ParseExpressionOfTypes(new [] { SymType.FIXEDCHAR, SymType.CHAR}); break; case "END": case "ERR": node = ParseLabel(); break; case "REC": case "RECL": node = ParseExpressionOfTypes(new [] { SymType.INTEGER }); break; case "IOSTAT": case "EXIST": case "OPENED": case "NUMBER": case "NAMED": case "NAME": case "SEQUENTIAL": case "DIRECT": case "FORMATTED": case "UNFORMATTED": case "NEXTREC": node = ParseIdentifier(); break; } if (node != null) { cilist[paramName] = node; } ++index; token = _ls.GetToken(); } while (token.ID == TokenID.COMMA); _ls.BackToken(); ExpectToken(TokenID.RPAREN); } // Add FMT default if (!cilist.Has("FMT")) { cilist["FMT"] = new StringParseNode(string.Empty); } return cilist; }