fork download
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5.  
  6. #define MAX_ID 1024
  7. #define MAX_TYPES 64
  8. #define MAX_TOKENS 65536
  9.  
  10. typedef enum {
  11. T_IDENT, T_KEYWORD, T_INT_LIT, T_STR_LIT,
  12. T_OP, T_DELIM, T_LPAREN, T_RPAREN,
  13. T_LBRACK, T_RBRACK, T_LBRACE, T_RBRACE,
  14. T_BOOL_LIT
  15. } TokenClass;
  16.  
  17. const char* className[] = {
  18. "IDENT","KEYWORD","INT_LIT","STR_LIT",
  19. "OP","DELIM","LPAREN","RPAREN",
  20. "LBRACK","RBRACK","LBRACE","RBRACE",
  21. "BOOL_LIT"
  22. };
  23.  
  24. const char* keywords[] = {
  25. "list","add","remove","print","if","else","while","for",
  26. "function","return","int","string","bool",
  27. "length","concat","reverse"
  28. };
  29. const int KW_COUNT = 16;
  30.  
  31. typedef struct { char name[128]; } Ident;
  32. typedef struct { char name[32]; } Type;
  33.  
  34. Ident idTable[MAX_ID]; int idCount=0;
  35. Type typeTable[MAX_TYPES]; int typeCount=0;
  36.  
  37. typedef struct {
  38. TokenClass cls;
  39. int indexInClass;
  40. int row, col;
  41. char lexeme[128];
  42. int stmtNo;
  43. int nesting;
  44. } Token;
  45.  
  46. Token tokens[MAX_TOKENS]; int tokCount=0;
  47.  
  48. int isKeyword(const char* s) {
  49. for (int i=0;i<KW_COUNT;i++) if (!strcmp(s, keywords[i])) return 1;
  50. return 0;
  51. }
  52. int isBoolLiteral(const char* s){ return (!strcmp(s,"true")||!strcmp(s,"false")); }
  53.  
  54. int addIdent(const char* s){
  55. for (int i=0;i<idCount;i++) if(!strcmp(idTable[i].name,s)) return i+1;
  56. strcpy(idTable[idCount].name,s); idCount++; return idCount;
  57. }
  58. int ensureType(const char* s){
  59. for (int i=0;i<typeCount;i++) if(!strcmp(typeTable[i].name,s)) return i+1;
  60. strcpy(typeTable[typeCount].name,s); typeCount++; return typeCount;
  61. }
  62.  
  63. void emit(TokenClass c, int idx, int row, int col, const char* lex, int stmt, int nest){
  64. tokens[tokCount].cls=c;
  65. tokens[tokCount].indexInClass=idx;
  66. tokens[tokCount].row=row;
  67. tokens[tokCount].col=col;
  68. tokens[tokCount].stmtNo=stmt;
  69. tokens[tokCount].nesting=nest;
  70. strncpy(tokens[tokCount].lexeme, lex, 127);
  71. tokCount++;
  72. }
  73.  
  74. int main(int argc, char** argv){
  75. // Заповнюємо таблицю типів базовими типами
  76. ensureType("int"); ensureType("string");
  77. ensureType("bool"); ensureType("list");
  78.  
  79. FILE* f = stdin;
  80. if (argc>1){ f=fopen(argv[1],"r"); if(!f){ perror("open"); return 1; } }
  81.  
  82. int row=1,col=0;
  83. int c, peek;
  84. char buf[256];
  85. int stmtNo=0, nesting=0;
  86.  
  87. while ((c=fgetc(f))!=EOF){
  88. if (c=='\n'){ row++; col=0; continue; }
  89. col++;
  90. if (isspace(c)) continue;
  91.  
  92. // Коментарі
  93. if (c=='/'){
  94. peek=fgetc(f);
  95. if (peek=='/'){ while((c=fgetc(f))!=EOF && c!='\n'); row++; col=0; continue; }
  96. else if (peek=='*'){ int prev=0;
  97. while((c=fgetc(f))!=EOF){ if(c=='\n'){ row++; col=0; }
  98. if(prev=='*' && c=='/') break; prev=c; }
  99. continue;
  100. } else { ungetc(peek,f); }
  101. }
  102.  
  103. // Ідентифікатор / ключове слово / булевий літерал
  104. if (isalpha(c)||c=='_'){
  105. int k=0; buf[k++]=(char)c;
  106. while((peek=fgetc(f))!=EOF && (isalnum(peek)||peek=='_')){
  107. buf[k++]=(char)peek;
  108. }
  109. if (peek!=EOF) ungetc(peek,f);
  110. buf[k]='\0';
  111. if (isBoolLiteral(buf)){
  112. emit(T_BOOL_LIT,0,row,col-k+1,buf,stmtNo,nesting);
  113. } else if (isKeyword(buf)){
  114. if (!strcmp(buf,"int")||!strcmp(buf,"string")||
  115. !strcmp(buf,"bool")||!strcmp(buf,"list")) ensureType(buf);
  116. emit(T_KEYWORD,0,row,col-k+1,buf,stmtNo,nesting);
  117. } else {
  118. int id=addIdent(buf);
  119. emit(T_IDENT,id,row,col-k+1,buf,stmtNo,nesting);
  120. }
  121. continue;
  122. }
  123.  
  124. // Ціле число
  125. if (isdigit(c)){
  126. int k=0; buf[k++]=(char)c;
  127. while((peek=fgetc(f))!=EOF && isdigit(peek)) buf[k++]=(char)peek;
  128. if (peek!=EOF) ungetc(peek,f);
  129. buf[k]='\0';
  130. emit(T_INT_LIT,0,row,col-strlen(buf)+1,buf,stmtNo,nesting);
  131. continue;
  132. }
  133.  
  134. // Рядок
  135. if (c=='"'){
  136. int k=0; int startCol=col; int closed=0;
  137. while((peek=fgetc(f))!=EOF){
  138. col++;
  139. if (peek=='\n'){ row++; col=0; }
  140. if (peek=='"'){ closed=1; break; }
  141. buf[k++]=(char)peek;
  142. }
  143. buf[k]='\0';
  144. if (!closed) fprintf(stderr,"LEXERR: Unterminated string at %d:%d\n",row,startCol);
  145. else emit(T_STR_LIT,0,row,startCol,buf,stmtNo,nesting);
  146. continue;
  147. }
  148.  
  149. // Оператори, дужки, роздільники
  150. buf[0]=(char)c; buf[1]='\0';
  151. switch(c){
  152. case '+': case '-': case '*': case '/': case '=':
  153. case '<': case '>': emit(T_OP,0,row,col,buf,stmtNo,nesting); break;
  154. case ',': case ';':
  155. emit(T_DELIM,0,row,col,buf,stmtNo,nesting);
  156. if(c==';') stmtNo++; break;
  157. case '(': emit(T_LPAREN,0,row,col,buf,stmtNo,nesting); break;
  158. case ')': emit(T_RPAREN,0,row,col,buf,stmtNo,nesting); break;
  159. case '[': emit(T_LBRACK,0,row,col,buf,stmtNo,nesting); break;
  160. case ']': emit(T_RBRACK,0,row,col,buf,stmtNo,nesting); break;
  161. case '{': nesting++; emit(T_LBRACE,0,row,col,buf,stmtNo,nesting); break;
  162. case '}': emit(T_RBRACE,0,row,col,buf,stmtNo,nesting); nesting--; break;
  163. default: fprintf(stderr,"LEXERR: Unknown symbol '%c' at %d:%d\n",c,row,col);
  164. }
  165. }
  166.  
  167. // Вивід результатів
  168. printf("=== а) Реорганізований текст ===\n");
  169. for(int i=0;i<tokCount;i++)
  170. printf("(%s,%d) ", className[tokens[i].cls], tokens[i].indexInClass);
  171. printf("\n\n=== б) Таблиця ідентифікаторів ===\n");
  172. for(int i=0;i<idCount;i++) printf("%3d : %s\n", i+1, idTable[i].name);
  173. printf("\n=== Таблиця типів ===\n");
  174. for(int i=0;i<typeCount;i++) printf("%3d : %s\n", i+1, typeTable[i].name);
  175.  
  176. printf("\n=== в) Листинг трансляції ===\n");
  177. for(int i=0;i<tokCount;i++)
  178. printf("[line %d,col %d] %-8s %-10s (stmt %d, nest %d)\n",
  179. tokens[i].row,tokens[i].col,
  180. className[tokens[i].cls],tokens[i].lexeme,
  181. tokens[i].stmtNo,tokens[i].nesting);
  182. return 0;
  183. }
  184.  
Success #stdin #stdout 0.01s 5288KB
stdin
Standard input is empty
stdout
=== а) Реорганізований текст ===


=== б) Таблиця ідентифікаторів ===

=== Таблиця типів ===
  1 : int
  2 : string
  3 : bool
  4 : list

=== в) Листинг трансляції ===