#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <ctype.h>
#include <time.h>
#define IN_BASE 8 //входная СИ
#define OUT_BASE 12 //выходная СИ
#define COM 15 //кол-во комманд
#define R1 Reg[*ar1-'A']
#define R2 Reg[*ar2-'A']
#define R3 Reg[*ar3-'A']
#define R4 Reg[*ar4-'A']
char* com[COM] = { //глобальный массив с названиями комманд
"IN" //№1
, "OUT" //№2
, "AND" //№3
, "OR" //№4
, "XOR" //№5
, "EQV" //№6
, "NOR" //№7
, "NAND" //№8
, "IMP" //№9
, "COIMP" //№10
, "BIMP" //№11
, "COBIMP" //№12
, "EQUIVALEN" //№13=№6!
, "IMPLICATION" //№14=№9!
, "MYCOMMAND" //№15
};
char**comPtr = com;
char* sErrors[] = { //глобальный массив с ошибками
""
, "Входной файл не удалось открыть!\n" //№1
, "Вложенные комментарии запрещены!\n" //№2
, "Комментарий уже закрыт, но еще не начался!\n" //№3
, "Файл закончился, но комментарий не закрыт!\n" //№4
, "Инструкция не найдена!\n" //№5
, "Файл трассировки не удалось открыть!\n" //№6
, "Аргумент должен быть буквой!\n" //№7
, "Аргумент должен состоять из одной буквы!\n" //№8
, "Неверно введено число!\n" //№9
, "Нет запятой, разделяющей аргументы!\n" //№10
, "Второй аргумент не найден или он не буква!\n" //№11
, "Лишние знаки в бинарной конструкции!\n" //№12
, "Буфер не содержит инструкций!\n" //№13
, "Фатальная ошибка: недопустимые символы для записи комманд!\n"//№14
, "Значение должно быть цифрой!\n" //№15
, "\n" //№16
, "Слишком много ошибок!\n" //№17
, "Неизвестная инструкция!\n" }; //№18
char** p=sErrors;
unsigned Reg[26]; //массив с регистрами
char *fp = "C:\\in.txt";
char *fTr = "C:\\out.txt";
void Fatal_Error(int num, char** p, char* s)
{
FILE *fT;
fT = fopen(fTr, "a");
printf("Фатальная ошибка №%d : %s%s", num, p[num], s);
fprintf(fT, "Фатальная ошибка №%d : %s%s", num, p[num], s);
exit(EXIT_FAILURE);
}
void Error(int num, char** p, char* s) //функция, пишушая ошибку
{
FILE *fT;
fT = fopen(fTr, "a");
printf("Ошибка №%d : %s%s\n",num, p[num],s);
fprintf(fT,"Ошибка №%d : %s%s\n", num, p[num], s);
//fclose(fT);
//exit(EXIT_FAILURE);
}
char* AntiGorner(int num, int BASE_OUT)
{
static char result[BUFSIZ] = { 0 };
char* res = result + sizeof(result)-1;
int base = BASE_OUT;
while (num)
{
*--res = (num%base <= 9) ? (num%base+'0') : (num%base+'A'-10);
num = (num / base);
}
if (!*res) res = "0\0"; //если результат нулевой, чтобы строка не была пустой
return res;
}
int argument_input(const char* ar1)
{
FILE *fT;
fT = fopen(fTr, "a");
char integer[BUFSIZ] = { 0 };
char*n = integer;
unsigned result = 0;
int base = IN_BASE,i,count,fatals=0;
do //-----
{
count = 0;
printf("-==> %c = ", *ar1); //вводим значение регистра
scanf("%s", &integer);
fprintf(fT, "Введенно значение %s(8) для регистра %c\n", integer, *ar1);
for (i = 0; i < sizeof(integer)-1; i++) //работаю с буфером содержащим число
{
if (!(integer[i] == NULL))
if (isdigit(integer[i])) //если элемент массива цифра
{
if ((integer[i] - '0') >= IN_BASE) // если цифра числа больше системы исчисления - ошибка!
{
Error(9, p, "");
count++;
}
}
else
{
Error(15, p, "");
count++;
}
}
if (count > 0) ++fatals;
if (fatals >= 5) Fatal_Error(17, p, "");
}
while (count>0); //----------
while (*n)
{
//if (base <= *n)
// Error(9, p, "");
//else
result = isdigit(*n) ? (result*base + (*n++) - '0') : (result*base + toupper(*n++) - 'A' + 10);
}
return(result);
}
int argument_output(const char* ar1)
{
FILE *fT;
fT = fopen(fTr, "a");
printf("%c=%X(16)=%o(8)=%s(12)\n",*ar1, R1, R1, AntiGorner(R1, OUT_BASE));
fprintf(fT, "%c=%X(16)=%o(8)=%s(12)\n",* ar1, R1, R1, AntiGorner(R1, OUT_BASE));
return 0;
}
int main()
{
FILE *fI=0,*fT=0;
int inComment = 0; //состояние в многострочном комментарии 0-НЕТ, 1-ДА
int k = 0;
char c, buf[BUFSIZ] = {0}, *b = buf; //буфер и указатель на него
char *ar1 = NULL, *ar2 = NULL, *ar3 = NULL, *ar4 = NULL;
setlocale(LC_ALL, "Russian");
printf("ИНТЕРПРЕТАТОР\n\n");
if (!(fT = fopen(fTr, "a"))) Error(6, p, fTr);
else
{
time_t t;
time(&t);
fprintf(fT, "||_________________________________________________________||\n");
fprintf(fT, " Время запуска программы: %s\n\n", ctime(&t));
//fclose(fT);
}
fprintf(fT,"\nИНТЕРПРЕТАТОР\n\n");
if (!(fI = fopen(fp, "r"))) Error(1, p, fp);
else
{
while (!feof(fI)) //пока не конец файла
{
c = fgetc(fI); //посимвольно читаем
if (c == '{')
{
if (inComment) Fatal_Error(2, p, ""); //вызов ошибки вложенного комментария
else inComment = 1;
}
if (!inComment) //итерация происходит только тогда, когда мы не в комменте
{
if (c == '#') while (c != '\n') c = fgetc(fI); //переходим на новую строку, если это однострочный комментарий
if (!(isspace(c)) && c != ';' && c != EOF)
*b++ = toupper(c); //записываем символ в буфер, если это не знак препинания, ; или -1
if (c == ';')
{
*b = 0; //если встретился знак конца комманды, то закрываем буфер
printf("Содержимое буфера: [%s]\n", buf);
fprintf(fT, "Содержимое буфера: [%s]\n", buf);
b = buf;
for (comPtr = com; comPtr - com < COM; comPtr++) //ищем команду
if (strstr(buf, *comPtr) == buf) break;
if ((k = comPtr - com) == COM) Fatal_Error(5, p, ""); //не нашли комманду
printf("Найдена комманда {%s} номер: %d\n", com[k], k + 1);
fprintf(fT, "Найдена комманда {%s} номер: %d\n", com[k], k + 1);
if (!isalpha(*(ar1 = buf + strlen(*comPtr)))) Fatal_Error(7, p, ""); //
if (k < 2) if (*(ar1 + 1)) Fatal_Error(8, p, ""); // проверки на правильность введенных комманд
if (k == 14) // условие для индивидуального задания
{
ar2 = ar1 + 1;
ar3 = ar2 + 1;
ar4 = ar3 + 1;
}
else
{
if (k >= 2)
{
if ((*(ar2 = ar1 + 1) != ',')) Fatal_Error(10, p, "");
if (!isalpha(*++ar2)) Fatal_Error(11, p, "");
if (*(ar2 + 1)) Fatal_Error(12, p, "");
}
}
switch (k) //выполнение операций
{
case 0: //IN
R1=argument_input(ar1);
break;
case 1: //OUT
argument_output(ar1);
break;
case 2: //AND
R1 &= R2;
break;
case 3: //OR
R1 |= R2;
break;
case 4: //XOR
R1 ^= R2;
break;
case 5: //EQV
//R1 = R1&R2 | ~R1&~R2;
R1 = (!R1 | R2)&(R1 | !R2);
break;
case 6: //NOR(Пирс)
R1 = !(R1 | R2);
break;
case 7: //NAND(Шеффер)
R1 = !(R1 & R2);
break;
case 8: //IMP
R1 = (!R1) | R2;
break;
case 9: //COIMP
R1 = R1 | (!R2);
break;
case 10: //BIMP
R1 = (!R2) | R1;
break;
case 11: //COBIMP
R1 = R2 | (!R1);
break;
case 12: //EQUIVALEN=EQV
R1 = (!R1 | R2)&(R1 | !R2);
break;
case 13: //IMPLICATION=IMP
R1 = (!R1) | R2;
break;
case 14: //ИНДИВИДУАЛЬНОЕ ЗАДАНИЕ
R1 = R1|((!R2&R3)&R4);
break;
default:
Fatal_Error(18, p, "");
break;
}
}
}
if (c == '}')
{
if (!inComment) Fatal_Error(3, p, ""); // выход из комментария
else inComment = 0;
}
if (c == EOF && inComment) Fatal_Error(4, p, ""); // файл закончился,но мы еще в комментарии
if (c != '{' && c != '}' && !(isspace(c)) && c != EOF &&c != '#' && c != ';' && !(isalnum(c)) && c != '['&& c != ']' && c != ',') Fatal_Error(14, p, "");
//проверка допустимости символа
}
if (sizeof(buf) == 0) Fatal_Error(13, p, ""); // что-то не работает
}
return 0;
}