#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_ID 1024
#define MAX_TYPES 64
#define MAX_TOKENS 65536
typedef enum {
T_IDENT, T_KEYWORD, T_INT_LIT, T_STR_LIT,
T_OP, T_DELIM, T_LPAREN, T_RPAREN,
T_LBRACK, T_RBRACK, T_LBRACE, T_RBRACE,
T_BOOL_LIT
} TokenClass;
const char* className[] = {
"IDENT","KEYWORD","INT_LIT","STR_LIT",
"OP","DELIM","LPAREN","RPAREN",
"LBRACK","RBRACK","LBRACE","RBRACE",
"BOOL_LIT"
};
const char* keywords[] = {
"list","add","remove","print","if","else","while","for",
"function","return","int","string","bool",
"length","concat","reverse"
};
const int KW_COUNT = 16;
typedef struct { char name[128]; } Ident;
typedef struct { char name[32]; } Type;
Ident idTable[MAX_ID]; int idCount=0;
Type typeTable[MAX_TYPES]; int typeCount=0;
typedef struct {
TokenClass cls;
int indexInClass;
int row, col;
char lexeme[128];
int stmtNo;
int nesting;
} Token;
Token tokens[MAX_TOKENS]; int tokCount=0;
int isKeyword(const char* s) {
for (int i
=0;i
<KW_COUNT
;i
++) if (!strcmp(s
, keywords
[i
])) return 1; return 0;
}
int isBoolLiteral
(const char* s
){ return (!strcmp(s
,"true")||!strcmp(s
,"false")); }
int addIdent(const char* s){
for (int i
=0;i
<idCount
;i
++) if(!strcmp(idTable
[i
].
name,s
)) return i
+1; strcpy(idTable
[idCount
].
name,s
); idCount
++; return idCount
; }
int ensureType(const char* s){
for (int i
=0;i
<typeCount
;i
++) if(!strcmp(typeTable
[i
].
name,s
)) return i
+1; strcpy(typeTable
[typeCount
].
name,s
); typeCount
++; return typeCount
; }
void emit(TokenClass c, int idx, int row, int col, const char* lex, int stmt, int nest){
tokens[tokCount].cls=c;
tokens[tokCount].indexInClass=idx;
tokens[tokCount].row=row;
tokens[tokCount].col=col;
tokens[tokCount].stmtNo=stmt;
tokens[tokCount].nesting=nest;
strncpy(tokens
[tokCount
].
lexeme, lex
, 127); tokCount++;
}
int main(int argc, char** argv){
// Заповнюємо таблицю типів базовими типами
ensureType("int"); ensureType("string");
ensureType("bool"); ensureType("list");
FILE* f = stdin;
if (argc
>1){ f
=fopen(argv
[1],"r"); if(!f
){ perror("open"); return 1; } }
int row=1,col=0;
int c, peek;
char buf[256];
int stmtNo=0, nesting=0;
while ((c
=fgetc(f
))!=EOF
){ if (c=='\n'){ row++; col=0; continue; }
col++;
// Коментарі
if (c=='/'){
if (peek
=='/'){ while((c
=fgetc(f
))!=EOF
&& c
!='\n'); row
++; col
=0; continue; } else if (peek=='*'){ int prev=0;
while((c
=fgetc(f
))!=EOF
){ if(c
=='\n'){ row
++; col
=0; } if(prev=='*' && c=='/') break; prev=c; }
continue;
}
// Ідентифікатор / ключове слово / булевий літерал
int k=0; buf[k++]=(char)c;
buf[k++]=(char)peek;
}
if (peek
!=EOF
) ungetc(peek
,f
); buf[k]='\0';
if (isBoolLiteral(buf)){
emit(T_BOOL_LIT,0,row,col-k+1,buf,stmtNo,nesting);
} else if (isKeyword(buf)){
emit(T_KEYWORD,0,row,col-k+1,buf,stmtNo,nesting);
} else {
int id=addIdent(buf);
emit(T_IDENT,id,row,col-k+1,buf,stmtNo,nesting);
}
continue;
}
// Ціле число
int k=0; buf[k++]=(char)c;
while((peek
=fgetc(f
))!=EOF
&& isdigit(peek
)) buf
[k
++]=(char)peek
; if (peek
!=EOF
) ungetc(peek
,f
); buf[k]='\0';
emit
(T_INT_LIT
,0,row
,col
-strlen(buf
)+1,buf
,stmtNo
,nesting
); continue;
}
// Рядок
if (c=='"'){
int k=0; int startCol=col; int closed=0;
while((peek
=fgetc(f
))!=EOF
){ col++;
if (peek=='\n'){ row++; col=0; }
if (peek=='"'){ closed=1; break; }
buf[k++]=(char)peek;
}
buf[k]='\0';
if (!closed
) fprintf(stderr
,"LEXERR: Unterminated string at %d:%d\n",row
,startCol
); else emit(T_STR_LIT,0,row,startCol,buf,stmtNo,nesting);
continue;
}
// Оператори, дужки, роздільники
buf[0]=(char)c; buf[1]='\0';
switch(c){
case '+': case '-': case '*': case '/': case '=':
case '<': case '>': emit(T_OP,0,row,col,buf,stmtNo,nesting); break;
case ',': case ';':
emit(T_DELIM,0,row,col,buf,stmtNo,nesting);
if(c==';') stmtNo++; break;
case '(': emit(T_LPAREN,0,row,col,buf,stmtNo,nesting); break;
case ')': emit(T_RPAREN,0,row,col,buf,stmtNo,nesting); break;
case '[': emit(T_LBRACK,0,row,col,buf,stmtNo,nesting); break;
case ']': emit(T_RBRACK,0,row,col,buf,stmtNo,nesting); break;
case '{': nesting++; emit(T_LBRACE,0,row,col,buf,stmtNo,nesting); break;
case '}': emit(T_RBRACE,0,row,col,buf,stmtNo,nesting); nesting--; break;
default: fprintf(stderr
,"LEXERR: Unknown symbol '%c' at %d:%d\n",c
,row
,col
); }
}
// Вивід результатів
printf("=== а) Реорганізований текст ===\n"); for(int i=0;i<tokCount;i++)
printf("(%s,%d) ", className
[tokens
[i
].
cls], tokens
[i
].
indexInClass); printf("\n\n=== б) Таблиця ідентифікаторів ===\n"); for(int i
=0;i
<idCount
;i
++) printf("%3d : %s\n", i
+1, idTable
[i
].
name); printf("\n=== Таблиця типів ===\n"); for(int i
=0;i
<typeCount
;i
++) printf("%3d : %s\n", i
+1, typeTable
[i
].
name);
printf("\n=== в) Листинг трансляції ===\n"); for(int i=0;i<tokCount;i++)
printf("[line %d,col %d] %-8s %-10s (stmt %d, nest %d)\n", tokens[i].row,tokens[i].col,
className[tokens[i].cls],tokens[i].lexeme,
tokens[i].stmtNo,tokens[i].nesting);
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8Y3R5cGUuaD4KCiNkZWZpbmUgTUFYX0lEIDEwMjQKI2RlZmluZSBNQVhfVFlQRVMgNjQKI2RlZmluZSBNQVhfVE9LRU5TIDY1NTM2Cgp0eXBlZGVmIGVudW0gewogICAgVF9JREVOVCwgVF9LRVlXT1JELCBUX0lOVF9MSVQsIFRfU1RSX0xJVCwKICAgIFRfT1AsIFRfREVMSU0sIFRfTFBBUkVOLCBUX1JQQVJFTiwKICAgIFRfTEJSQUNLLCBUX1JCUkFDSywgVF9MQlJBQ0UsIFRfUkJSQUNFLAogICAgVF9CT09MX0xJVAp9IFRva2VuQ2xhc3M7Cgpjb25zdCBjaGFyKiBjbGFzc05hbWVbXSA9IHsKICAgICJJREVOVCIsIktFWVdPUkQiLCJJTlRfTElUIiwiU1RSX0xJVCIsCiAgICAiT1AiLCJERUxJTSIsIkxQQVJFTiIsIlJQQVJFTiIsCiAgICAiTEJSQUNLIiwiUkJSQUNLIiwiTEJSQUNFIiwiUkJSQUNFIiwKICAgICJCT09MX0xJVCIKfTsKCmNvbnN0IGNoYXIqIGtleXdvcmRzW10gPSB7CiAgICAibGlzdCIsImFkZCIsInJlbW92ZSIsInByaW50IiwiaWYiLCJlbHNlIiwid2hpbGUiLCJmb3IiLAogICAgImZ1bmN0aW9uIiwicmV0dXJuIiwiaW50Iiwic3RyaW5nIiwiYm9vbCIsCiAgICAibGVuZ3RoIiwiY29uY2F0IiwicmV2ZXJzZSIKfTsKY29uc3QgaW50IEtXX0NPVU5UID0gMTY7Cgp0eXBlZGVmIHN0cnVjdCB7IGNoYXIgbmFtZVsxMjhdOyB9IElkZW50Owp0eXBlZGVmIHN0cnVjdCB7IGNoYXIgbmFtZVszMl07IH0gVHlwZTsKCklkZW50IGlkVGFibGVbTUFYX0lEXTsgaW50IGlkQ291bnQ9MDsKVHlwZSB0eXBlVGFibGVbTUFYX1RZUEVTXTsgaW50IHR5cGVDb3VudD0wOwoKdHlwZWRlZiBzdHJ1Y3QgewogICAgVG9rZW5DbGFzcyBjbHM7CiAgICBpbnQgaW5kZXhJbkNsYXNzOwogICAgaW50IHJvdywgY29sOwogICAgY2hhciBsZXhlbWVbMTI4XTsKICAgIGludCBzdG10Tm87CiAgICBpbnQgbmVzdGluZzsKfSBUb2tlbjsKClRva2VuIHRva2Vuc1tNQVhfVE9LRU5TXTsgaW50IHRva0NvdW50PTA7CgppbnQgaXNLZXl3b3JkKGNvbnN0IGNoYXIqIHMpIHsKICAgIGZvciAoaW50IGk9MDtpPEtXX0NPVU5UO2krKykgaWYgKCFzdHJjbXAocywga2V5d29yZHNbaV0pKSByZXR1cm4gMTsKICAgIHJldHVybiAwOwp9CmludCBpc0Jvb2xMaXRlcmFsKGNvbnN0IGNoYXIqIHMpeyByZXR1cm4gKCFzdHJjbXAocywidHJ1ZSIpfHwhc3RyY21wKHMsImZhbHNlIikpOyB9CgppbnQgYWRkSWRlbnQoY29uc3QgY2hhciogcyl7CiAgICBmb3IgKGludCBpPTA7aTxpZENvdW50O2krKykgaWYoIXN0cmNtcChpZFRhYmxlW2ldLm5hbWUscykpIHJldHVybiBpKzE7CiAgICBzdHJjcHkoaWRUYWJsZVtpZENvdW50XS5uYW1lLHMpOyBpZENvdW50Kys7IHJldHVybiBpZENvdW50Owp9CmludCBlbnN1cmVUeXBlKGNvbnN0IGNoYXIqIHMpewogICAgZm9yIChpbnQgaT0wO2k8dHlwZUNvdW50O2krKykgaWYoIXN0cmNtcCh0eXBlVGFibGVbaV0ubmFtZSxzKSkgcmV0dXJuIGkrMTsKICAgIHN0cmNweSh0eXBlVGFibGVbdHlwZUNvdW50XS5uYW1lLHMpOyB0eXBlQ291bnQrKzsgcmV0dXJuIHR5cGVDb3VudDsKfQoKdm9pZCBlbWl0KFRva2VuQ2xhc3MgYywgaW50IGlkeCwgaW50IHJvdywgaW50IGNvbCwgY29uc3QgY2hhciogbGV4LCBpbnQgc3RtdCwgaW50IG5lc3QpewogICAgdG9rZW5zW3Rva0NvdW50XS5jbHM9YzsKICAgIHRva2Vuc1t0b2tDb3VudF0uaW5kZXhJbkNsYXNzPWlkeDsKICAgIHRva2Vuc1t0b2tDb3VudF0ucm93PXJvdzsKICAgIHRva2Vuc1t0b2tDb3VudF0uY29sPWNvbDsKICAgIHRva2Vuc1t0b2tDb3VudF0uc3RtdE5vPXN0bXQ7CiAgICB0b2tlbnNbdG9rQ291bnRdLm5lc3Rpbmc9bmVzdDsKICAgIHN0cm5jcHkodG9rZW5zW3Rva0NvdW50XS5sZXhlbWUsIGxleCwgMTI3KTsKICAgIHRva0NvdW50Kys7Cn0KCmludCBtYWluKGludCBhcmdjLCBjaGFyKiogYXJndil7CiAgICAvLyDQl9Cw0L/QvtCy0L3RjtGU0LzQviDRgtCw0LHQu9C40YbRjiDRgtC40L/RltCyINCx0LDQt9C+0LLQuNC80Lgg0YLQuNC/0LDQvNC4CiAgICBlbnN1cmVUeXBlKCJpbnQiKTsgZW5zdXJlVHlwZSgic3RyaW5nIik7CiAgICBlbnN1cmVUeXBlKCJib29sIik7IGVuc3VyZVR5cGUoImxpc3QiKTsKCiAgICBGSUxFKiBmID0gc3RkaW47CiAgICBpZiAoYXJnYz4xKXsgZj1mb3Blbihhcmd2WzFdLCJyIik7IGlmKCFmKXsgcGVycm9yKCJvcGVuIik7IHJldHVybiAxOyB9IH0KCiAgICBpbnQgcm93PTEsY29sPTA7CiAgICBpbnQgYywgcGVlazsKICAgIGNoYXIgYnVmWzI1Nl07CiAgICBpbnQgc3RtdE5vPTAsIG5lc3Rpbmc9MDsKCiAgICB3aGlsZSAoKGM9ZmdldGMoZikpIT1FT0YpewogICAgICAgIGlmIChjPT0nXG4nKXsgcm93Kys7IGNvbD0wOyBjb250aW51ZTsgfQogICAgICAgIGNvbCsrOwogICAgICAgIGlmIChpc3NwYWNlKGMpKSBjb250aW51ZTsKCiAgICAgICAgLy8g0JrQvtC80LXQvdGC0LDRgNGWCiAgICAgICAgaWYgKGM9PScvJyl7CiAgICAgICAgICAgIHBlZWs9ZmdldGMoZik7CiAgICAgICAgICAgIGlmIChwZWVrPT0nLycpeyB3aGlsZSgoYz1mZ2V0YyhmKSkhPUVPRiAmJiBjIT0nXG4nKTsgcm93Kys7IGNvbD0wOyBjb250aW51ZTsgfQogICAgICAgICAgICBlbHNlIGlmIChwZWVrPT0nKicpeyBpbnQgcHJldj0wOwogICAgICAgICAgICAgICAgd2hpbGUoKGM9ZmdldGMoZikpIT1FT0YpeyBpZihjPT0nXG4nKXsgcm93Kys7IGNvbD0wOyB9CiAgICAgICAgICAgICAgICAgICAgaWYocHJldj09JyonICYmIGM9PScvJykgYnJlYWs7IHByZXY9YzsgfQogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0gZWxzZSB7IHVuZ2V0YyhwZWVrLGYpOyB9CiAgICAgICAgfQoKICAgICAgICAvLyDQhtC00LXQvdGC0LjRhNGW0LrQsNGC0L7RgCAvINC60LvRjtGH0L7QstC1INGB0LvQvtCy0L4gLyDQsdGD0LvQtdCy0LjQuSDQu9GW0YLQtdGA0LDQuwogICAgICAgIGlmIChpc2FscGhhKGMpfHxjPT0nXycpewogICAgICAgICAgICBpbnQgaz0wOyBidWZbaysrXT0oY2hhciljOwogICAgICAgICAgICB3aGlsZSgocGVlaz1mZ2V0YyhmKSkhPUVPRiAmJiAoaXNhbG51bShwZWVrKXx8cGVlaz09J18nKSl7CiAgICAgICAgICAgICAgICBidWZbaysrXT0oY2hhcilwZWVrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChwZWVrIT1FT0YpIHVuZ2V0YyhwZWVrLGYpOwogICAgICAgICAgICBidWZba109J1wwJzsKICAgICAgICAgICAgaWYgKGlzQm9vbExpdGVyYWwoYnVmKSl7CiAgICAgICAgICAgICAgICBlbWl0KFRfQk9PTF9MSVQsMCxyb3csY29sLWsrMSxidWYsc3RtdE5vLG5lc3RpbmcpOwogICAgICAgICAgICB9IGVsc2UgaWYgKGlzS2V5d29yZChidWYpKXsKICAgICAgICAgICAgICAgIGlmICghc3RyY21wKGJ1ZiwiaW50Iil8fCFzdHJjbXAoYnVmLCJzdHJpbmciKXx8CiAgICAgICAgICAgICAgICAgICAgIXN0cmNtcChidWYsImJvb2wiKXx8IXN0cmNtcChidWYsImxpc3QiKSkgZW5zdXJlVHlwZShidWYpOwogICAgICAgICAgICAgICAgZW1pdChUX0tFWVdPUkQsMCxyb3csY29sLWsrMSxidWYsc3RtdE5vLG5lc3RpbmcpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgaW50IGlkPWFkZElkZW50KGJ1Zik7CiAgICAgICAgICAgICAgICBlbWl0KFRfSURFTlQsaWQscm93LGNvbC1rKzEsYnVmLHN0bXRObyxuZXN0aW5nKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIC8vINCm0ZbQu9C1INGH0LjRgdC70L4KICAgICAgICBpZiAoaXNkaWdpdChjKSl7CiAgICAgICAgICAgIGludCBrPTA7IGJ1ZltrKytdPShjaGFyKWM7CiAgICAgICAgICAgIHdoaWxlKChwZWVrPWZnZXRjKGYpKSE9RU9GICYmIGlzZGlnaXQocGVlaykpIGJ1ZltrKytdPShjaGFyKXBlZWs7CiAgICAgICAgICAgIGlmIChwZWVrIT1FT0YpIHVuZ2V0YyhwZWVrLGYpOwogICAgICAgICAgICBidWZba109J1wwJzsKICAgICAgICAgICAgZW1pdChUX0lOVF9MSVQsMCxyb3csY29sLXN0cmxlbihidWYpKzEsYnVmLHN0bXRObyxuZXN0aW5nKTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgfQoKICAgICAgICAvLyDQoNGP0LTQvtC6CiAgICAgICAgaWYgKGM9PSciJyl7CiAgICAgICAgICAgIGludCBrPTA7IGludCBzdGFydENvbD1jb2w7IGludCBjbG9zZWQ9MDsKICAgICAgICAgICAgd2hpbGUoKHBlZWs9ZmdldGMoZikpIT1FT0YpewogICAgICAgICAgICAgICAgY29sKys7CiAgICAgICAgICAgICAgICBpZiAocGVlaz09J1xuJyl7IHJvdysrOyBjb2w9MDsgfQogICAgICAgICAgICAgICAgaWYgKHBlZWs9PSciJyl7IGNsb3NlZD0xOyBicmVhazsgfQogICAgICAgICAgICAgICAgYnVmW2srK109KGNoYXIpcGVlazsKICAgICAgICAgICAgfQogICAgICAgICAgICBidWZba109J1wwJzsKICAgICAgICAgICAgaWYgKCFjbG9zZWQpIGZwcmludGYoc3RkZXJyLCJMRVhFUlI6IFVudGVybWluYXRlZCBzdHJpbmcgYXQgJWQ6JWRcbiIscm93LHN0YXJ0Q29sKTsKICAgICAgICAgICAgZWxzZSBlbWl0KFRfU1RSX0xJVCwwLHJvdyxzdGFydENvbCxidWYsc3RtdE5vLG5lc3RpbmcpOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIC8vINCe0L/QtdGA0LDRgtC+0YDQuCwg0LTRg9C20LrQuCwg0YDQvtC30LTRltC70YzQvdC40LrQuAogICAgICAgIGJ1ZlswXT0oY2hhciljOyBidWZbMV09J1wwJzsKICAgICAgICBzd2l0Y2goYyl7CiAgICAgICAgICAgIGNhc2UgJysnOiBjYXNlICctJzogY2FzZSAnKic6IGNhc2UgJy8nOiBjYXNlICc9JzoKICAgICAgICAgICAgY2FzZSAnPCc6IGNhc2UgJz4nOiBlbWl0KFRfT1AsMCxyb3csY29sLGJ1ZixzdG10Tm8sbmVzdGluZyk7IGJyZWFrOwogICAgICAgICAgICBjYXNlICcsJzogY2FzZSAnOyc6CiAgICAgICAgICAgICAgICBlbWl0KFRfREVMSU0sMCxyb3csY29sLGJ1ZixzdG10Tm8sbmVzdGluZyk7CiAgICAgICAgICAgICAgICBpZihjPT0nOycpIHN0bXRObysrOyBicmVhazsKICAgICAgICAgICAgY2FzZSAnKCc6IGVtaXQoVF9MUEFSRU4sMCxyb3csY29sLGJ1ZixzdG10Tm8sbmVzdGluZyk7IGJyZWFrOwogICAgICAgICAgICBjYXNlICcpJzogZW1pdChUX1JQQVJFTiwwLHJvdyxjb2wsYnVmLHN0bXRObyxuZXN0aW5nKTsgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgJ1snOiBlbWl0KFRfTEJSQUNLLDAscm93LGNvbCxidWYsc3RtdE5vLG5lc3RpbmcpOyBicmVhazsKICAgICAgICAgICAgY2FzZSAnXSc6IGVtaXQoVF9SQlJBQ0ssMCxyb3csY29sLGJ1ZixzdG10Tm8sbmVzdGluZyk7IGJyZWFrOwogICAgICAgICAgICBjYXNlICd7JzogbmVzdGluZysrOyBlbWl0KFRfTEJSQUNFLDAscm93LGNvbCxidWYsc3RtdE5vLG5lc3RpbmcpOyBicmVhazsKICAgICAgICAgICAgY2FzZSAnfSc6IGVtaXQoVF9SQlJBQ0UsMCxyb3csY29sLGJ1ZixzdG10Tm8sbmVzdGluZyk7IG5lc3RpbmctLTsgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6IGZwcmludGYoc3RkZXJyLCJMRVhFUlI6IFVua25vd24gc3ltYm9sICclYycgYXQgJWQ6JWRcbiIsYyxyb3csY29sKTsKICAgICAgICB9CiAgICB9CgogICAgLy8g0JLQuNCy0ZbQtCDRgNC10LfRg9C70YzRgtCw0YLRltCyCiAgICBwcmludGYoIj09PSDQsCkg0KDQtdC+0YDQs9Cw0L3RltC30L7QstCw0L3QuNC5INGC0LXQutGB0YIgPT09XG4iKTsKICAgIGZvcihpbnQgaT0wO2k8dG9rQ291bnQ7aSsrKQogICAgICAgIHByaW50ZigiKCVzLCVkKSAiLCBjbGFzc05hbWVbdG9rZW5zW2ldLmNsc10sIHRva2Vuc1tpXS5pbmRleEluQ2xhc3MpOwogICAgcHJpbnRmKCJcblxuPT09INCxKSDQotCw0LHQu9C40YbRjyDRltC00LXQvdGC0LjRhNGW0LrQsNGC0L7RgNGW0LIgPT09XG4iKTsKICAgIGZvcihpbnQgaT0wO2k8aWRDb3VudDtpKyspIHByaW50ZigiJTNkIDogJXNcbiIsIGkrMSwgaWRUYWJsZVtpXS5uYW1lKTsKICAgIHByaW50ZigiXG49PT0g0KLQsNCx0LvQuNGG0Y8g0YLQuNC/0ZbQsiA9PT1cbiIpOwogICAgZm9yKGludCBpPTA7aTx0eXBlQ291bnQ7aSsrKSBwcmludGYoIiUzZCA6ICVzXG4iLCBpKzEsIHR5cGVUYWJsZVtpXS5uYW1lKTsKCiAgICBwcmludGYoIlxuPT09INCyKSDQm9C40YHRgtC40L3QsyDRgtGA0LDQvdGB0LvRj9GG0ZbRlyA9PT1cbiIpOwogICAgZm9yKGludCBpPTA7aTx0b2tDb3VudDtpKyspCiAgICAgICAgcHJpbnRmKCJbbGluZSAlZCxjb2wgJWRdICUtOHMgJS0xMHMgKHN0bXQgJWQsIG5lc3QgJWQpXG4iLAogICAgICAgICAgICAgICB0b2tlbnNbaV0ucm93LHRva2Vuc1tpXS5jb2wsCiAgICAgICAgICAgICAgIGNsYXNzTmFtZVt0b2tlbnNbaV0uY2xzXSx0b2tlbnNbaV0ubGV4ZW1lLAogICAgICAgICAgICAgICB0b2tlbnNbaV0uc3RtdE5vLHRva2Vuc1tpXS5uZXN0aW5nKTsKICAgIHJldHVybiAwOwp9Cg==