Простой интерпретатор на C

Я сделал простой интерпретатор на C и теперь хочу улучшить свой код.

Вот мой код:

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>

#include "def.h"

int main(int argc, char *argv[])
{
    int i;
    char ch[100];
    char input[100];
    char sinput[100];
    char output[100];
    int while_int;
    if (argv[1] != NULL)
    {
        char *file_extension = strrchr(argv[1], '.');
        if (file_extension == NULL)
        {
            printf("ErrornNo File Extensionn");
        }
        else if (strcmp(file_extension, ".pri") == FALSE)
        {
            FILE *fp = fopen(argv[1], "r");
            fgets(ch, 100, fp);
            fclose(fp);
        }
    }
    do
    {
        if (argv[1] == NULL)
        {
            printf(">>> ");
            scanf("%[^n]%*c", ch);
        }
        if (ch[0] != '@' & argv[1] == NULL)
        {
            while_int = TRUE;
        }
        else
        {
            while_int = FALSE;
        }
        if (ch[0] == '"' & ch[strlen(ch) - 1] == '"')
        {
            if (strlen(ch) == 1 | strlen(ch) == 2)
            {
                printf("ErrornError Code: PRINTLANG.1n");
                ch[0] = '@';
            }
            else
            {
                chh(ch, output, 0, strlen(ch) - 1);
                printf("%sn", output);
                ch[0] = '@';
            }
        }
        if (ch[0] == 'p' & ch[1] == 'r' & ch[2] == 'i' & ch[3] == 'n' & ch[4] == 't')
        {
            if (ch[5] == '(' & ch[strlen(ch) - 1] == ')')
            {
                if (ch[6] == '"' & ch[strlen(ch) - 2] == '"')
                {
                    if (strlen(ch) == 8 | strlen(ch) == 9)
                    {
                        printf("ErrornError Code: PRINTLANG.2n");
                        ch[0] = '@';
                    }
                    else
                    {
                        chh(ch, output, 6, strlen(ch) - 2);
                        printf("%sn", output);
                        ch[0] = '@';
                    }
                }
                else if (ch[6] == 'i' & ch[7] == 'n' & ch[8] == 'p' & ch[9] == 'u' & ch[10] == 't')
                {
                    if (ch[11] == '(' & ch[strlen(ch) - 2] == ')')
                    {
                        if (strlen(ch) == 14)
                        {
                            scanf("%[^n]%*c", input);
                            printf("%sn", input);
                            ch[0] = '@';
                        }
                        else
                        {
                            if (ch[12] == '"' & ch[strlen(ch) - 3] == '"')
                            {
                                if (strlen(ch) == 16)
                                {
                                    printf("ErrornError Code: PRINTLANG.3n");
                                    ch[0] = '@';
                                }
                                else
                                {
                                    chh(ch, output, 12, strlen(ch) - 3);
                                    printf("%s", output);
                                    scanf("%[^n]%*c", input);
                                    printf("%sn", input);
                                    ch[0] = '@';
                                }
                            }
                            else
                            {
                                printf("ErrornError Code: PRINTLANG.4n");
                            }
                        }
                    }
                    else
                    {
                        printf("ErrornError Code: PRINTLANG.5n");
                        ch[0] = '@';
                    }
                }
                else
                {
                    printf("ErrornError Code: PRINTLANG.6n");
                    ch[0] = '@';
                }
            }
            else
            {
                printf("ErrornError Code: PRINTLANG.7n");
                ch[0] = '@';
            }
        }
        else if (ch[0] == 'e' & ch[1] == 'c' & ch[2] == 'h' & ch[3] == 'o')
        {
            if (ch[4] == ' ')
            {
                if (ch[5] == '"' & ch[strlen(ch) - 1] == '"')
                {
                    chh(ch, output, 5, strlen(ch) - 1);
                    printf("%sn", output);
                    ch[0] = '@';
                }
                else
                {
                    printf("ErrornError Code: PRINTLANG.8n");
                    ch[0] = '@';
                }
            }
            else
            {
                printf("ErrornError Code: PRINTLANG.9n");
                ch[0] = '@';
            }
        }
        else
        {
            ch[0] = '@';
        }
    }
    while (while_int);
}

