// SysProg01.cpp : Defines the entry point for the console application. // #include "stdafx.h" #define DELIMITER 1 #define VARIABLE 2 #define NUMBER 3 #define COMMAND 4 #define STRING 5 #define QUOTE 6 #define PRINT 7 #define INPUT 8 #define IF 9 #define THEN 10 #define FOR 11 #define NEXT 12 #define TO 13 #define GOTO 14 #define EOL 15 #define FINISHED 16 #define GOSUB 17 #define RETURN 18 #define END 19 #define NUM_LAB 100 #define LAB_LEN 10 #define FOR_NEST 25 #define SUB_NEST 25 #define PROG_SIZE 10240 struct for_stack { int var; //поточний стан int target; //кінцеве значення int step; // крок char* loc; //точка входу в цикл }; struct for_stack fstack[FOR_NEST]; int variables[26] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int token_type; //тип лексеми int tok; //уточнення типу #if _DEBUG char *prog = "10 PRINT \"TEST\"\r\n20 PRINT \"TEST2\"\r\n30 GOSUB 100\r\n40 PRINT \"TEST3\"\r\n50 END\r\n100 PRINT \"ABC\"\r\n110 RETURN"; #else char *prog; #error Реалізуйте завантаження програми #endif char token[256]; //для збереження значень лексем int get_token(void); int isdelim(char c); int look_up(char *s); struct commands { char command[20]; char tok; } table[] = { "print", PRINT, "input", INPUT, "if", IF, "then", THEN, "goto", GOTO, "for", FOR, "next", NEXT, "to", TO, "gosub", GOSUB, "return", RETURN, "end", END, "", END }; struct label { char name[LAB_LEN]; char *p; }; struct label label_table[NUM_LAB]; void print(void); void scan_label(void); void find_eol(void); void exec_if(void); void exec_for(void); void next(void); void fpush(struct for_stack i); struct for_stack fpop(void); int ftos; int gtos; void input(void); void gosub(void); void putback(void); void greturn(void); void label_init(void); char *find_label(char *s); int find_var(char *s); int load_program(char *p, char *fname); int assignment(void); void serror(int error); void gpush(char *s); char *gpop(void); int get_next_label(char *s); int look_up(char *s); int isdelim(char c); int is_space(char s); void get_exp(int *result); void level2(int *result); void level3(int *result); void level4(int *result); void level5(int *result); void level6(int *result); void primitive(int *result); void arith(char o, int *r, int *h); void unary(char o, int *r); void putback(); char *gstack[SUB_NEST]; int _tmain(int argc, _TCHAR* argv[]) { scan_label(); ftos = 0; gtos = 0; do { token_type = get_token(); if (token_type == VARIABLE) { putback(); assignment(); } switch (tok) { case PRINT: print(); break; case IF: exec_if(); break; case FOR: exec_for(); break; case NEXT: next(); break; case INPUT: input(); break; case GOSUB: gosub(); break; case RETURN: greturn(); break; case END: exit(0); } } while (tok != FINISHED); return 0; } int get_token(void) { char *temp; token_type = 0; tok = 0; temp = token; if (*prog == '\0') { *token = 0; tok = FINISHED; return (token_type = DELIMITER); } while (is_space(*prog)) prog++; if (*prog == '\r') { prog += 2; tok = EOL; token[0] = '\r'; token[1] = '\n'; token[2] = 0; return (token_type = DELIMITER); } if (strchr("*+-^/%=;(),><", *prog) != NULL) { *temp = *prog; prog++; temp++; *temp = 0; return (token_type = DELIMITER); } if (*prog == '"') { prog++; while (*prog != '"' && *prog != '\r') *temp++ = *prog++; *temp = 0; prog++; return (token_type = QUOTE); } if (isdigit(*prog)) { while (!isdelim(*prog)) *temp++ = *prog++; *temp = '\0'; return (token_type = NUMBER); } if (isalpha(*prog)) { while (!isdelim(*prog)) *temp++ = *prog++; token_type = STRING; } *temp = '\0'; if (token_type == STRING) { tok = look_up(token); if (!tok) token_type = VARIABLE; else token_type = COMMAND; } return token_type; } int look_up(char *s) { register int i; char *p; p = s; while (*p) { *p = tolower(*p); p++; } for (i = 0; *table[i].command; i++) if (!strcmp(table[i].command, s)) return table[i].tok; return 0; } int isdelim(char c) { if ((strchr(" ;,+-<>/*%^=()", c) != NULL) || c == 9 || c == '\r' || c == 0) return 1; return 0; } int is_space(char c) { if (c == ' ' || c == '\t') return 1; return 0; } int load_program(char *p, char *fname) { FILE *fp; int prg_size; int err = fopen_s(&fp, fname, "rb"); if (err != 0) { fprintf(stderr, "The file was not opened\n"); exit(0); } prg_size = fread(p, PROG_SIZE, sizeof(char), fp); *(p - prg_size - 2) = '\0'; fclose(fp); return 1; } int assignment(void) { int var, value; get_token(); if (!isalpha(*token)) { serror(4); return 0; } var = toupper(*token) - 'A'; get_token(); if (*token != '=') { serror(3); return 0; } get_exp(&value); variables[var] = value; return 0; } void putback() { char *t; t = token; for (; *t; t++) prog--; } void scan_label() { int addr; char *temp; label_init(); temp = prog; get_token(); if (token_type == NUMBER) { strcpy_s(label_table[0].name, LAB_LEN, token); label_table[0].p = prog; } find_eol(); do { get_token(); if (token_type == NUMBER) { addr = get_next_label(token); if (addr == -1 || addr == -2) { (addr == -1) ? serror(5) : serror(6); } strncpy_s(label_table[addr].name, LAB_LEN, token, LAB_LEN-1); label_table[addr].p = prog; } if (tok != EOL) find_eol(); } while (tok != FINISHED); prog = temp; } void find_eol() { while (*prog != '\n' && *prog != '\0') ++prog; if (*prog) prog++; } int get_next_label(char *s) { register int t; for (t = 0; t= 0 && var <= 25) { scanf_s("%d", &i); variables[var] = i; } else { serror(99); } } void gosub() { char *loc; get_token(); if (token_type != NUMBER) { //.... } loc = find_label(token); if (loc == '\0') serror(7); else { gpush(prog); prog = loc; } } void gpush(char *s) { gtos++; if (gtos == SUB_NEST) { serror(12); return; } gstack[gtos] = s; } void greturn() { prog = gpop(); } char *gpop(void) { if (gtos == 0) { serror(13); return 0; } return gstack[gtos--]; } void goto_operator() { char *loc; get_token(); loc = find_label(token); if (loc == '\0') serror(7); else prog = loc; } void get_exp(int *result) { get_token(); if (!(*token)) { serror(2); return; } level2(result); putback(); } void level2(int *result) { char op; int hold; level3(result); while (((op = *token) == '+') || (op == '-')) { get_token(); level3(&hold); arith(op, result, &hold); } } void level3(int *result) { char op; int hold; level4(result); //P1 while (((op = *token) == '*') || (op == '/') || (op == '%')) { get_token(); level4(&hold); //P2 arith(op, result, &hold); } } void level4(int *result) { char op = '\0'; int hold; level5(result); if (*token == '^') { get_token(); level5(&hold); arith('^', result, &hold); } //get_token(); } void level5(int *result) { char op = 0; if ((token_type == DELIMITER) && (*token == '+') || (*token == '-')) { op = *token; get_token(); } level6(result); if (op) unary(op, result); } void level6(int *result) { if ((*token == '(') && (token_type == DELIMITER)) { get_token(); level2(result); if (*token != ')') serror(1); get_token(); } else primitive(result); } void primitive(int *result) { switch (token_type) { case VARIABLE: *result = find_var(token); get_token(); return; case NUMBER: *result = atoi(token); get_token(); return; default: serror(0); } } void arith(char o, int *r, int *h) { int t = 0, ex = 0; switch (o) { case '-': *r = *r - *h; break; case '*': *r = *r * *h; break; case '/': *r = *r / *h; break; case '%': *r = *r % *h; break; case '+': *r = *r + *h; break; case '^': ex = *r; if (*h == 0) { *r = 1; break; } for (int t = 1; t<*h; t++) *r = (*r) * ex; break; } } void exec_if(void) { int x, y, cond; char op; get_exp(&x); //prog--; get_token(); if (!strchr("=<>", *token)) { serror(0); } op = *token; get_exp(&y); prog--; cond = 0; switch (op) { case '=': if (x == y) cond = 1; break; case '<': if (x < y) cond = 1; break; case '>': if (x > y) cond = 1; break; } if (cond) { get_token(); if (tok != THEN) { serror(8); } } else { find_eol(); } } void unary(char o, int *r) { if (o == '-') *r = -*r; } void exec_for(void) { struct for_stack i; int value; get_token(); if (token_type != VARIABLE) { serror(4); return; } i.var = toupper(*token) - 'A'; get_token(); if (*token != '=') { serror(3); return; } get_exp(&value); variables[i.var] = value; get_token(); if (tok != TO) { serror(9); return; } get_exp(&i.target); get_token(); /*if (tok != STEP) { serror(19); return; } get_exp(&i.?????);*/ if (value >= variables[i.var]) { i.loc = prog; fpush(i); } else while (tok != NEXT) get_token(); } void next() { struct for_stack i; i = fpop(); //variables[i.var] += i.step; //+1 variables[i.var] ++; if (variables[i.var] > i.target) return; prog = i.loc; fpush(i); } void fpush(struct for_stack i) { if (ftos > FOR_NEST) { serror(10); return; } fstack[ftos++] = i; } struct for_stack fpop() { ftos--; if (ftos < 0) { serror(11); } return (fstack[ftos]); } void serror(int k) { switch (k) { case 0: printf("Syntaksychna pomylka.\n"); break; case 1: printf("Neparni krugli duzhky.\n"); break; case 2: printf("Pomylka u vyrazi, propuschenyy znak.\n"); break; case 3: printf("Ochikuet'sya znak dorivnue.\n"); break; case 4: printf("Ochikuet'sya zminna.\n"); break; case 5: printf("Tablycyu mitok perepovneno.\n"); break; case 6: printf("Dubluut'sya mitky.\n"); break; case 7: printf("Nevyznachena mitka.\n"); break; case 8: printf("Ochikuet'sya THEN.\n"); break; case 9: printf("Ochikuet'sya TO.\n"); break; case 10: printf("Perevyscheno riven' vkladenosti FOR.\n"); break; case 11: printf("NEXT bez FOR.\n"); break; case 12: printf("Perevyscheno riven' vkladenosti GO SUB.\n"); break; case 13: printf("RETURN bez GO SUB.\n"); break; } exit(1); } int find_var(char *s) { char i = toupper(*s) - 'A'; if (i<0 || i>25) serror(2); return variables[i]; }