andruhovski icon

SysProg-01-2017

andruhovski | PRO | 10/02/17 09:59:30 AM UTC | 0 ⭐ | 607 👁️ | Never ⏰ | []
C++ |

12.5 KB

|

None

|

0 👍

/

0 👎

// 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