def.h:

#ifndef _DEF_H
# define _DEF_H
#endif

#define TRUE (1 == 1)
#define FALSE (1 == 0)

char *chh(char *ch, char *output, int x, int y)
{
    int i;
    for (i = x + 1; i < y; i++)
    {
        output[i - (x + 1)] = ch[i];
    }
    return output;
}

Ссылка на GitHub

Рекомендуемый вопрос (мой вопрос)

2 ответа
2

Используйте генератор парсера

Поскольку кажется, что вы собираетесь расширить поддерживаемый в настоящее время язык, я не могу рекомендовать вам продолжать писать код синтаксического анализа самостоятельно. Это уже некрасиво, и хотя его можно улучшить, есть общие инструменты доступно, что с учетом описания токенов и грамматики вашего языка сгенерировать код C, необходимый для синтаксического анализа этого языка. Наиболее известны GNU Flex и GNU Bison.

Разделите свою программу на несколько функций

Помимо одной функции в def.h, который на самом деле должен быть сам по себе .c файл, у вас есть все функции внутри main(). Вам следует попытаться разделить свою программу на отдельные функции, каждая из которых выполняет простую задачу. Это упростит чтение и сопровождение кода.

Распечатать полезные сообщения об ошибках

Когда ваш интерпретатор обнаруживает ошибку, он просто печатает:

Error
Error Code: PRINTLANG.n

Где n это какое-то число. Это очень бесполезно. Сообщения об ошибках служат для информирования пользователя о том, что пошло не так. Так что напишите что-нибудь, что сообщит пользователю, что было не так, и, если возможно, также предложите, как они могут исправить проблему. Например, вместо PRINTLANG.1, написать:

Error: empty or unterminated quoted string

