#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <cctype>
#include <regex>
using namespace std;
// 定义Token结构
struct Token {
enum Type {
KEYWORD, IDENTIFIER, INTEGER, FLOAT, CHAR_LITERAL, STRING_LITERAL,
OPERATOR, DELIMITER, UNKNOWN
};
Type type; // Token的类型
string value; // Token的值
Token(Type t, const string& v) : type(t), value(v) {}
};
// 关键字映射表
unordered_map<string, Token::Type> keywords = {
{"int", Token::KEYWORD}, {"double", Token::KEYWORD}, {"char", Token::KEYWORD}, {"string", Token::KEYWORD},
{"if", Token::KEYWORD}, {"else", Token::KEYWORD}, {"while", Token::KEYWORD}, {"for", Token::KEYWORD},
{"return", Token::KEYWORD}, {"void", Token::KEYWORD}, {"true", Token::KEYWORD}, {"false", Token::KEYWORD}
};
// 分隔符映射表
unordered_map<char, Token::Type> delimiters = {
{'(', Token::DELIMITER}, {')', Token::DELIMITER}, {'{', Token::DELIMITER}, {'}', Token::DELIMITER},
{'[', Token::DELIMITER}, {']', Token::DELIMITER}, {',', Token::DELIMITER}, {'.', Token::DELIMITER},
{';', Token::DELIMITER}, {':', Token::DELIMITER}, {'?', Token::DELIMITER}, {'->', Token::DELIMITER}
};
// 运算符映射表
unordered_map<string, Token::Type> operators = {
{"+", Token::OPERATOR}, {"-", Token::OPERATOR}, {"*", Token::OPERATOR}, {"/", Token::OPERATOR},
{"%", Token::OPERATOR}, {"=", Token::OPERATOR}, {"==", Token::OPERATOR}, {"!=", Token::OPERATOR},
{"<", Token::OPERATOR}, {">", Token::OPERATOR}, {"<=", Token::OPERATOR}, {">=", Token::OPERATOR},
{"&&", Token::OPERATOR}, {"||", Token::OPERATOR}, {"!", Token::OPERATOR}, {"++", Token::OPERATOR},
{"--", Token::OPERATOR}
};
// 辅助函数:跳过空白字符
void skipWhitespace(const string& input, size_t& position) {
while (position < input.size() && isspace(input[position])) {
position++;
}
}
// 辅助函数:识别标识符或关键字
Token recognizeIdentifierOrKeyword(const string& input, size_t& position) {
size_t start = position;
while (position < input.size() && (isalnum(input[position]) || input[position] == '_')) {
position++;
}
string token = input.substr(start, position - start);
if (keywords.find(token) != keywords.end()) {
return Token(Token::KEYWORD, token);
}
return Token(Token::IDENTIFIER, token);
}
// 辅助函数:识别整数或浮点数
Token recognizeNumber(const string& input, size_t& position) {
size_t start = position;
bool isFloat = false;
while (position < input.size() && isdigit(input[position])) {
position++;
}
if (position < input.size() && input[position] == '.') {
position++;
isFloat = true;
while (position < input.size() && isdigit(input[position])) {
position++;
}
}
if (position < input.size() && (input[position] == 'e' || input[position] == 'E')) {
position++;
if (position < input.size() && (input[position] == '+' || input[position] == '-')) {
position++;
}
while (position < input.size() && isdigit(input[position])) {
position++;
}
isFloat = true;
}
string token = input.substr(start, position - start);
return isFloat ? Token(Token::FLOAT, token) : Token(Token::INTEGER, token);
}
// 辅助函数:识别字符常量
Token recognizeCharLiteral(const string& input, size_t& position) {
size_t start = position;
position++; // 跳过开头的单引号
while (position < input.size() && input[position] != '\'') {
position++;
}
position++; // 跳过结尾的单引号
string token = input.substr(start, position - start);
return Token(Token::CHAR_LITERAL, token);
}
// 辅助函数:识别字符串常量
Token recognizeStringLiteral(const string& input, size_t& position) {
size_t start = position;
position++; // 跳过开头的双引号
while (position < input.size() && input[position] != '"') {
if (input[position] == '\\') {
position++; // 跳过转义字符
}
position++;
}
position++; // 跳过结尾的双引号
string token = input.substr(start, position - start);
return Token(Token::STRING_LITERAL, token);
}
// 辅助函数:识别运算符
Token recognizeOperator(const string& input, size_t& position) {
size_t start = position;
size_t length = 1;
while (position + length < input.size() && operators.find(input.substr(position, length + 1)) != operators.end()) {
length++;
}
string token = input.substr(start, length);
position += length;
return Token(operators[token], token);
}
// 辅助函数:识别分隔符
Token recognizeDelimiter(const string& input, size_t& position) {
char c = input[position++];
return Token(delimiters[c], string(1, c));
}
// 主函数:词法分析器
vector<Token> lexicalAnalyzer(const string& input) {
vector<Token> tokens;
size_t position = 0;
while (position < input.size()) {
skipWhitespace(input, position);
if (position >= input.size()) {
break;
}
char currentChar = input[position];
if (isalpha(currentChar) || currentChar == '_') {
tokens.push_back(recognizeIdentifierOrKeyword(input, position));
} else if (isdigit(currentChar)) {
tokens.push_back(recognizeNumber(input, position));
} else if (currentChar == '\'') {
tokens.push_back(recognizeCharLiteral(input, position));
} else if (currentChar == '"') {
tokens.push_back(recognizeStringLiteral(input, position));
} else if (operators.find(string(1, currentChar)) != operators.end()) {
tokens.push_back(recognizeOperator(input, position));
} else if (delimiters.find(currentChar) != delimiters.end()) {
tokens.push_back(recognizeDelimiter(input, position));
} else {
tokens.push_back(Token(Token::UNKNOWN, string(1, currentChar)));
position++;
}
}
return tokens;
}
// 打印Token
void printTokens(const vector<Token>& tokens) {
for (const auto& token : tokens) {
cout << "Token Type: ";
switch (token.type) {
case Token::KEYWORD: cout << "KEYWORD"; break;
case Token::IDENTIFIER: cout << "IDENTIFIER"; break;
case Token::INTEGER: cout << "INTEGER"; break;
case Token::FLOAT: cout << "FLOAT"; break;
case Token::CHAR_LITERAL: cout << "CHAR_LITERAL"; break;
case Token::STRING_LITERAL: cout << "STRING_LITERAL"; break;
case Token::OPERATOR: cout << "OPERATOR"; break;
case Token::DELIMITER: cout << "DELIMITER"; break;
case Token::UNKNOWN: cout << "UNKNOWN"; break;
}
cout << ", Value: " << token.value << endl;
}
}
// 主程序
int main() {
string sourceCode;
cout << "请输入C++代码(输入`end`结束):\n";
while (true) {
string line;
getline(cin, line);
if (line == "end") break;
sourceCode += line + "\n";
}
vector<Token> tokens = lexicalAnalyzer(sourceCode);
printTokens(tokens);
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8dW5vcmRlcmVkX21hcD4KI2luY2x1ZGUgPGNjdHlwZT4KI2luY2x1ZGUgPHJlZ2V4PgoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCi8vIOWumuS5iVRva2Vu57uT5p6ECnN0cnVjdCBUb2tlbiB7CiAgICBlbnVtIFR5cGUgewogICAgICAgIEtFWVdPUkQsIElERU5USUZJRVIsIElOVEVHRVIsIEZMT0FULCBDSEFSX0xJVEVSQUwsIFNUUklOR19MSVRFUkFMLAogICAgICAgIE9QRVJBVE9SLCBERUxJTUlURVIsIFVOS05PV04KICAgIH07CgogICAgVHlwZSB0eXBlOyAgICAgICAvLyBUb2tlbueahOexu+WeiwogICAgc3RyaW5nIHZhbHVlOyAgICAvLyBUb2tlbueahOWAvAoKICAgIFRva2VuKFR5cGUgdCwgY29uc3Qgc3RyaW5nJiB2KSA6IHR5cGUodCksIHZhbHVlKHYpIHt9Cn07CgovLyDlhbPplK7lrZfmmKDlsITooagKdW5vcmRlcmVkX21hcDxzdHJpbmcsIFRva2VuOjpUeXBlPiBrZXl3b3JkcyA9IHsKICAgIHsiaW50IiwgVG9rZW46OktFWVdPUkR9LCB7ImRvdWJsZSIsIFRva2VuOjpLRVlXT1JEfSwgeyJjaGFyIiwgVG9rZW46OktFWVdPUkR9LCB7InN0cmluZyIsIFRva2VuOjpLRVlXT1JEfSwKICAgIHsiaWYiLCBUb2tlbjo6S0VZV09SRH0sIHsiZWxzZSIsIFRva2VuOjpLRVlXT1JEfSwgeyJ3aGlsZSIsIFRva2VuOjpLRVlXT1JEfSwgeyJmb3IiLCBUb2tlbjo6S0VZV09SRH0sCiAgICB7InJldHVybiIsIFRva2VuOjpLRVlXT1JEfSwgeyJ2b2lkIiwgVG9rZW46OktFWVdPUkR9LCB7InRydWUiLCBUb2tlbjo6S0VZV09SRH0sIHsiZmFsc2UiLCBUb2tlbjo6S0VZV09SRH0KfTsKCi8vIOWIhumalOespuaYoOWwhOihqAp1bm9yZGVyZWRfbWFwPGNoYXIsIFRva2VuOjpUeXBlPiBkZWxpbWl0ZXJzID0gewogICAgeycoJywgVG9rZW46OkRFTElNSVRFUn0sIHsnKScsIFRva2VuOjpERUxJTUlURVJ9LCB7J3snLCBUb2tlbjo6REVMSU1JVEVSfSwgeyd9JywgVG9rZW46OkRFTElNSVRFUn0sCiAgICB7J1snLCBUb2tlbjo6REVMSU1JVEVSfSwgeyddJywgVG9rZW46OkRFTElNSVRFUn0sIHsnLCcsIFRva2VuOjpERUxJTUlURVJ9LCB7Jy4nLCBUb2tlbjo6REVMSU1JVEVSfSwKICAgIHsnOycsIFRva2VuOjpERUxJTUlURVJ9LCB7JzonLCBUb2tlbjo6REVMSU1JVEVSfSwgeyc/JywgVG9rZW46OkRFTElNSVRFUn0sIHsnLT4nLCBUb2tlbjo6REVMSU1JVEVSfQp9OwoKLy8g6L+Q566X56ym5pig5bCE6KGoCnVub3JkZXJlZF9tYXA8c3RyaW5nLCBUb2tlbjo6VHlwZT4gb3BlcmF0b3JzID0gewogICAgeyIrIiwgVG9rZW46Ok9QRVJBVE9SfSwgeyItIiwgVG9rZW46Ok9QRVJBVE9SfSwgeyIqIiwgVG9rZW46Ok9QRVJBVE9SfSwgeyIvIiwgVG9rZW46Ok9QRVJBVE9SfSwKICAgIHsiJSIsIFRva2VuOjpPUEVSQVRPUn0sIHsiPSIsIFRva2VuOjpPUEVSQVRPUn0sIHsiPT0iLCBUb2tlbjo6T1BFUkFUT1J9LCB7IiE9IiwgVG9rZW46Ok9QRVJBVE9SfSwKICAgIHsiPCIsIFRva2VuOjpPUEVSQVRPUn0sIHsiPiIsIFRva2VuOjpPUEVSQVRPUn0sIHsiPD0iLCBUb2tlbjo6T1BFUkFUT1J9LCB7Ij49IiwgVG9rZW46Ok9QRVJBVE9SfSwKICAgIHsiJiYiLCBUb2tlbjo6T1BFUkFUT1J9LCB7Inx8IiwgVG9rZW46Ok9QRVJBVE9SfSwgeyIhIiwgVG9rZW46Ok9QRVJBVE9SfSwgeyIrKyIsIFRva2VuOjpPUEVSQVRPUn0sCiAgICB7Ii0tIiwgVG9rZW46Ok9QRVJBVE9SfQp9OwoKLy8g6L6F5Yqp5Ye95pWw77ya6Lez6L+H56m655m95a2X56ymCnZvaWQgc2tpcFdoaXRlc3BhY2UoY29uc3Qgc3RyaW5nJiBpbnB1dCwgc2l6ZV90JiBwb3NpdGlvbikgewogICAgd2hpbGUgKHBvc2l0aW9uIDwgaW5wdXQuc2l6ZSgpICYmIGlzc3BhY2UoaW5wdXRbcG9zaXRpb25dKSkgewogICAgICAgIHBvc2l0aW9uKys7CiAgICB9Cn0KCi8vIOi+heWKqeWHveaVsO+8muivhuWIq+agh+ivhuespuaIluWFs+mUruWtlwpUb2tlbiByZWNvZ25pemVJZGVudGlmaWVyT3JLZXl3b3JkKGNvbnN0IHN0cmluZyYgaW5wdXQsIHNpemVfdCYgcG9zaXRpb24pIHsKICAgIHNpemVfdCBzdGFydCA9IHBvc2l0aW9uOwogICAgd2hpbGUgKHBvc2l0aW9uIDwgaW5wdXQuc2l6ZSgpICYmIChpc2FsbnVtKGlucHV0W3Bvc2l0aW9uXSkgfHwgaW5wdXRbcG9zaXRpb25dID09ICdfJykpIHsKICAgICAgICBwb3NpdGlvbisrOwogICAgfQogICAgc3RyaW5nIHRva2VuID0gaW5wdXQuc3Vic3RyKHN0YXJ0LCBwb3NpdGlvbiAtIHN0YXJ0KTsKICAgIGlmIChrZXl3b3Jkcy5maW5kKHRva2VuKSAhPSBrZXl3b3Jkcy5lbmQoKSkgewogICAgICAgIHJldHVybiBUb2tlbihUb2tlbjo6S0VZV09SRCwgdG9rZW4pOwogICAgfQogICAgcmV0dXJuIFRva2VuKFRva2VuOjpJREVOVElGSUVSLCB0b2tlbik7Cn0KCi8vIOi+heWKqeWHveaVsO+8muivhuWIq+aVtOaVsOaIlua1rueCueaVsApUb2tlbiByZWNvZ25pemVOdW1iZXIoY29uc3Qgc3RyaW5nJiBpbnB1dCwgc2l6ZV90JiBwb3NpdGlvbikgewogICAgc2l6ZV90IHN0YXJ0ID0gcG9zaXRpb247CiAgICBib29sIGlzRmxvYXQgPSBmYWxzZTsKCiAgICB3aGlsZSAocG9zaXRpb24gPCBpbnB1dC5zaXplKCkgJiYgaXNkaWdpdChpbnB1dFtwb3NpdGlvbl0pKSB7CiAgICAgICAgcG9zaXRpb24rKzsKICAgIH0KCiAgICBpZiAocG9zaXRpb24gPCBpbnB1dC5zaXplKCkgJiYgaW5wdXRbcG9zaXRpb25dID09ICcuJykgewogICAgICAgIHBvc2l0aW9uKys7CiAgICAgICAgaXNGbG9hdCA9IHRydWU7CiAgICAgICAgd2hpbGUgKHBvc2l0aW9uIDwgaW5wdXQuc2l6ZSgpICYmIGlzZGlnaXQoaW5wdXRbcG9zaXRpb25dKSkgewogICAgICAgICAgICBwb3NpdGlvbisrOwogICAgICAgIH0KICAgIH0KCiAgICBpZiAocG9zaXRpb24gPCBpbnB1dC5zaXplKCkgJiYgKGlucHV0W3Bvc2l0aW9uXSA9PSAnZScgfHwgaW5wdXRbcG9zaXRpb25dID09ICdFJykpIHsKICAgICAgICBwb3NpdGlvbisrOwogICAgICAgIGlmIChwb3NpdGlvbiA8IGlucHV0LnNpemUoKSAmJiAoaW5wdXRbcG9zaXRpb25dID09ICcrJyB8fCBpbnB1dFtwb3NpdGlvbl0gPT0gJy0nKSkgewogICAgICAgICAgICBwb3NpdGlvbisrOwogICAgICAgIH0KICAgICAgICB3aGlsZSAocG9zaXRpb24gPCBpbnB1dC5zaXplKCkgJiYgaXNkaWdpdChpbnB1dFtwb3NpdGlvbl0pKSB7CiAgICAgICAgICAgIHBvc2l0aW9uKys7CiAgICAgICAgfQogICAgICAgIGlzRmxvYXQgPSB0cnVlOwogICAgfQoKICAgIHN0cmluZyB0b2tlbiA9IGlucHV0LnN1YnN0cihzdGFydCwgcG9zaXRpb24gLSBzdGFydCk7CiAgICByZXR1cm4gaXNGbG9hdCA/IFRva2VuKFRva2VuOjpGTE9BVCwgdG9rZW4pIDogVG9rZW4oVG9rZW46OklOVEVHRVIsIHRva2VuKTsKfQoKLy8g6L6F5Yqp5Ye95pWw77ya6K+G5Yir5a2X56ym5bi46YePClRva2VuIHJlY29nbml6ZUNoYXJMaXRlcmFsKGNvbnN0IHN0cmluZyYgaW5wdXQsIHNpemVfdCYgcG9zaXRpb24pIHsKICAgIHNpemVfdCBzdGFydCA9IHBvc2l0aW9uOwogICAgcG9zaXRpb24rKzsgIC8vIOi3s+i/h+W8gOWktOeahOWNleW8leWPtwogICAgd2hpbGUgKHBvc2l0aW9uIDwgaW5wdXQuc2l6ZSgpICYmIGlucHV0W3Bvc2l0aW9uXSAhPSAnXCcnKSB7CiAgICAgICAgcG9zaXRpb24rKzsKICAgIH0KICAgIHBvc2l0aW9uKys7ICAvLyDot7Pov4fnu5PlsL7nmoTljZXlvJXlj7cKICAgIHN0cmluZyB0b2tlbiA9IGlucHV0LnN1YnN0cihzdGFydCwgcG9zaXRpb24gLSBzdGFydCk7CiAgICByZXR1cm4gVG9rZW4oVG9rZW46OkNIQVJfTElURVJBTCwgdG9rZW4pOwp9CgovLyDovoXliqnlh73mlbDvvJror4bliKvlrZfnrKbkuLLluLjph48KVG9rZW4gcmVjb2duaXplU3RyaW5nTGl0ZXJhbChjb25zdCBzdHJpbmcmIGlucHV0LCBzaXplX3QmIHBvc2l0aW9uKSB7CiAgICBzaXplX3Qgc3RhcnQgPSBwb3NpdGlvbjsKICAgIHBvc2l0aW9uKys7ICAvLyDot7Pov4flvIDlpLTnmoTlj4zlvJXlj7cKICAgIHdoaWxlIChwb3NpdGlvbiA8IGlucHV0LnNpemUoKSAmJiBpbnB1dFtwb3NpdGlvbl0gIT0gJyInKSB7CiAgICAgICAgaWYgKGlucHV0W3Bvc2l0aW9uXSA9PSAnXFwnKSB7CiAgICAgICAgICAgIHBvc2l0aW9uKys7ICAvLyDot7Pov4fovazkuYnlrZfnrKYKICAgICAgICB9CiAgICAgICAgcG9zaXRpb24rKzsKICAgIH0KICAgIHBvc2l0aW9uKys7ICAvLyDot7Pov4fnu5PlsL7nmoTlj4zlvJXlj7cKICAgIHN0cmluZyB0b2tlbiA9IGlucHV0LnN1YnN0cihzdGFydCwgcG9zaXRpb24gLSBzdGFydCk7CiAgICByZXR1cm4gVG9rZW4oVG9rZW46OlNUUklOR19MSVRFUkFMLCB0b2tlbik7Cn0KCi8vIOi+heWKqeWHveaVsO+8muivhuWIq+i/kOeul+espgpUb2tlbiByZWNvZ25pemVPcGVyYXRvcihjb25zdCBzdHJpbmcmIGlucHV0LCBzaXplX3QmIHBvc2l0aW9uKSB7CiAgICBzaXplX3Qgc3RhcnQgPSBwb3NpdGlvbjsKICAgIHNpemVfdCBsZW5ndGggPSAxOwoKICAgIHdoaWxlIChwb3NpdGlvbiArIGxlbmd0aCA8IGlucHV0LnNpemUoKSAmJiBvcGVyYXRvcnMuZmluZChpbnB1dC5zdWJzdHIocG9zaXRpb24sIGxlbmd0aCArIDEpKSAhPSBvcGVyYXRvcnMuZW5kKCkpIHsKICAgICAgICBsZW5ndGgrKzsKICAgIH0KCiAgICBzdHJpbmcgdG9rZW4gPSBpbnB1dC5zdWJzdHIoc3RhcnQsIGxlbmd0aCk7CiAgICBwb3NpdGlvbiArPSBsZW5ndGg7CiAgICByZXR1cm4gVG9rZW4ob3BlcmF0b3JzW3Rva2VuXSwgdG9rZW4pOwp9CgovLyDovoXliqnlh73mlbDvvJror4bliKvliIbpmpTnrKYKVG9rZW4gcmVjb2duaXplRGVsaW1pdGVyKGNvbnN0IHN0cmluZyYgaW5wdXQsIHNpemVfdCYgcG9zaXRpb24pIHsKICAgIGNoYXIgYyA9IGlucHV0W3Bvc2l0aW9uKytdOwogICAgcmV0dXJuIFRva2VuKGRlbGltaXRlcnNbY10sIHN0cmluZygxLCBjKSk7Cn0KCi8vIOS4u+WHveaVsO+8muivjeazleWIhuaekOWZqAp2ZWN0b3I8VG9rZW4+IGxleGljYWxBbmFseXplcihjb25zdCBzdHJpbmcmIGlucHV0KSB7CiAgICB2ZWN0b3I8VG9rZW4+IHRva2VuczsKICAgIHNpemVfdCBwb3NpdGlvbiA9IDA7CgogICAgd2hpbGUgKHBvc2l0aW9uIDwgaW5wdXQuc2l6ZSgpKSB7CiAgICAgICAgc2tpcFdoaXRlc3BhY2UoaW5wdXQsIHBvc2l0aW9uKTsKCiAgICAgICAgaWYgKHBvc2l0aW9uID49IGlucHV0LnNpemUoKSkgewogICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgICAgIGNoYXIgY3VycmVudENoYXIgPSBpbnB1dFtwb3NpdGlvbl07CgogICAgICAgIGlmIChpc2FscGhhKGN1cnJlbnRDaGFyKSB8fCBjdXJyZW50Q2hhciA9PSAnXycpIHsKICAgICAgICAgICAgdG9rZW5zLnB1c2hfYmFjayhyZWNvZ25pemVJZGVudGlmaWVyT3JLZXl3b3JkKGlucHV0LCBwb3NpdGlvbikpOwogICAgICAgIH0gZWxzZSBpZiAoaXNkaWdpdChjdXJyZW50Q2hhcikpIHsKICAgICAgICAgICAgdG9rZW5zLnB1c2hfYmFjayhyZWNvZ25pemVOdW1iZXIoaW5wdXQsIHBvc2l0aW9uKSk7CiAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50Q2hhciA9PSAnXCcnKSB7CiAgICAgICAgICAgIHRva2Vucy5wdXNoX2JhY2socmVjb2duaXplQ2hhckxpdGVyYWwoaW5wdXQsIHBvc2l0aW9uKSk7CiAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50Q2hhciA9PSAnIicpIHsKICAgICAgICAgICAgdG9rZW5zLnB1c2hfYmFjayhyZWNvZ25pemVTdHJpbmdMaXRlcmFsKGlucHV0LCBwb3NpdGlvbikpOwogICAgICAgIH0gZWxzZSBpZiAob3BlcmF0b3JzLmZpbmQoc3RyaW5nKDEsIGN1cnJlbnRDaGFyKSkgIT0gb3BlcmF0b3JzLmVuZCgpKSB7CiAgICAgICAgICAgIHRva2Vucy5wdXNoX2JhY2socmVjb2duaXplT3BlcmF0b3IoaW5wdXQsIHBvc2l0aW9uKSk7CiAgICAgICAgfSBlbHNlIGlmIChkZWxpbWl0ZXJzLmZpbmQoY3VycmVudENoYXIpICE9IGRlbGltaXRlcnMuZW5kKCkpIHsKICAgICAgICAgICAgdG9rZW5zLnB1c2hfYmFjayhyZWNvZ25pemVEZWxpbWl0ZXIoaW5wdXQsIHBvc2l0aW9uKSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdG9rZW5zLnB1c2hfYmFjayhUb2tlbihUb2tlbjo6VU5LTk9XTiwgc3RyaW5nKDEsIGN1cnJlbnRDaGFyKSkpOwogICAgICAgICAgICBwb3NpdGlvbisrOwogICAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gdG9rZW5zOwp9CgovLyDmiZPljbBUb2tlbgp2b2lkIHByaW50VG9rZW5zKGNvbnN0IHZlY3RvcjxUb2tlbj4mIHRva2VucykgewogICAgZm9yIChjb25zdCBhdXRvJiB0b2tlbiA6IHRva2VucykgewogICAgICAgIGNvdXQgPDwgIlRva2VuIFR5cGU6ICI7CiAgICAgICAgc3dpdGNoICh0b2tlbi50eXBlKSB7CiAgICAgICAgICAgIGNhc2UgVG9rZW46OktFWVdPUkQ6IGNvdXQgPDwgIktFWVdPUkQiOyBicmVhazsKICAgICAgICAgICAgY2FzZSBUb2tlbjo6SURFTlRJRklFUjogY291dCA8PCAiSURFTlRJRklFUiI7IGJyZWFrOwogICAgICAgICAgICBjYXNlIFRva2VuOjpJTlRFR0VSOiBjb3V0IDw8ICJJTlRFR0VSIjsgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgVG9rZW46OkZMT0FUOiBjb3V0IDw8ICJGTE9BVCI7IGJyZWFrOwogICAgICAgICAgICBjYXNlIFRva2VuOjpDSEFSX0xJVEVSQUw6IGNvdXQgPDwgIkNIQVJfTElURVJBTCI7IGJyZWFrOwogICAgICAgICAgICBjYXNlIFRva2VuOjpTVFJJTkdfTElURVJBTDogY291dCA8PCAiU1RSSU5HX0xJVEVSQUwiOyBicmVhazsKICAgICAgICAgICAgY2FzZSBUb2tlbjo6T1BFUkFUT1I6IGNvdXQgPDwgIk9QRVJBVE9SIjsgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgVG9rZW46OkRFTElNSVRFUjogY291dCA8PCAiREVMSU1JVEVSIjsgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgVG9rZW46OlVOS05PV046IGNvdXQgPDwgIlVOS05PV04iOyBicmVhazsKICAgICAgICB9CiAgICAgICAgY291dCA8PCAiLCBWYWx1ZTogIiA8PCB0b2tlbi52YWx1ZSA8PCBlbmRsOwogICAgfQp9CgovLyDkuLvnqIvluo8KaW50IG1haW4oKSB7CiAgICBzdHJpbmcgc291cmNlQ29kZTsKICAgIGNvdXQgPDwgIuivt+i+k+WFpUMrK+S7o+egge+8iOi+k+WFpWBlbmRg57uT5p2f77yJ77yaXG4iOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgICBzdHJpbmcgbGluZTsKICAgICAgICBnZXRsaW5lKGNpbiwgbGluZSk7CiAgICAgICAgaWYgKGxpbmUgPT0gImVuZCIpIGJyZWFrOwogICAgICAgIHNvdXJjZUNvZGUgKz0gbGluZSArICJcbiI7CiAgICB9CgogICAgdmVjdG9yPFRva2VuPiB0b2tlbnMgPSBsZXhpY2FsQW5hbHl6ZXIoc291cmNlQ29kZSk7CiAgICBwcmludFRva2Vucyh0b2tlbnMpOwoKICAgIHJldHVybiAwOwp9Cg==