// 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<NUM_LAB; ++t)
{
if (label_table[t].name[0] == 0)
return t;
if (!strcmp(label_table[t].name, s))
return -2;
}
return -1;
}
char *find_label(char *s)
{
register int t;
for (t = 0; t<NUM_LAB; t++)
if (!strcmp(label_table[t].name, s))
return label_table[t].p;
return'\0';
}
void exec_goto()
{
char *loc;
get_token();
loc = find_label(token);
if (loc == '\0')
serror(7);
else
prog = loc;
}
void label_init()
{
memset(label_table, 0, sizeof(label_table));
}
void print()
{
int answer;
int len = 0, spaces;
char last_delim = '\0';
do
{
get_token();
if (tok == EOL || tok == FINISHED)
break;
if (token_type == QUOTE)
{
printf("%s", token);
len += strlen(token);
get_token();
}
else
{
putback();
get_exp(&answer);
get_token();
len += printf("%d", answer);
}
last_delim = *token;
if (*token == ',')
{
spaces = 8 - (len % 8);
len += spaces;
while (spaces)
{
putchar(' ');
spaces--;
}
}
else{
if ((*token != ';')
&& (tok != EOL)
&& (tok != FINISHED))
serror(0);
}
} while (*token == ';' || *token == ',');
if (tok == EOL || tok == FINISHED)
{
if (last_delim != ';' || last_delim != ',')
putchar('\n');
}
else
serror(0);
}
void input()
{
char var;
int i;
get_token();
if (token_type == QUOTE)
{
printf(token);
get_token();
if (*token != ',')
serror(1);
get_token();
}
else
printf("? ");
var = toupper(*token) - 'A'; //toupper - перетворити до вел. літери tolower - перетворити до мал. літ.
if (var >= 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];
}
Comments