Также возьмите за привычку писать сообщения об ошибках на stderr.

    Я предполагаю, что вы учитесь писать код. Итак, чтобы не усложнять, я думаю, вам следует сосредоточиться на разделении кода на уровни абстракции. Если функция становится слишком длинной, разбейте ее на подфункции. Старайтесь, чтобы код функции находился на едином уровне абстракции, избегайте смешивания высокоуровневой и низкоуровневой работы.

    Это искусство, требующее большой практики, чтобы добиться правильного результата. Вместо того, чтобы думать о своем коде как о чем-то, что будет выполнять компьютер, вы должны думать о нем как о чем-то, что прочитает другой человек. Это даст вам правильное мышление.

    Добавление уровней абстракции в ваш код может выглядеть так, как показано ниже. Обратите внимание, как были устранены избыточные переменные. Этот код имеет больше смысла, если вы начнете снизу. Постарайтесь улучшить его, сделав читабельным сверху. Для этого вы можете ввести некоторые комментарии, объясняющие контекст, или вы можете переосмыслить функции, чтобы они были общими, а не специфическими для родителя, вызывающего их в одном точном месте — как сейчас.

    Вы должны потратить столько же времени на то, чтобы ваш код был читабельным, сколько вы потратили времени на то, чтобы он работал правильно.

    Удачного кодирования.

    #include <stdio.h>
    #include <stdlib.h>
    #include <stddef.h>
    #include <string.h>
    
    #include "def.h"
    
    void do_quotes(char* ch)
    {
        char output[100];
    
        if (strlen(ch) == 1 | strlen(ch) == 2)
        {
            printf("ErrornError Code: PRINTLANG.1n");
            ch[0] = '@';
        }
        else
        {
            chh(ch, output, 0, strlen(ch) - 1);
            printf("%sn", output);
            ch[0] = '@';
        }
    }
    
    void do_print_quote(char* ch)
    {
        char output[100];
    
        if (strlen(ch) == 8 | strlen(ch) == 9)
        {
            printf("ErrornError Code: PRINTLANG.2n");
            ch[0] = '@';
        }
        else
        {
            chh(ch, output, 6, strlen(ch) - 2);
            printf("%sn", output);
            ch[0] = '@';
        }
    }
    
    void do_print_input(char* ch)
    {
        char output[100];
        char input[100];
    
        if (ch[11] == '(' & ch[strlen(ch) - 2] == ')')
        {
            if (strlen(ch) == 14)
            {
                scanf("%[^n]%*c", input);
                printf("%sn", input);
                ch[0] = '@';
            }
            else
            {
                if (ch[12] == '"' & ch[strlen(ch) - 3] == '"')
                {
                    if (strlen(ch) == 16)
                    {
                        printf("ErrornError Code: PRINTLANG.3n");
                        ch[0] = '@';
                    }
                    else
                    {
                        chh(ch, output, 12, strlen(ch) - 3);
                        printf("%s", output);
                        scanf("%[^n]%*c", input);
                        printf("%sn", input);
                        ch[0] = '@';
                    }
                }
                else
                {
                    printf("ErrornError Code: PRINTLANG.4n");
                }
            }
        }
        else
        {
            printf("ErrornError Code: PRINTLANG.5n");
            ch[0] = '@';
        }
    }
    
    void do_print(char* ch)
    {
        if (ch[5] == '(' & ch[strlen(ch) - 1] == ')')
        {
            if (ch[6] == '"' & ch[strlen(ch) - 2] == '"')
            {
                do_print_quote(ch);
            }
            else if (ch[6] == 'i' & ch[7] == 'n' & ch[8] == 'p' & ch[9] == 'u' & ch[10] == 't')
            {
                do_print_input(ch);
            }
            else
            {
                printf("ErrornError Code: PRINTLANG.6n");
                ch[0] = '@';
            }
        }
        else
        {
            printf("ErrornError Code: PRINTLANG.7n");
            ch[0] = '@';
        }
    }
    
    void do_echo(char* ch)
    {
        char output[100];
    
        if (ch[4] == ' ')
        {
            if (ch[5] == '"' & ch[strlen(ch) - 1] == '"')
            {
                chh(ch, output, 5, strlen(ch) - 1);
                printf("%sn", output);
                ch[0] = '@';
            }
            else
            {
                printf("ErrornError Code: PRINTLANG.8n");
                ch[0] = '@';
            }
        }
        else
        {
            printf("ErrornError Code: PRINTLANG.9n");
            ch[0] = '@';
        }
    }
    
    int main(int argc, char *argv[])
    {
        char ch[100];
        int while_int;
        if (argv[1] != NULL)
        {
            char *file_extension = strrchr(argv[1], '.');
            if (file_extension == NULL)
            {
                printf("ErrornNo File Extensionn");
            }
            else if (strcmp(file_extension, ".pri") == FALSE)
            {
                FILE *fp = fopen(argv[1], "r");
                fgets(ch, 100, fp);
                fclose(fp);
            }
        }
        do
        {
            if (argv[1] == NULL)
            {
                printf(">>> ");
                scanf("%[^n]%*c", ch);
            }
            while_int = (ch[0] != '@' & argv[1] == NULL);
            if (ch[0] == '"' & ch[strlen(ch) - 1] == '"')
            {
                do_quotes(ch);
            }
            if (ch[0] == 'p' & ch[1] == 'r' & ch[2] == 'i' & ch[3] == 'n' & ch[4] == 't')
            {
                do_print(ch);
            }
            else if (ch[0] == 'e' & ch[1] == 'c' & ch[2] == 'h' & ch[3] == 'o')
            {
                do_echo(ch);
            }
            else
            {
                ch[0] = '@';
            }
        }
        while (while_int);
    }
    

      Добавить комментарий

      Ваш адрес email не будет опубликован. Обязательные поля помечены *